mirror of
https://github.com/tbamud/tbamud.git
synced 2025-09-21 21:40:49 +02:00
MAJOR: 3.63 Pre-Release: Cedit Toggle for prot system, new skill, updated documentation, and more.
This commit is contained in:
parent
5c317f6863
commit
24018d145b
24 changed files with 854 additions and 38 deletions
16
changelog
16
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
|
||||
|
|
547
doc/ProtocolSystem.txt
Normal file
547
doc/ProtocolSystem.txt
Normal file
|
@ -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 \t<send href="buy pie">pie\t</send>.
|
||||
|
||||
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 "<SUPPORT>" 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.
|
|
@ -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.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
BIN
doc/mudmail.pdf
BIN
doc/mudmail.pdf
Binary file not shown.
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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];
|
||||
|
|
14
src/cedit.c
14
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 : "<None>",
|
||||
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);
|
||||
|
|
|
@ -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
|
||||
|
|
20
src/comm.c
20
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) */
|
||||
|
|
3
src/db.c
3
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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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_ */
|
||||
|
|
|
@ -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 )
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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? */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue