Crashcourse - Part 13

[previous part] [Table of contents] [next part]

In this part of the crashcourse, we'll be taking a close look at guilds and how they work.

NOTE: To join this testguild, you must first leave your current guild (if you have one), and then use:

? load_object("/doc/crashcourse/course13/master")->join_guild(this_player())

To leave it, you must use:

? load_object("/doc/crashcourse/course13/master")->leave_guild(this_player())

First of all, when you're thinking about creating a guild, there are a few important things to consider. A guild is a large part of the mud world, since a lot of players will probably (or at least try to) join your guild when it comes into play, so it's crucially important that you have a good and well thought-through theme. Things like "Well, it's a mage guild with a lot of cool magical spells" just won't do. Write a short story to give the guild some background, and try to weave it into the theme of the mud at the same time. The guild should also have an ultimate goal of some kind. For instance, to rid the world of all evil vermin, or kill of all those pesky goodies that infect this world or even a smaller goal like protect a certain area/artifact/something from intruders. Just try to think of something that you can stick to as the guild develops further. It is also very important that you try to balance the guild as early as possible. Don't create 200 different spells to try to cover each and every aspect of the mud. Instead, try to create some spells/abilities that will help your guild to stand out among the other ones. Perhaps specialize the guild inside one area, like for instance healing, attacking or defense. Now, these are very general stills, so you need to go even deeper. For instance, liquid healing, axe attacking, parry/block defense, etc.

To "activate" your guild, you will also have to register your guild in the mudlib. More specifically, in the file '/std/include/guilds.h'. Only an Arch can do this, so once your guild is on its way, have a chat with on of them. You also need to deceide on a name, which needs to be entered into that file. The name is used for channelname, among other things. Once the file has been updated, '/std/obj/player' will have to be freshed. And the players who can join the guild will have to log out and in again so that the changes will take effect for them. If you are serious about coding a guild and getting it into gameplay, you should also request the Arches for a domaindirectory. For instance, '/d/Magesofdarkness' could be a domain for our example guild. If you, however, deceide to code it in your homedirectory, just remember that all members of the guild will have to leave it if you ever change anything in the pathname of the guild. If your guild master is '/d/Magesofdarkness/master.c', and you want to rename it or move it, all members must first leave it.

I think that will do for now. Let's jump right into the action and have a look at our example guild, 'The Mages Of Darkness'. Now, it's just a code example, so I haven't written a storyline for it, it's just an example of how it can be done.

The first thing you need when starting to code a guild, is the guild master file, which controls / maintains the guild. It is the same file you specified in the guilds.h file. This master file will be called whenever certain events occur with your guild members, for instance when they log in, log out, go linkdead, etc. Before you proceed, please have a look at the files in the /doc/lfun/guild directory.

Directory structure

Having a clean and neat directory structure will help greatly as the guild expands. This is, however, all up to you. I have chosen this structure for this example guild:

area/       - Contains the guild area(s). It should be further
              divided into smaller directories, like for instance
              rooms, items, functions, etc.
board/      - Contains the guild board and its functionfile.
com/        - Contains all the guild commands. If you intend to
              have a lot of commands for mortals and also for
              wizards, it may be a good idea to split it into
              two different directories, like com/ and wizcom/.
etc/        - Contains all the textfiles(news, joinmsg, leavemsg, etc).
help/       - Contains all helpfiles for the guild.
include/    - Contains all the headerfiles used for the guild.
log/        - Contains all logfiles. This is very important if your
              guild directory is a domain directory!
./          - Contains the master.

The guildmaster

FILENAME: master.c

When building the master for the guild, the first thing you should do, is deceide how to structure it. The applies must all be in the master if you want to use them. An apply is just a standard function that is called in an object from an external source. For instance, the driver calls certain applies in the mudlib upon player login, linkdeaths, etc. In our case, the mudlib calls a set of functions (applies) in the guild master. Have a look at /doc/lfun/guild for all the applies. Using these applies you can initialize a member that logs in to his/her "guildstate". For instance, add hooks, properties, skills, etc.

I also prefer to include the actual joining and leaving functions inside the master, but that's totally up to you. For instance, if players may only join your guild from a special room, by typing: 'join guild' or something like that, you can have a trigger that just calls the joining function in the master (can't be done with our master).

