--------------------------------------------------------------interp.c/interp.h-
At the top of interp.c, find this:
/*
 * Command logging types.
 */
#define LOG_NORMAL  0
#define LOG_ALWAYS  1
#define LOG_NEVER   2

Remove it, and replace it near the top of interp.h.

In interpret(), after the freeze code, but before grabbing the command word, add
this:
	//Called here, because the command can't be cut off yet.
	if (parse_channel (ch, argument))
		return;

Now add these to the bottom of interp.h:
/* New Channel System -- Midboss */
DECLARE_DO_FUN( chan_do_commands );
DECLARE_DO_FUN( chan_do_list	 );
DECLARE_DO_FUN( chan_do_invite	 );
DECLARE_DO_FUN( chan_do_join	 );
DECLARE_DO_FUN( chan_do_leave	 );
DECLARE_DO_FUN( chan_do_kick	 );
DECLARE_DO_FUN( chan_do_topic	 );
DECLARE_DO_FUN( chan_do_config	 );
DECLARE_DO_FUN( chan_do_create	 );
DECLARE_DO_FUN( chan_do_admin	 );
DECLARE_DO_FUN( chan_do_ban		 );
DECLARE_DO_FUN( chan_do_stats	 );
-------------------------------------------------------------------------merc.h-
Add this with the other typedefs:
typedef struct	  channel_data	   CHANNEL_DATA;

Add this stuff wherever you feel like it:
/*
 * Channel configuration.
 */
#define CHANNEL_PRIVATE		(A) //Invitation only.
#define CHANNEL_STAFF		(B) //Immortals (level 2+) only.
#define CHANNEL_ADMIN		(C) //Administrators (level 8+) only.
#define CHANNEL_IMP			(D) //Implementors (level 10) only.
#define CHANNEL_INVITE		(E) //All users may invite (private only).
#define CHANNEL_KICK		(F) //Channel admins can '.kick'.
#define CHANNEL_BAN			(G) //Channel admins can '.ban'.
#define CHANNEL_TOPIC		(H) //Channel admins can '.topic'.
#define CHANNEL_PUBLIC		(I) //All immortals are automatically admins.
#define CHANNEL_ADVANCE		(J) //Admins can create other admins.

/*
 * New channel structure.  -- Midboss, 6/8/2006
 */
struct channel_data
{
	bool			valid;
	CHANNEL_DATA *	next;
	char *			name;
	char *			owner;
	char *			topic;
	char *			keyword;
	long			config;
	CHANMEMBER *	lists;
};

#define MEMBER_BAN		0
#define MEMBER_ADMIN	1

struct chanmember
{
	bool			valid;
	CHANMEMBER *	next;
	sh_int			type;
	char *			name;
};

Now, in struct pc_data, add:
	char *			channels;
	char *			invitations;

Add this with your other globals:
extern  CHANNEL_DATA	*	channel_list;

Add this with your other data files:
#define CHAN_FILE		"channels.txt"		  /* Channel file. */

Add these with your other prototypes:
/* channels.c */
void			send_to_channel		(CHAR_DATA * ch, char * cmd, 
										char * arg, bool fSkip);
bool			parse_channel		(CHAR_DATA * ch, char * arg);
bool			can_hear			(CHAR_DATA * ch, CHANNEL_DATA * chan);
bool			is_admin			(CHAR_DATA * ch, CHANNEL_DATA * chan);
bool			has_invite			(CHAR_DATA * ch, CHANNEL_DATA * chan);
bool			is_owner			(CHAR_DATA * ch, CHANNEL_DATA * chan);
bool			is_banned			(CHAR_DATA * ch, CHANNEL_DATA * chan);
void			check_channels		(CHAR_DATA * ch);
void			leave_channel		(CHAR_DATA * ch, CHANNEL_DATA * chan);
bool			legal_channel		(char * keywd, char * name);
CHANNEL_DATA *	get_channel			(char * name);
CHANNEL_DATA *	get_channel_char	(CHAR_DATA * ch);
CHANMEMBER *	get_member_data		(CHAR_DATA * ch, CHANNEL_DATA * chan);
CHANNEL_DATA *	new_channel			(void);
void			free_channel		(CHANNEL_DATA * channel);
CHANMEMBER *	new_member			(void);
void			free_member			(CHANMEMBER * member);
void			save_channels		(void);
void			load_channels		(void);
-------------------------------------------------------------------------save.c-
In fwrite_char, with the other pcdata fields, add this:
		fprintf (fp, "Chan %s~\n", ch->pcdata->channels);

Now, in fread_char, in the 'C' case, add this:
                KEY ("Chan", ch->pcdata->channels, fread_string (fp));

Now, in the 'E' case, inside of the "End" statement, before the return:
					//Make sure the channels still exist.
					check_channels (ch);
---------------------------------------------------------------------------db.c-
With the globals, add this:
CHANNEL_DATA * channel_list;

Along with the fix_exits() stuff in boot_db(), add a call to load_channels().
---------------------------------------------------------------------olc_save.c-
Inside do_asave, inside the 'world' case, add a call to save_channels().

Also add this somewhere AFTER the 'changed' case:
	if (!str_cmp ("channels", arg1))
		save_channels ();
-------------------------------------------------------------------------./area-
Add this to your helpfiles:
0 CHANNELS~
This MUD uses a player-run channel system, originally written by Midboss.  Any
line preceded by a period will be recieved as a channel command, allowing them
to use a completely seperate set of commands.  Players may create their own
channels, set them up, and run them as they please, however, a player may only
own one channel at a time.

Syntax: .commands                  - Check the up to date command list.
Syntax: .list                      - List all channels.
Syntax: .invite <user> <channel>   - Invite the user to specified channel.
Syntax: .join <channel>            - Join the specified channel.
Syntax: .leave <channel>           - Leave the specified channel.

Syntax: .create <name> <keyword>   - Creates a channel.
Syntax: .grant <user> <channel>    - Add user to channel's admin list.
Syntax: .config <channel> <option> - Adjust the channel's settings.
Syntax: .ban <user> <channel>      - Ban a user from the channel.
Syntax: .kick <user> <channel>     - Kick a user from the channel.
Syntax: .topic <channel> <string>  - Change the channel's topic.

Syntax: .<channel> <text>          - Send a message to the specified channel.
Syntax: .<channel> /me <text>      - Send an emote to the specified channel.

                                         -- Midboss (eclipsing.souls@gmail.com)
~

Now, add channels.txt to your area directory.
--------------------------------------------------------------------------------
Now, add channels.c to your source directory and, if neccesary, add channels.o
to your makefile.  Make clean, recompile, and all should be well.  Be sure to
read channels.c and make sure you at least vaguely understand it, as with any
snippet.  Enjoy!
                                         -- Midboss (eclipsing.souls@gmail.com)
--------------------------------------------------------------------------------