diff --git a/changelog b/changelog index abaa6e5..43d7ab2 100644 --- a/changelog +++ b/changelog @@ -35,9 +35,23 @@ export (QQ's a zone into a tarball) Xlist (mlist, olist, rlist, zlist, slist, tlist, qlist) (lots of major bugfixes too) @ +[Mar 31 2012] - Vatiken + improve: updated some of the documents. + feature: added the 'whirlwind' skill as a event/list template + feature: protocol system now can be deactivated thru cedit + improve: 256 to ANSI conversions changed to reflect the new colouring scheme + feature: added blink, underline, bold, reverse and '@' to the protocol system +[Mar 25 2012] - Vatiken + feature: whois now lists protocol informations when used by an immortal + improve: proc_colors() has been removed, and tbaMUD has been made backwards compatible for + systems still using '@' symbols for colour. + feature: added underline, bold, reverse, and flashing text to the protocol system. + bug: Fixed a glitch within protocol.h that had defines differing from similar tbaMUD defines. + feature: added oset() to allow modification of individual objects through commands or dg_scripts. + improve: Adjusted protocolinput() and processinput() to be more efficient. + bug: Fixed major leak in the history system [Feb 12 2012] - Vatiken bug: do_score, changed level 30 to LVL_IMMORT - idea: Mortals can't see immortals levels bug: the NOHASSLE flag allows imms to carry unlimited weight idea: dexterity now affects whether a character gets the first hit idea: advance to immortal now sets hunger/thirst to -1 diff --git a/doc/ProtocolSystem.txt b/doc/ProtocolSystem.txt new file mode 100644 index 0000000..986f1dc --- /dev/null +++ b/doc/ProtocolSystem.txt @@ -0,0 +1,547 @@ +/****************************************************************************** + Protocol snippet by KaVir. Released into the Public Domain in February 2011. + + Version 6: 16-Nov-2011. The changes are listed at the end of this file. + ******************************************************************************/ + +There are no licence conditions or restrictions to worry about. So feel free +to copy whatever you need, or just use it as a reference if you prefer. + +This was originally just supposed to be an MSDP snippet, but I got a little +carried away and ended up adding several other features as well. Thanks go to +Donky for inspiring me to start playing with protocols, and to Scandum for +creating the specifications for MSDP and MSSP (and also for introducing me to +XTerm 256 colours). I'd also like to thank Tijer and Squiggle for testing the +snippet and providing me with feedback, and to Bryantos for porting the snippet +to a couple of other codebases, and pointing out a missing statement in the +installation instructions. Tyche drew my attention to the problem of broken +packets, while the MSSP table was updated in version 5 following feedback from +Rarva.Riendf on MudBytes. Version 6 contains a minor bugfix and clarification +for using MCCP based on feedback from Jindrak. + +I've included instructions for adding the snippet to Diku/Merc, as it was first +tested on Tijer's GodWars mud, but the snippet itself is codebase-neutral and +should be fairly easy to use for any mud written in C. It should take around +5-10 minutes to install in most muds, as long as you know where the hooks need +to go (see the appropriate INSTALL file for details). + +The goal was to produce something that's easy to add and easy to use. It's not +exactly optimised for performance, but it shouldn't cause any problems, and the +REPORTABLE option makes MSDP fairly light on bandwidth. + +In order to make the snippet as easy as possible to add, I made it greedy. If +you were using other protocols, they'll just stop working, as the snippet will +eat all the negotiation sequences. Fixing this is a pretty simple job though, +you just need to call your code from within the snippet's negotiation functions. + +/****************************************************************************** + So what does it do? + ******************************************************************************/ + +The snippet offers the following features: + +Out-of-band communication between mud and client: Clients can choose either +MSDP or ATCP to transmit data to and from the mud. This is done invisibly, +allowing you to update energy bars, icons, maps, etc, without anything being +displayed in the text window. These are the same protocols I used for the +MUSHclient and Mudlet GUIs described on my blog: http://godwars2.blogspot.com + +Extended colours: Allows you to embed XTerm 256 colours in strings (including +help files, room descriptions, etc). Automatically downgrades to the best-fit +ANSI colour for clients that don't support extended colours. + +Client detection: Allows you to view the name (and version when available) of +the clients used by each of your players, see which protocols they support, and +track the current size of their screen. + +Clickable links: Allows you to embed clickable MXP links in strings (including +help files, room descriptions, etc). Automatically strips links before sending +them to clients that don't support MXP. + +Unicode support: Allows you to embed unicode characters within regular ASCII +strings, and provide an alternative ASCII sequence that will be automatically +substituted for clients that don't support UTF-8. + +MSSP: Provides information about your mud to crawlers. This is currently only +used by sites such as MudBytes and MudStats, but could in theory be used for +automatically generating and updating entire mud lists. + +Sound support: Provides an extremely simple mechanism for sending sounds via +MSDP or ATCP, with an automatic fallback for clients that only support MSP. +You will need to provide your own soundpack of course! + +/****************************************************************************** + How do I add the snippet to my mud? + ******************************************************************************/ + +1. Follow the installation instructions in the INSTALL.TXT file. + +2. Edit MUD_NAME in protocol.h, replacing "Unknown MUD" with your mud name. + +3. Make sure the first section of protocol.c uses the correct headers and + functions for your mud. + +/****************************************************************************** + How do I add a new MSDP variable? + ******************************************************************************/ + +In protocol.h, add your new variable to the variable_t enum. + +In protocol.c, add your new variable to the VariableNameTable[]. This needs +to be in the same order as the enum (you'll get a runtime warning if it isn't). + +Add a call to either MSDPSetString() or MSDPSetNumber() whenever the variable +might change. If the variable could be changed in multiple places, you can +just add the call to msdp_update() instead. + +/****************************************************************************** + I need to send my MSDP variable immediately, not once per second! + ******************************************************************************/ + +You can call MSDPUpdate() after setting your variables, and it will immediately +send them all to the player. If you only want to flush a single variable, you +can use MSDPFlush() instead - however, as with MSDPUpdate(), it will only send +variables that are reportable and have changed. + +/****************************************************************************** + The MSDP_GOLD variable reports a negative number! + ******************************************************************************/ + +The snippet uses ints, which are usually 32 bits. If you're using 64 bit long +long ints for certain things (such as gold), then you should either store them +in MSDP string variables, or change the snippet to use long long ints. + +Note that this won't effect your character, it's only the MSDP variable that +overflows. It will give inaccurate information on your GUI, but players won't +actually lose any gold, so don't panic! + +/****************************************************************************** + The snippet is revealing my vnums! Those are supposed to be top secret! + ******************************************************************************/ + +I'm not quite sure why people are so protective about revealing vnums, but many +are. If you don't want to reveal them then you could have MSDP_ROOM_VNUM only +update for imms, or even remove it entirely. However if you wish to support +the automappers that many major clients offer, you really need to provide your +players with some way to uniquely identify their current room, and vnums are +the easiest way of doing it. + +If you don't want people mapping certain areas (such as mazes), then just send +a vnum of '0' when in those areas. You'll need a flag for this if you don't +have one already. + +/****************************************************************************** + My mud previously supported MCCP, but it's stopped working! + ******************************************************************************/ + +The snippet intercepts and extracts all negotiation requests. You will need to +edit protocol.h and uncomment USING_MCCP, then update the CompressStart() and +CompressEnd() functions in protocol.c to call whatever functions you normally +use for starting and ending compression. + +If you don't yet support MCCP and wish to, there are snippets available. Jobo +has some on his website here: http://www.dystopiamud.dk/snippets.php + +MCCP increases the memory and CPU usage of your mud, but also gives significant +bandwidth savings. The exact savings will vary, but you can generally expect +your bandwidth to be reduced to about 20% of its previous amount. + +Please note that MCCP1 is obsolete, and should not be used. All references to +MCCP throughout this snippet refer to MCCP2 (telnet option 86). + +If you also support copyover/hotreboot, please read the next section as well. + +/****************************************************************************** + All the protocol information vanishes after I do a copyover/hotreboot! + ******************************************************************************/ + +Some muds use an exec() function to replace the current process with a new one, +effectively rebooting the mud without shutting it down. The problem with this +is that the client can't detect it, and because clients need to protect against +negotiation loops they may end up ignoring your attempts to renegotiate. + +Therefore in order to store the data across reboots, you need to save it when +you do the copyover, and then load it again afterwards. + +The snippet offers CopyoverSet() and CopyoverGet() functions to make this a +bit easier. When writing descriptors to the temporary file in your copyover +code, add an extra "%s" to each row and copy the string from CopyoverGet() into +it. Then when you load the file again after the copyover, pass the string back +into CopyoverSet(), and it'll restore the settings. + +Note that this won't save the client name and version. It's recommend that you +instead save these in the player file (this means you can grep through player +files to collect client usage statistics, which can be quite useful). + +If you do start saving things in the player file, once again be particularly +careful about the malloc/str_dup free/free_string thing. If you mix them you +may end up with some nasty bugs that are hard to track down. As I mentioned +earlier, it's well worth going through the snippet and making sure it uses +the same functions as the rest of your mud. + +Note also that CopyoverSet() calls CompressStart(), while CopyoverGet() calls +CompressEnd(). So if you're using both copyover and MCCP, you shouldn't need +to manually switch compression off and back on when doing a copyover, it should +be done for you automatically. + +/****************************************************************************** + None of the official ATCP variables work! + ******************************************************************************/ + +This snippet primarily uses MSDP for transmitting data. Unfortunately not all +clients support MSDP, so I offer an alternative - you can use ATCP instead, +with the MSDP variables treated as if they were a custom ATCP package. + +This is really just a workaround. The muds that originally used ATCP are now +migrating over to GMCP, so I'm just "borrowing" their old telnet option. My +workaround doesn't break the ATCP specification (because the MSDP variables all +go into their own package), but neither does it implement the official options. + +If you actually want full ATCP, I'd suggest implementing GMCP instead. + +/****************************************************************************** + Why don't you support GMCP/ZMP/102/etc? + ******************************************************************************/ + +Because the original intent of this snippet was to add MSDP support. I got a +bit carried away, and ended up adding various other features that I felt could +improve the user interface, but the main focus of the snippet is still MSDP. + +/****************************************************************************** + How do I view/modify information about the clients my players are using? + ******************************************************************************/ + +All of the data is stored in the protocol structure, it can be read and changed +just like any other data. For example ScreenWidth and ScreenHeight are simple +integers, while client name and version are MSDP strings. You can view the +full list of options in the protocol.h file. + +An IMPORTANT word of warning though: + +Although I've added a small section at the top of protocol.c to make it easier +to integrate into Diku/Merc derivatives, the snippet is designed to be codebase +independent. It has its own functions and its own types, and in particular it +uses the standard C malloc() and free() functions for strings. + +If you use this in a Diku you're probably using str_dup() and free_string() for +strings. Well whatever you do, do NOT mix and match. If you allocate memory +with str_dup() you MUST free it with free_string() - and if you allocate it +with malloc(), you MUST free it with free(). + +In fact you should probably go through the snippet and change it to use the +same functions as the rest of your mud for allocating and freeing memory. +Update the types as well, and use your own equivalent of MatchString(), etc. + +/****************************************************************************** + How do I use sound? + ******************************************************************************/ + +Place a call to SoundSend() in your code. You should do this before sending +the associated message, because when sending an MSP trigger there is no newline +(you could in theory add one to the SoundSend() function, but then the user +would see a blank line every time they received a sound). + +The client can enable sound through ATCP/MSDP by setting SOUND to 1. If the +client supports ATCP or MSDP, then these will be used to send out-of-band sound +triggers to the client, which can then be played using a plugin or script. + +For other clients, you will need to provide a command for switching sound on +and off. If the bSound variable in the protocol structure is set to true, and +the client doesn't support ATCP or MSDP, then the snippet will send an old +MSP-style in-band sound trigger. + +If a client is using MSP sound triggers, then any text sequences of "!!SOUND(" +sent to them will be instead be displayed as "!?SOUND(", so that players can't +trigger sounds through chats, tells, etc. + +/****************************************************************************** + How do I update the MSSP fields? + ******************************************************************************/ + +Edit protocol.c and do a text search for "MSSPTable". Remove the comments from +around the variables you wish to use, and fill in the fields according the MSSP +specification, which you can read here: http://tintin.sourceforge.net/mssp/ + +The "NAME" should already be defined if you've edited MUD_NAME in protocol.h, +while PLAYERS and UPTIME will be calculated for you automatically. + +/****************************************************************************** + How do I use extended colour? + ******************************************************************************/ + +The special character used to indicate the start of a colour sequence is '\t' +(i.e., a tab, or ASCII character 9). This makes it easy to include in help +files (as you can literally press the tab key) as well as strings (where you +can use "\t" instead). However players can't send tabs (on most muds at +least), so this stops them from sending colour codes to each other. + +The predefined colours are: + + n: no colour (switches colour off) + r: dark red R: bright red + g: dark green G: bright green + b: dark blue B: bright blue + y: dark yellow Y: bright yellow + m: dark magenta M: bright magenta + c: dark cyan C: bright cyan + w: dark white W: bright white + o: dark orange O: bright orange + +/* Vatiken Additions */ + p: dark pink P: bright pink + +: bold -: blink + _: underline =: reverse + *: The '@' Symbol 1: Primary Colour + 2: Secondary Colour 3: Tertiary Colour + +So for example "This is \tOorange\tn." will colour the word "orange". You can +add more colours by updating the switch statement in ProtocolOutput(), and if +you're using your own colour code, it can use extended colours in the same way. + +It's also possible to explicitly specify an RGB value, by including a four +character colour sequence within square brackets, eg: + + This is a \t[F010]very dark green foreground\tn. + +Or: + + This is a \t[B210]dark brown background\tn. + +The first character is either 'F' for foreground or 'B' for background. The +next three characters are the RGB (red/green/blue) values, each of which must +be a digit in the range 0 (very dark) to 5 (very light). + +Finally, it's also possible to retrieve the colour code directly by calling the +ColourRGB() function. This uses a static buffer, so make sure you copy the +result after each call, don't do a sprintf() with multiple ColourRGB() calls. + +Note that sending extended colours to a terminal that doesn't support them can +have some very strange results. The snippet therefore automatically downgrades +to the best-fit ANSI colour for users that don't support extended colours. + +Because there is no official way to detect support for extended colours, the +snippet tries to work it out indirectly, erring on the side of caution. If the +b256Support variable in the protocol structure is set to "eSOMETIMES", that +means some versions of this client are known to support extended colour - you +will need to ask the user, and then set eMSDP_XTERM_256_COLORS to 1 (or they +can do this themselves through MSDP/ATCP). + +/****************************************************************************** + How do I use unicode characters? + ******************************************************************************/ + +Unicode characters can be displayed in a similar way to colour, using square +brackets to provide both a unicode value and an ASCII substitute. For example: + + \t[U9814/Rook] + +The above will draw a rook (the chess piece - unicode value 9814) if the client +supports UTF-8, otherwise it'll display the text "Rook". + +As with extended colour, support for UTF-8 is detected automatically - in this +case using the CHARSET telnet option. However it's not possible to detect if +their font includes that particular character, or even if they're actually +using a unicode font at all, so some care will need to be taken. + +A free unicode font that I've found good is Fixedsys Excelsior, which you can +download from here: http://www.fixedsysexcelsior.com/ + +Also of interest: http://en.wikipedia.org/wiki/List_of_Unicode_characters + +/****************************************************************************** + How do I use clickable MXP links? + ******************************************************************************/ + +You can add MXP tags in the same way as colour and unicode. The easiest and +safest way to do this is via the ( and ) bracket options. For example: + + From here, you can walk \t(north\t). + +This will turn the word "north" into a clickable link - you can click on it to +execute the "north" command. + +However it's also possible to include more explicit MXP tags, like this: + + The baker offers to sell you a \tpie\t. + +As with the extended colour, MXP tags will be automatically removed if the user +doesn't support MXP - but it's very important you remember to close the tags. + +In theory you could also use other MXP options, such as graphics and sound, but +be aware that MXP is implemented very inconsistently across clients - you'd be +better off using MSDP instead. If you do play with other MXP options, the +pMXPVersion variable in the protocol structure will tell you which version of +MXP the client is using, and you can use MXPSendTag() with the "" tag +to find out exactly which options they support. You can also embed another +tag within strings to indicate which version of MXP is required: + + \t[X1.0]Special MXP data + +In the above example, "\t[X1.0]" temporarily blocks MXP if the client is using +a version of MXP below 1.0. The block only applies to the next MXP tag, after +that it is automatically cleared. + +It's worth noting that MXP also supports 24-bit colour, which you may want to +investigate. Personally I've found that 256 colours are more than enough. + +/****************************************************************************** + How do I use the Mudlet autoinstaller for my custom GUI? + ******************************************************************************/ + +Uncomment MUDLET_PACKAGE at the top of protocol.h, and replace the URL with the +one for your Mudlet package. This should be a zip file containing one script +(an XML file) and a folder containing whatever graphics and/or sound your GUI +uses. You may wish to rename the file from ".zip" to ".mpackage" to make it +clear it's a Mudlet package, although this isn't strictly necessary. + +If you update your GUI you will also need to update the version number so that +Mudlet knows it needs to download a newer version. The "1" before the package +name represents the version number, so simply increment it by 1. + +/****************************************************************************** + Your snippet thinks my client doesn't support X, but actually it does! + ******************************************************************************/ + +I've covered what I could, but some of these things (particularly XTerm 256 +colour) are difficult to detect, so there will be clients that I've missed. + +If you're a developer on a mud that uses this snippet, it should be fairly easy +to add new clients to the list - but you should also add some in-game commands +allowing players to manually switch the various options on and off. + +If you're a client developer, you could add MSDP to your client and use the +configurable variables to switch on XTerm 256 colour, UTF-8, etc. + +/****************************************************************************** + My hosting service uses mudcheck.pl, and it keeps killing my mud! + ******************************************************************************/ + +The mudcheck script checks the first line it receives after connecting, which +is now a negotiation sequence. You need to send a newline (or whatever the +script is checking for) first. + +Add another Write() to the ProtocolNegotiate() function: + +void ProtocolNegotiate( descriptor_t *apDescriptor ) +{ + static const char DoTTYPE [] = { (char)IAC, (char)DO, TELOPT_TTYPE, '\0' }; + Write(apDescriptor, "\n"); /* <--- Add this line */ + Write(apDescriptor, DoTTYPE); +} + +/****************************************************************************** + I already added an older version, what do I need to change to update? + ******************************************************************************/ + +Ideally you should diff the old protocol.h and protocol.c against the new ones +to see exactly what has changed. At the very least, have a brief look to give +yourself a general idea. You should also make a backup of your old stuff. + +At the top of your protocol.c is a section with mud-specific stuff, you will +almost certainly have changed the #include, the Write() and the ReportBug(), +so make sure you copy them across to the new protocol.c file. + +In the MSSPTable[] in your old protocol.c file, copy everything between here: + + /* Generic */ + { "CRAWL DELAY", "-1" }, + +And here: + + { NULL, NULL } /* This must always be last. */ + +Then paste it into the new protocol.c file. Do the same in protocol.h: + + #define MUD_NAME "Unknown MUD" + + typedef struct descriptor_data descriptor_t; + +Make sure the above is updated to be the same as your old protocol.h file. + +Take a look in the appropriate INSTALL file and see how the MSDP_AFFECTS and +MSDP_ROOM_EXITS now use tables. It is recommended that you do the same, but +don't forget to update your MUSHclient plugin and/or Mudlet script as well! + +Some muds internally modify or strip out characters with ASCII values of 3, 4, +5 and/or 6. If your mud does this, you will need to change it before you can +use the MSDP tables and arrays. + +As the protocol_t structure has changed, it's essential that you do a clean +make after updating to the latest version. + +/****************************************************************************** + What's new in this version? + ******************************************************************************/ + +As people use the snippet, occasional problems are revealed and reported, and I +resolve them for the next version. Furthermore, the specifications for some of +the protocols (particularly MSDP) change over time, and the snippet needs to be +updated to remain compliant. The following summary describes each version: + +Version 2 (13-Jun-2011) + +* Added support for broken packets. + +* Resolved a cyclic TTYPE issue that caused Windows telnet to freeze. + +* Added the new MSSP variables. + +Version 3 (28-Aug-2011) + +* Added an AllocString() wrapper function, as strdup() isn't standard C. + +* Added support for the new MSDP tables and arrays. + +* Added support for the new UNREPORT and RESET MSDP commands. + +* Added a new REPORTED_VARIABLES list, as described in the latest MSDP spec. + +* Renamed VARIABLES to SENDABLE_VARIABLES as described in the latest MDSP spec. + +* Cleaned up the code, adding consts and fixing -ansi and -pedantic warnings. + +* Added support for the new Mudlet GUI autoinstaller. + +* Added an MCCP flag to make integration with the snippet easier. + +* Updated CopyoverGet() and CopyoverSet() to include TTYPE, MCCP and CHARSET. + +* Added an MSDPFlush() function for variables that need to be sent immediately. + +* ProtocolOutput() now lets you send tabs. + +* The snippet now recognises that DecafMUD supports 256 colours. + +* Updated the TBA instructions with a fix for strfrmt(). + +* Updated the installation instructions to use MSDP tables. + +Version 4 (31-Aug-2011) + +* Quick fix to AllocString(). + +Version 5 (12-Oct-2011) + +* Added symbolic constants for MSDP_TABLE_OPEN/CLOSE and MSDP_ARRAY_OPEN/CLOSE. + +* MSDPSetArray() was using table values rather than the array values. Fixed. + +* Added MSDPSendList(), used for the MSDP LIST command. + +* Doubled MAX_VARIABLE_LENGTH for the list variables. + +* Some of the LISTs had no separators between values when using ATCP. Fixed. + +* The MSSP table now uses function pointers, making it easier to update. + +* Added support for both variants of MXP negotiation. + +Version 6 (16-Nov-2011) + +* Removed a stray semicolon at the end of an 'if' statement. + +* Made it easier to add MCCP support. + +* Made several minor updates to the installation instructions. + +* Added an INSTALL_ROM.TXT. diff --git a/doc/dg_events.txt b/doc/dg_events.txt index b01f14b..b96b0c6 100644 --- a/doc/dg_events.txt +++ b/doc/dg_events.txt @@ -2,12 +2,117 @@ ************************************************************************ * 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 @@ -195,7 +300,3 @@ Tips for creating events: 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. - - - - diff --git a/doc/mudmail.pdf b/doc/mudmail.pdf deleted file mode 100644 index bdb8423..0000000 Binary files a/doc/mudmail.pdf and /dev/null differ diff --git a/lib/text/greetings b/lib/text/greetings index af36d57..395871e 100644 --- a/lib/text/greetings +++ b/lib/text/greetings @@ -1,6 +1,6 @@ T B A M U D D E V E L O P M E N T P O R T - + 3 . 6 3 Based on CircleMUD, Created by Jeremy Elson diff --git a/src/act.h b/src/act.h index 34d3c4b..e2bc341 100644 --- a/src/act.h +++ b/src/act.h @@ -185,7 +185,7 @@ ACMD(do_kick); ACMD(do_kill); ACMD(do_order); ACMD(do_rescue); - +ACMD(do_whirlwind); /***************************************************************************** * Begin Functions and defines for act.other.c diff --git a/src/act.informative.c b/src/act.informative.c index f6c89a1..b311131 100644 --- a/src/act.informative.c +++ b/src/act.informative.c @@ -2441,7 +2441,7 @@ ACMD(do_whois) if (!got_from_file && victim->desc != NULL && GET_LEVEL(ch) >= LVL_GOD) { protocol_t * prot = victim->desc->pProtocol; send_to_char(ch, "Client: %s\r\n", prot->pVariables[eMSDP_CLIENT_ID]->pValueString); - send_to_char(ch, "Color: %s\r\n", prot->pVariables[eMSDP_XTERM_256_COLORS] ? "Xterm" : (prot->pVariables[eMSDP_ANSI_COLORS] ? "Ansi" : "None")); + send_to_char(ch, "Color: %s\r\n", prot->pVariables[eMSDP_XTERM_256_COLORS]->ValueInt ? "Xterm" : (prot->pVariables[eMSDP_ANSI_COLORS]->ValueInt ? "Ansi" : "None")); send_to_char(ch, "MXP: %s\r\n", prot->bMXP ? "Yes" : "No"); send_to_char(ch, "Charset: %s\r\n", prot->bCHARSET ? "Yes" : "No"); send_to_char(ch, "MSP: %s\r\n", prot->bMSP ? "Yes" : "No"); diff --git a/src/act.offensive.c b/src/act.offensive.c index e47ba69..73af429 100644 --- a/src/act.offensive.c +++ b/src/act.offensive.c @@ -19,6 +19,7 @@ #include "spells.h" #include "act.h" #include "fight.h" +#include "mud_event.h" ACMD(do_assist) { @@ -390,6 +391,98 @@ ACMD(do_rescue) WAIT_STATE(vict, 2 * PULSE_VIOLENCE); } +EVENTFUNC(event_whirlwind) +{ + 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; + + /* For the sake of simplicity, we will place the event data in easily + * referenced pointers */ + pMudEvent = (struct mud_event_data *) event_obj; + ch = (struct char_data *) pMudEvent->pStruct; + + /* When using a list, we have to make sure to allocate the list as it + * uses dynamic memory */ + room_list = create_list(); + + /* We search through the "next_in_room", and grab all NPCs and add them + * to our list */ + for (tch = world[IN_ROOM(ch)].people; tch; tch = tch->next_in_room) + if (IS_NPC(tch)) + add_to_list(tch, room_list); + + /* If our list is empty or has "0" entries, we free it from memory and + * close off our event */ + if (room_list->iSize == 0) { + free_list(room_list); + send_to_char(ch, "There is no one in the room to whirlwind!\r\n"); + return 0; + } + + /* We spit out some ugly colour, making use of the new colour options, + * to let the player know they are performing their whirlwind strike */ + send_to_char(ch, "\t[f313]You deliver a vicious \t[f014]\t[b451]WHIRLWIND!!!\tn\r\n"); + + /* Lets grab some a random NPC from the list, and hit() them up */ + for (count = dice(1, 4); count > 0; count--) { + tch = random_from_list(room_list); + hit(ch, tch, TYPE_UNDEFINED); + } + + /* Now that our attack is done, let's free out list */ + free_list(room_list); + + /* The "return" of the event function is the time until the event is called + * again. If we return 0, then the event is freed and removed from the list, but + * any other numerical response will be the delay until the next call */ + if (GET_SKILL(ch, SKILL_WHIRLWIND) < rand_number(1, 101)) { + send_to_char(ch, "You stop spinning.\r\n"); + return 0; + } else + return 1.5 * PASSES_PER_SEC; +} + +/* The "Whirlwind" skill is designed to provide a basic understanding of the + * mud event and list systems. This is in NO WAY a balanced skill. */ +ACMD(do_whirlwind) +{ + + if (IS_NPC(ch) || !GET_SKILL(ch, SKILL_WHIRLWIND)) { + send_to_char(ch, "You have no idea how.\r\n"); + return; + } + + if (GET_POS(ch) < POS_FIGHTING) { + send_to_char(ch, "You must be on your feet to perform a whirlwind.\r\n"); + return; + } + + /* First thing we do is check to make sure the character is not in the middle + * of a whirl wind attack. + * + * "char_had_mud_event() will sift through the character's event list to see if + * an event of type "eWHIRLWIND" currently exists. */ + if (char_has_mud_event(ch, eWHIRLWIND)) { + send_to_char(ch, "You are already attempting that!\r\n"); + return; + } + + send_to_char(ch, "You begin to spin rapidly in circles.\r\n"); + act("$N begins to rapidly spin in a circle!", FALSE, ch, 0, 0, TO_ROOM); + + /* NEW_EVENT() will add a new mud event to the event list of the character. + * This function below adds a new event of "eWHIRLWIND", to "ch", and passes "NULL" as + * additional data. The event will be called in "3 * PASSES_PER_SEC" or 3 seconds */ + NEW_EVENT(eWHIRLWIND, ch, NULL, 3 * PASSES_PER_SEC); + WAIT_STATE(ch, PULSE_VIOLENCE * 3); +} + ACMD(do_kick) { char arg[MAX_INPUT_LENGTH]; diff --git a/src/cedit.c b/src/cedit.c index dcc6316..2b46ae0 100644 --- a/src/cedit.c +++ b/src/cedit.c @@ -134,6 +134,8 @@ static void cedit_setup(struct descriptor_data *d) OLC_CONFIG(d)->operation.nameserver_is_slow = CONFIG_NS_IS_SLOW; OLC_CONFIG(d)->operation.medit_advanced = CONFIG_MEDIT_ADVANCED; OLC_CONFIG(d)->operation.ibt_autosave = CONFIG_IBT_AUTOSAVE; + OLC_CONFIG(d)->operation.protocol_negotiation = CONFIG_PROTOCOL_NEGOTIATION; + /* Autowiz */ OLC_CONFIG(d)->autowiz.use_autowiz = CONFIG_USE_AUTOWIZ; OLC_CONFIG(d)->autowiz.min_wizlist_lev = CONFIG_MIN_WIZLIST_LEV; @@ -233,6 +235,8 @@ static void cedit_save_internally(struct descriptor_data *d) CONFIG_OLC_SAVE = OLC_CONFIG(d)->operation.auto_save_olc; CONFIG_MEDIT_ADVANCED = OLC_CONFIG(d)->operation.medit_advanced; CONFIG_IBT_AUTOSAVE = OLC_CONFIG(d)->operation.ibt_autosave; + CONFIG_PROTOCOL_NEGOTIATION = OLC_CONFIG(d)->operation.protocol_negotiation; + /* Autowiz */ CONFIG_USE_AUTOWIZ = OLC_CONFIG(d)->autowiz.use_autowiz; CONFIG_MIN_WIZLIST_LEV = OLC_CONFIG(d)->autowiz.min_wizlist_lev; @@ -542,6 +546,9 @@ int save_config( IDXTYPE nowhere ) "min_wizlist_lev = %d\n\n", CONFIG_MIN_WIZLIST_LEV); + fprintf(fl, "* If yes, enable the protocol negotiation system?\n" + "protocol_negotiation = %d\n\n", + CONFIG_PROTOCOL_NEGOTIATION); fclose(fl); @@ -727,6 +734,7 @@ static void cedit_disp_operation_options(struct descriptor_data *d) "%sN%s) Start Message : \r\n%s%s\r\n" "%sO%s) Medit Stats Menu : %s%s\r\n" "%sP%s) Autosave bugs when resolved from commandline : %s%s\r\n" + "%sR%s) Enable Protocol Negotiation : %s%s\r\n" "%sQ%s) Exit To The Main Menu\r\n" "Enter your choice : ", grn, nrm, cyn, OLC_CONFIG(d)->operation.DFLT_PORT, @@ -745,6 +753,7 @@ static void cedit_disp_operation_options(struct descriptor_data *d) grn, nrm, cyn, OLC_CONFIG(d)->operation.START_MESSG ? OLC_CONFIG(d)->operation.START_MESSG : "", grn, nrm, cyn, OLC_CONFIG(d)->operation.medit_advanced ? "Advanced" : "Standard", grn, nrm, cyn, OLC_CONFIG(d)->operation.ibt_autosave ? "Yes" : "No", + grn, nrm, cyn, OLC_CONFIG(d)->operation.protocol_negotiation ? "Yes" : "No", grn, nrm ); @@ -1218,6 +1227,11 @@ void cedit_parse(struct descriptor_data *d, char *arg) TOGGLE_VAR(OLC_CONFIG(d)->operation.ibt_autosave); break; + case 'r': + case 'R': + TOGGLE_VAR(OLC_CONFIG(d)->operation.protocol_negotiation); + break; + case 'q': case 'Q': cedit_disp_menu(d); diff --git a/src/class.c b/src/class.c index e9c29b6..fadae16 100644 --- a/src/class.c +++ b/src/class.c @@ -1634,6 +1634,7 @@ void init_spell_levels(void) spell_level(SKILL_RESCUE, CLASS_WARRIOR, 3); spell_level(SKILL_TRACK, CLASS_WARRIOR, 9); spell_level(SKILL_BASH, CLASS_WARRIOR, 12); + spell_level(SKILL_WHIRLWIND, CLASS_WARRIOR, 12); } /* This is the exp given to implementors -- it must always be greater than the diff --git a/src/comm.c b/src/comm.c index 7172f0c..ad074e4 100644 --- a/src/comm.c +++ b/src/comm.c @@ -1443,7 +1443,7 @@ static void init_descriptor (struct descriptor_data *newd, int desc) *newd->output = '\0'; newd->bufptr = 0; newd->has_prompt = 1; /* prompt is part of greetings */ - STATE(newd) = CON_GET_PROTOCOL; + STATE(newd) = CONFIG_PROTOCOL_NEGOTIATION ? CON_GET_PROTOCOL : CON_GET_NAME; CREATE(newd->history, char *, HISTORY_SIZE); if (++last_desc == 1000) last_desc = 1; @@ -1457,6 +1457,7 @@ static int new_descriptor(socket_t s) { socket_t desc; int sockets_connected = 0; + int greetsize; socklen_t i; struct descriptor_data *newd; struct sockaddr_in peer; @@ -1521,13 +1522,16 @@ static int new_descriptor(socket_t s) newd->next = descriptor_list; descriptor_list = newd; - /* Attach Event */ - attach_mud_event(new_mud_event(ePROTOCOLS, newd, NULL), 1.5 * PASSES_PER_SEC); - - /* KaVir's plugin*/ - write_to_output(newd, "Attempting to Detect Client, Please Wait...\r\n"); - ProtocolNegotiate(newd); - + if (CONFIG_PROTOCOL_NEGOTIATION) { + /* Attach Event */ + NEW_EVENT(ePROTOCOLS, newd, NULL, 1.5 * PASSES_PER_SEC); + /* KaVir's plugin*/ + write_to_output(newd, "Attempting to Detect Client, Please Wait...\r\n"); + ProtocolNegotiate(newd); + } else { + greetsize = strlen(GREETINGS); + write_to_output(newd, "%s", ProtocolOutput(newd, GREETINGS, &greetsize)); + } return (0); } diff --git a/src/config.c b/src/config.c index d6c7f67..cddf4dd 100644 --- a/src/config.c +++ b/src/config.c @@ -297,7 +297,6 @@ int min_wizlist_lev = LVL_GOD; * set to YES. */ int display_closed_doors = YES; - /* Automap and map options */ /* Default is to have automap and map command only enabled for immortals */ int map_option = MAP_IMM_ONLY; @@ -309,3 +308,6 @@ int medit_advanced_stats = YES; /* Does "bug resolve" autosave ? */ int ibt_autosave = YES; + +/* Use the protocol negotiation system */ +int protocol_negotiation = YES; diff --git a/src/config.h b/src/config.h index 96cccec..1058cc3 100644 --- a/src/config.h +++ b/src/config.h @@ -68,6 +68,7 @@ extern const char *START_MESSG; extern int use_autowiz; extern int min_wizlist_lev; extern int display_closed_doors; +extern int protocol_negotiation; /* Automap and map options */ extern int map_option; extern int default_map_size; diff --git a/src/constants.c b/src/constants.c index 434f14d..1c90d40 100644 --- a/src/constants.c +++ b/src/constants.c @@ -24,7 +24,7 @@ * @todo cpp_extern isn't needed here (or anywhere) as the extern reserved word * works correctly with C compilers (at least in my Experience) * Jeremy Osborne 1/28/2008 */ -cpp_extern const char *tbamud_version = "tbaMUD 3.62"; +cpp_extern const char *tbamud_version = "tbaMUD 3.63"; /* strings corresponding to ordinals/bitvectors in structs.h */ /* (Note: strings for class definitions in class.c instead of here) */ diff --git a/src/db.c b/src/db.c index b3a9100..4eb95d9 100644 --- a/src/db.c +++ b/src/db.c @@ -3761,6 +3761,7 @@ static void load_default_config( void ) CONFIG_TRACK_T_DOORS = track_through_doors; CONFIG_NO_MORT_TO_IMMORT = no_mort_to_immort; CONFIG_DISP_CLOSED_DOORS = display_closed_doors; + CONFIG_PROTOCOL_NEGOTIATION = protocol_negotiation; CONFIG_DIAGONAL_DIRS = diagonal_dirs; CONFIG_MAP = map_option; CONFIG_MAP_SIZE = default_map_size; @@ -4005,6 +4006,8 @@ void load_config( void ) case 'p': if (!str_cmp(tag, "pk_allowed")) CONFIG_PK_ALLOWED = num; + else if (!str_cmp(tag, "protocol_negotiation")) + CONFIG_PROTOCOL_NEGOTIATION = num; else if (!str_cmp(tag, "pt_allowed")) CONFIG_PT_ALLOWED = num; break; diff --git a/src/dg_event.c b/src/dg_event.c index 3245ce3..c92166b 100644 --- a/src/dg_event.c +++ b/src/dg_event.c @@ -127,6 +127,8 @@ void event_process(void) the_event->q_el = queue_enq(event_q, the_event, new_time + pulse); else { + if (the_event->isMudEvent && the_event->event_obj != NULL) + free_mud_event((struct mud_event_data *) the_event->event_obj); /* It is assumed that the_event will already have freed ->event_obj. */ free(the_event); } diff --git a/src/interpreter.c b/src/interpreter.c index 7d9f55e..b64b533 100644 --- a/src/interpreter.c +++ b/src/interpreter.c @@ -343,6 +343,7 @@ cpp_extern const struct command_info cmd_info[] = { { "whois" , "whoi" , POS_DEAD , do_whois , 0, 0 }, { "whoami" , "whoami" , POS_DEAD , do_gen_ps , 0, SCMD_WHOAMI }, { "where" , "where" , POS_RESTING , do_where , 1, 0 }, + { "whirlwind", "whirl" , POS_FIGHTING, do_whirlwind, 0, 0 }, { "whisper" , "whisper" , POS_RESTING , do_spec_comm, 0, SCMD_WHISPER }, { "wield" , "wie" , POS_RESTING , do_wield , 0, 0 }, { "withdraw" , "withdraw", POS_STANDING, do_not_here , 1, 0 }, @@ -1303,7 +1304,6 @@ EVENTFUNC(get_protocols) write_to_output(d, GREETINGS, 0); STATE(d) = CON_GET_NAME; - free_mud_event(pMudEvent); return 0; } diff --git a/src/mud_event.c b/src/mud_event.c index a92012b..bb21915 100644 --- a/src/mud_event.c +++ b/src/mud_event.c @@ -18,17 +18,38 @@ /* Global List */ struct list_data * world_events = NULL; +/* The mud_event_index[] is merely a tool for organizing events, and giving + * them a "const char *" name to help in potential debugging */ struct mud_event_list mud_event_index[] = { - { "Null" , NULL , -1 }, /* eNULL */ - { "Protocol" , get_protocols, EVENT_DESC } /* ePROTOCOLS */ + { "Null" , NULL , -1 }, /* eNULL */ + { "Protocol" , get_protocols , EVENT_DESC }, /* ePROTOCOLS */ + { "Whirlwind" , event_whirlwind, EVENT_CHAR } /* eWHIRLWIND */ }; +/* init_events() is the ideal function for starting global events. This + * might be the case if you were to move the contents of heartbeat() into + * the event system */ void init_events(void) { /* Allocate Event List */ world_events = create_list(); } +/* event_countdown() is used for events which are to be used as a countdown... + * go figure eh? This could be useful for skills which have an extended cooldown, + * like "lay on hands" once every 24 hours. Simply add an event to the + * mud_event_index[] such as: + * { "Lay on hands" , event_countdown, EVENT_CHAR } + * and then add the event after a successful skill call: + * attach_mud_event(new_mud_event(eLAYONHANDS, ch, NULL), 24 * SECS_PER_MUD_HOUR); + * and then add something like this is your skill function: + * if (char_has_mud_event(ch, eLAYONHANDS)) { + * send_to_char(ch, "You must wait a full 24 hours before re-using this skill.\r\n"); + * return; + * } + * The bottom switch() is for any post-event actions, like telling the character they can + * now access their skill again. + */ EVENTFUNC(event_countdown) { struct mud_event_data * pMudEvent; @@ -48,11 +69,14 @@ EVENTFUNC(event_countdown) default: break; } - - free_mud_event(pMudEvent); + return 0; } - +/* As of 3.63, there are only global, descriptor, and character events. This + * is due to the potential scope of the necessary debugging if events were + * included with rooms, objects, spells or any other structure type. Adding + * events to these other systems should be just as easy as adding the current + * library was, and should be available in a future release. - Vat */ void attach_mud_event(struct mud_event_data *pMudEvent, long time) { struct event * pEvent; @@ -126,6 +150,9 @@ struct mud_event_data * char_has_mud_event(struct char_data * ch, event_id iId) struct mud_event_data * pMudEvent; bool found = FALSE; + if (ch->events->iSize == 0) + return NULL; + simple_list(NULL); while ((pEvent = (struct event *) simple_list(ch->events)) != NULL) { diff --git a/src/mud_event.h b/src/mud_event.h index 611b0c6..ffacb6a 100644 --- a/src/mud_event.h +++ b/src/mud_event.h @@ -19,9 +19,12 @@ #define EVENT_DESC 1 #define EVENT_CHAR 2 +#define NEW_EVENT(event_id, struct, var, time) (attach_mud_event(new_mud_event(event_id, struct, var), time)) + typedef enum { eNULL, - ePROTOCOLS, + ePROTOCOLS, /* The Protocol Detection Event */ + eWHIRLWIND, /* The Whirlwind Attack */ } event_id; struct mud_event_list { @@ -50,5 +53,6 @@ struct mud_event_data * char_has_mud_event(struct char_data * ch, event_id iId); /* Events */ EVENTFUNC(event_countdown); EVENTFUNC(get_protocols); +EVENTFUNC(event_whirlwind); #endif /* _MUD_EVENT_H_ */ diff --git a/src/protocol.c b/src/protocol.c index fbd5a5e..b5793ce 100644 --- a/src/protocol.c +++ b/src/protocol.c @@ -1,9 +1,5 @@ /****************************************************************************** Protocol snippet by KaVir. Released into the Public Domain in February 2011. - - This snippet was originally designed to be codebase independent, but has been - modified slightly so that it runs out-of-the-box on Merc derivatives. To use - it for other codebases, just change the code in the "Diku/Merc" section below. ******************************************************************************/ /****************************************************************************** @@ -550,13 +546,16 @@ const char *ProtocolOutput( descriptor_t *apDescriptor, const char *apData, int pCopyFrom = Tab; break; case '_': - pCopyFrom = "\x1B[4m"; /* Underline */ + pCopyFrom = "\x1B[4m"; /* Underline... if supported */ break; case '+': - pCopyFrom = "\x1B[1m"; /* Bold */ + pCopyFrom = "\x1B[1m"; /* Bold... if supported */ break; case '-': - pCopyFrom = "\x1B[5m"; /* Blinking??? */ + pCopyFrom = "\x1B[5m"; /* Blinking... if supported */ + break; + case '=': + pCopyFrom = "\x1B[7m"; /* Reverse... if supported */ break; case '*': pCopyFrom = "@"; /* The At Symbol... I don't really like this, but it seems like @@ -2429,9 +2428,9 @@ static const char *GetAnsiColour( bool_t abBackground, int aRed, int aGreen, int else if ( aRed == aGreen && aRed == aBlue ) return abBackground ? s_BackWhite : aRed >= 4 ? s_BoldWhite : s_DarkWhite; else if ( aRed > aGreen && aRed > aBlue ) - return abBackground ? s_BackRed : aRed >= 3 ? s_BoldRed : s_DarkRed; + return abBackground ? s_BackRed : aRed > 3 ? s_BoldRed : s_DarkRed; else if ( aRed == aGreen && aRed > aBlue ) - return abBackground ? s_BackYellow : aRed >= 3 ? s_BoldYellow : s_DarkYellow; + return abBackground ? s_BackYellow : aRed > 3 ? s_BoldYellow : s_DarkYellow; else if ( aRed == aBlue && aRed > aGreen ) return abBackground ? s_BackMagenta : aRed >= 3 ? s_BoldMagenta : s_DarkMagenta; else if ( aGreen > aBlue ) diff --git a/src/spell_parser.c b/src/spell_parser.c index 2915593..374bfb3 100644 --- a/src/spell_parser.c +++ b/src/spell_parser.c @@ -950,5 +950,6 @@ void mag_assign_spells(void) skillo(SKILL_SNEAK, "sneak"); skillo(SKILL_STEAL, "steal"); skillo(SKILL_TRACK, "track"); + skillo(SKILL_WHIRLWIND, "whirlwind"); } diff --git a/src/spells.h b/src/spells.h index 7619e3c..09142b8 100644 --- a/src/spells.h +++ b/src/spells.h @@ -103,11 +103,11 @@ #define SKILL_HIDE 133 /* Reserved Skill[] DO NOT CHANGE */ #define SKILL_KICK 134 /* Reserved Skill[] DO NOT CHANGE */ #define SKILL_PICK_LOCK 135 /* Reserved Skill[] DO NOT CHANGE */ -/* Undefined 136 */ +#define SKILL_WHIRLWIND 136 #define SKILL_RESCUE 137 /* Reserved Skill[] DO NOT CHANGE */ #define SKILL_SNEAK 138 /* Reserved Skill[] DO NOT CHANGE */ #define SKILL_STEAL 139 /* Reserved Skill[] DO NOT CHANGE */ -#define SKILL_TRACK 140 /* Reserved Skill[] DO NOT CHANGE */ +#define SKILL_TRACK 140 /* Reserved Skill[] DO NOT CHANGE */ /* New skills may be added here up to MAX_SKILLS (200) */ /* NON-PLAYER AND OBJECT SPELLS AND SKILLS: The practice levels for the spells diff --git a/src/structs.h b/src/structs.h index 34613d0..8a909a6 100644 --- a/src/structs.h +++ b/src/structs.h @@ -22,7 +22,7 @@ * on an older version. You are supposed to compare this with the macro * TBAMUD_VERSION() in utils.h. * It is read as Major/Minor/Patchlevel - MMmmPP */ -#define _TBAMUD 0x030620 +#define _TBAMUD 0x030630 /** If you want equipment to be automatically equipped to the same place * it was when players rented, set the define below to 1 because @@ -1348,6 +1348,7 @@ struct game_operation char *START_MESSG; /**< The start msg for new characters. */ int medit_advanced; /**< Does the medit OLC show the advanced stats menu ? */ int ibt_autosave; /**< Does "bug resolve" autosave ? */ + int protocol_negotiation; /**< Enable the protocol negotiation system ? */ }; /** The Autowizard options. */ diff --git a/src/utils.h b/src/utils.h index c79457f..90bdc65 100644 --- a/src/utils.h +++ b/src/utils.h @@ -1046,6 +1046,8 @@ do \ #define CONFIG_MEDIT_ADVANCED config_info.operation.medit_advanced /** Does "bug resolve" autosave ? */ #define CONFIG_IBT_AUTOSAVE config_info.operation.ibt_autosave +/** Use the protocol negotiation system? */ +#define CONFIG_PROTOCOL_NEGOTIATION config_info.operation.protocol_negotiation /* Autowiz */ /** Use autowiz or not? */