Our master's join and leave functions are coded so that other functions may call them. If the join/leave functions return 0, the operation failed and if they return 1, they succeeded.

As you can see, the master of this guild is written as a daemon (function-file). I find this the preferable option, although you can also use a room for it. The main guild room would be an obvious possibility. I personally don't like this option, as it can easily get messy.

The guild master is automatically loaded whenever a member enter the game, so there's no need to worry about that.

There are two important things to remember when coding the master object. The first is security. If you take a look at the remove_member() function in the master, you'll probably notice the securityhole. If some nasty wizard wanted to, he/she could easily remove all online members from the guild. A snippet of code that will do it:

---snip---
#define GUILD_MASTER "/doc/crashcourse/course13/master"
object member;

foreach(member in users())
    if (member->query_guild() == GUILD_MASTER)
        GUILD_MASTER->remove_member(member);
---snip---

Whoopsie.
This makes it important to have good security routines in order to prevent this sort of nasty behaviour. For instance, creating a security routine that just checks the previous object would do in most cases. If it's not anything in the guild area that's calling the master functions, puke on them. You should also log all joins and leaves of the guild, and also the players' stats/skills when they leave, just in case it's someone messing around.
The second is functionpointers connected to members. If you are hooking the members' fight beats (in order to improve their combat rounds, for instance) like this:

member->add_hook("__fight_beat",(:call_other,FUNC,"member_fight":));

you wouldn't be able to fresh the master object (or whichever object owns the hook) without messing with the members. In this case, all members would get an error message in every single fight beat. To prevent this, you should either stick to arrays, or make sure all members are cleaned up whenever the master object is destroyed and updated whenever the master object is loaded.

If you're not sure how to do either, you can have a looksie at my 'Ring of Steel' guild, which hopefully has been added to course part #AD. At least parts of it should be there.

If you wish to have a special death sequence for your guild members, read 'man query_deathmark'. If your guildmembers change appearence, it may be a good idea to have a look at 'man query_member_name'.

Spells

When designing spells for a guild, there are three important things that often go wrong for coders new to guild programming. The first is that they code the spells as if only one person was meant to use them at a time. For instance, using a global variable in the spellcode that get's changed each time the spell is cast. And what happens when several members use the same spell at the same time? A mess. So make sure this doesn't happen, always think about what might happen if more than one member tries to cast a spell at the same time. You should also code it so that even monsters can use the spells at the same time just like a normal member. That may come in handy later on when creating the guild area.

Second, the coders may make unstable code by not taking into account all the different states a player may be in. Let's take a small example: We have a spell that makes the player hit with both his/her weapons each round (extra hits). It's coded very simply by:

TP->hit_with_weapon(weapon1,attacker);
TP->hit_with_weapon(weapon2,attacker);

The problem usually occurs in between those two calls. For instance, the attacker may be dead, and the code will bug. Or the player may be dead, and has lost his/her weapons. You should also have some checks earlier in the code to make sure both TP and attacker are both alive, of course.

Third, a spell that does damage just uses hit_player(), right? Wrong. Don't use hit_player() in guild spells unless absolutely neccessary. You should instead use do_attack(). The only problem is that do_attack() doesn't do much damage, now does it? Not exactly, but it initiates an attack. Have a look at 'man do_attack' for more info. Also have a look at the "spells" of the 'Ring of Steel' guild in course part #AD.

I think is enough for now. It should be more than sufficient to get you underway with your first guild. If not, have a look at course part #AD, which should have files from at least one guild. May be more when you read this, but at least my guild should be there (sensored).

Here are now all files with their location within our guild-directory:

master.c

area/guildcenter.c

board/guildboard.c
board/boardfuncs.c

com/CMD_ACCESS.c
com/drain.c
com/sacrifice.c
com/help.c

etc/ENTERGAME_MSG
etc/EXITGAME_MSG
etc/JOIN_MSG
etc/LEAVE_MSG

help/drain
help/sacrifice

include/guild.h
include/master.h
include/spells.h

Well, I sure hope this did get you interested in guild programming, and if so, good luck with your guild.


WRITTEN: 29 - May - 1998 - Gunner
LAST UPDATE: 01 - Jun - 1998 - Gunner
HTML Version: 13 - Feb - 2000 - Ghorwin

[previous part] [to the top] [Table of contents] [next part]