/*
* IMC2 - an inter-mud communications protocol
*
* imc-mercbase.c: integrated interface code for Merc-derived codebases
*
* Copyright (C) 1996,1997 Oliver Jowett <oliver@sa-search.massey.ac.nz>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program (see the file COPYING); if not, write to the
* Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
/* Modifications by:
* Erwin S. Andreasen <erwin@pip.dknet.dk> (Envy changes)
* Erin Moeller <altrag@game.org> (Merc, SMAUG changes)
* Stephen Zepp <zenithar@fullnet.net> (Ack! changes)
*
* integration by Oliver Jowett
*/
#include <stdlib.h>
#include <sys/types.h>
#include <sys/time.h>
#include <ctype.h>
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include "imc.h"
/* ick! */
#define IN_IMC
#include "imc-mercbase.h"
#if !defined(ROM) && !defined(MERC) && !defined(ENVY) && !defined(SMAUG) && !defined(ACK)
#error You must #define one of ROM, MERC, SMAUG, ENVY, or ACK
#endif
#ifdef ROM
#include "recycle.h"
#define IS_NOCHAN(ch) (IS_SET((ch)->comm, COMM_NOCHANNELS))
#define IS_NOTELL(ch) (IS_SET((ch)->comm, COMM_NOTELL))
#define IS_SILENT(ch) (0)
/* from note.c: */
void append_note(NOTE_DATA *pnote);
#endif /* ROM */
#ifdef MERC
#define IS_NOCHAN(ch) (IS_SET((ch)->act, PLR_SILENCE))
#define IS_NOTELL(ch) (IS_SET((ch)->act, PLR_NO_TELL) || IS_NOCHAN(ch))
#define IS_SILENT(ch) (0)
#define page_to_char send_to_char
#endif /* Merc */
#ifdef SMAUG
#define IS_NOCHAN(ch) (IS_SET((ch)->act, PLR_SILENCE))
#define IS_NOTELL(ch) (IS_SET((ch)->act, PLR_NO_TELL) || IS_NOCHAN(ch))
#define IS_SILENT(ch) ((!IS_NPC(ch) && IS_SET(ch->act,PLR_SILENCE)) || \
IS_SET(ch->in_room->room_flags, ROOM_SILENCE))
#define page_to_char send_to_pager_color
#define send_to_char send_to_char_color
#define descriptor_list first_descriptor
#endif /* SMAUG */
#ifdef ENVY
/* There are 2 versions of the IS_SILENT macro: one that checks the race_table
* and one that doesn't. the RACE_MUTE flag appeared in one of the Envy 2.0
* patches, but not everyone has it. Uncomment as needed.
*/
#define IS_NOCHAN(ch) (IS_SET((ch)->act, PLR_SILENCE))
#define IS_NOTELL(ch) (IS_SET((ch)->act, PLR_NO_TELL) || IS_NOCHAN(ch))
#define IS_SILENT(ch) ((IS_AFFECTED((ch),AFF_MUTE) || \
/* IS_SET(race_table[(ch)->race].race_abilities, RACE_MUTE) || */ \
IS_SET((ch)->in_room->room_flags, ROOM_CONE_OF_SILENCE)))
#define page_to_char send_to_char
#endif /* Envy */
#ifdef ACK
#define IS_NOCHAN(ch) (IS_SET((ch)->act, PLR_SILENCE))
#define IS_NOTELL(ch) (IS_SET((ch)->act, PLR_NO_TELL) || IS_NOCHAN(ch))
#define IS_SILENT(ch) (IS_SET(ch->act,PLR_SILENCE) || \
IS_SET(ch->in_room->room_flags, ROOM_QUIET))
#define page_to_char send_to_char
#define descriptor_list first_desc
#endif
#define IS_RINVIS(ch) (!IS_NPC(ch) && \
IS_SET((ch)->pcdata->imc_deaf, IMC_RINVIS))
#define CAN(ch, x, minlev) \
(!IS_NPC(ch) && \
!IS_SET((ch)->pcdata->imc_deny, (x)) && \
((ch)->level >= (minlev) || \
IS_SET((ch)->pcdata->imc_allow, (x))))
#define CHECKIMC(ch) \
do { \
if (IS_NPC(ch)) \
{ \
send_to_char("NPCs cannot use IMC.\n\r", (ch)); \
return; \
} \
if (imc_active<IA_UP) \
{ \
send_to_char("IMC is not active.\n\r", (ch)); \
return; \
} \
} while(0)
#define CHECKMUD(ch,m) \
do { \
if (strcasecmp(m, imc_name) && !imc_find_reminfo(m,1)) \
{ \
char _buf[100]; \
sprintf(_buf, "Warning: '%s' doesn't seem to be active on IMC.\n\r", (m));\
send_to_char(_buf, (ch)); \
} \
} while(0)
#define CHECKMUDOF(ch,n) CHECKMUD(ch,imc_mudof(n))
/* memory allocation hooks */
void *imc_malloc(int size)
{
#ifdef SMAUG
/* Have to use char because CREATE uses a sizeof, which doesnt like void */
char *mem;
CREATE(mem, char, size);
return (void *)mem;
#elif defined(ACK)
return getmem(size);
#else
return alloc_mem(size);
#endif
}
void imc_free(void *block, int size)
{
#ifdef SMAUG
DISPOSE(block);
#elif defined(ACK)
dispose(block, size);
#else
free_mem(block, size);
#endif
}
char *imc_strdup(const char *src)
{
return str_dup(src);
}
void imc_strfree(char *str)
{
#ifdef SMAUG
DISPOSE(str);
#else
free_string(str);
#endif
}
/* config hooks */
int imc_readconfighook(const char *word, const char *value)
{
return 0;
}
void imc_saveconfighook(FILE *fp)
{
}
/* call markfn for every chunk of memory allocated by IMC */
void imc_markmemory(void (*markfn)(void *))
{
imc_reminfo *r;
imc_mail *mailp;
imc_qnode *queuep;
imc_mailid *idp;
imc_info *infop;
imc_connect *cp;
imc_event *ep;
for (infop=imc_info_list; infop; infop=infop->next)
markfn(infop);
for (cp=imc_connect_list; cp; cp=cp->next)
{
markfn(cp->inbuf);
markfn(cp->outbuf);
markfn(cp);
}
for (r=imc_reminfo_list; r; r=r->next)
markfn(r);
for (mailp=imc_ml_head; mailp; mailp=mailp->next)
markfn(mailp);
for (queuep=imc_mq_head; queuep; queuep=queuep->next)
markfn(queuep);
for (idp=imc_idlist; idp; idp=idp->next)
markfn(idp);
for (ep=imc_event_list; ep; ep=ep->next)
markfn(ep);
for (ep=imc_event_free; ep; ep=ep->next)
markfn(ep);
}
/* call markfn for every string allocated by IMC */
void imc_markstrings(void (*markfn)(char *))
{
int i;
imc_reminfo *r;
imc_mail *mailp;
imc_qnode *queuep;
imc_mailid *idp;
imc_info *infop;
imc_ignore_data *ign;
markfn(imc_name);
markfn(imc_prefix);
for (infop=imc_info_list; infop; infop=infop->next)
{
markfn(infop->name);
markfn(infop->host);
markfn(infop->serverpw);
markfn(infop->clientpw);
}
for (r=imc_reminfo_list; r; r=r->next)
{
markfn(r->name);
markfn(r->version);
markfn(r->route);
}
for (ign=imc_ignore_list; ign; ign=ign->next)
markfn(ign->name);
for (i=0; i<IMC_MEMORY; i++)
if (imc_memory[i].from)
markfn(imc_memory[i].from);
for (mailp=imc_ml_head; mailp; mailp=mailp->next)
{
markfn(mailp->from);
markfn(mailp->to);
markfn(mailp->date);
markfn(mailp->text);
markfn(mailp->subject);
markfn(mailp->id);
}
for (queuep=imc_mq_head; queuep; queuep=queuep->next)
markfn(queuep->tomud);
for (idp=imc_idlist; idp; idp=idp->next)
markfn(idp->id);
}
/* Color configuration (more tables to configure.. sowwy)
*
* The various #defines here are used within the IMC code to format
* things like rtells themselves (not the text of the message, but the
* "a@b rtells you 'blah'" structure)
*
* Each C_? #define maps an IMC color code (the ?) to one of your color codes.
*
* The various FORMATs define colors for rbeep, etc
*
* this may seem ugly, but it makes things expandable - and it will probably
* go away in the near future anyway
*
*/
#ifdef ACK
#define RTELL_FORMAT_1 _C(W) "You rtell " _C(Y) "%s " _C(W) "'" _C(w) "%s" _C(W) "'\n\r" _C(d)
#define RTELL_FORMAT_2 _C(Y) "%s " _C(W) "rtells you '" _C(w) "%s" _C(W) "'\n\r" _C(d)
#define RBEEP_FORMAT_1 _C(R) "You rbeep " _C(Y) "%s" _C(R) ".\n\r" _C(d)
#define RBEEP_FORMAT_2 _C(Y) "\a%s " _C(R) "rbeeps you.\n\r" _C(d)
#else /* custom formats */
#define RTELL_FORMAT_1 "You rtell %s '%s" _C(d) "'.\n\r"
#define RTELL_FORMAT_2 "%s rtells you '%s" _C(d) "'.\n\r"
#define RBEEP_FORMAT_1 "You rbeep %s.\n\r"
#define RBEEP_FORMAT_2 "\a%s rbeeps you.\n\r"
#endif
#ifdef ACK
/* Ack! colors */
#define _C(x) C_##x
#define C_b "@@B"
#define C_g "@@G"
#define C_r "@@R"
#define C_y "@@b"
#define C_m "@@m"
#define C_c "@@c"
#define C_w "@@g"
#define C_D "@@d"
#define C_B "@@l"
#define C_G "@@r"
#define C_R "@@e"
#define C_Y "@@y"
#define C_M "@@p"
#define C_C "@@a"
#define C_W "@@W"
#define C_x "@@N"
#define C_d "@@N"
#elif defined(SMAUG)
/* SMAUG colors */
#define _C(x) C_##x
#define C_b "&b"
#define C_g "&g"
#define C_r "&r"
#define C_y "&O"
#define C_m "&p"
#define C_c "&c"
#define C_w "&w"
#define C_D "&z"
#define C_B "&B"
#define C_G "&G"
#define C_R "&R"
#define C_Y "&Y"
#define C_M "&P"
#define C_C "&C"
#define C_W "&W"
#define C_x "&w"
#define C_d "&w"
#elif defined(IMC_COLOR)
/* custom color configuration */
#define _C(x) C_##x
#define C_b "{b"
#define C_g "{g"
#define C_r "{r"
#define C_y "{y"
#define C_m "{m"
#define C_c "{c"
#define C_w "{w"
#define C_D "{D"
#define C_B "{B"
#define C_G "{G"
#define C_R "{R"
#define C_Y "{Y"
#define C_M "{M"
#define C_C "{C"
#define C_W "{W"
#define C_x "{x"
#define C_d "{d"
#else
/* no color */
#define _C(x) ""
#endif
/* maps IMC standard -> mud local color codes
* let's be unique, noone uses ~ :>
*/
/* Most of this table will be generated from the #defines above;
* you will just need to add the exceptions.
*/
struct {
char *imc; /* IMC code to convert */
char *mud; /* Equivalent mud code */
}
trans_table[]=
{
/* common color definitions, derived from the #defines above */
{ "~!", _C(x) }, /* reset */
{ "~d", _C(d) }, /* default */
{ "~b", _C(b) }, /* dark blue */
{ "~g", _C(g) }, /* dark green */
{ "~r", _C(r) }, /* dark red */
{ "~y", _C(y) }, /* dark yellow / brown */
{ "~m", _C(m) }, /* dark magenta / purple */
{ "~c", _C(c) }, /* cyan */
{ "~w", _C(w) }, /* white */
{ "~D", _C(D) }, /* dark grey / "z" ? */
{ "~B", _C(B) }, /* light blue */
{ "~G", _C(G) }, /* light green */
{ "~R", _C(R) }, /* light red */
{ "~Y", _C(Y) }, /* light yellow */
{ "~M", _C(M) }, /* light magenta / purple */
{ "~C", _C(C) }, /* light cyan */
{ "~W", _C(W) }, /* bright white */
#ifdef SMAUG
/* built-in SMAUG color */
{ "&", "&&" },
{ "^", "^^" },
{ "~~", "&-" }, /* note ordering here.. */
{ "~~", "~" },
/* background colors - no support for these in IMC */
{ "", "^b" },
{ "", "^g" },
{ "", "^r" },
{ "", "^O" },
{ "", "^p" },
{ "", "^c" },
{ "", "^w" },
{ "", "^z" },
{ "", "^B" },
{ "", "^G" },
{ "", "^R" },
{ "", "^Y" },
{ "", "^P" },
{ "", "^C" },
{ "", "^W" },
#elif defined(ACK)
/* built-in Ack! color */
{ "~~", "~" }, /* escape raw tildes */
{ "@@", "@ @" }, /* escape our color character */
{ "~!", "@@x" }, /* catch commonly used (but incorrect) codes */
{ "~!", "@@f" }, /* ditto */
{ "~!", "@@!" }, /* ditto */
{ "~!", "@@." }, /* ditto */
{ "~!", "@@n" }, /* ditto */
{ "~!", "@@i" }, /* ditto */
{ "~D", "@@k" }, /* black -> grey */
#elif defined(IMC_COLOR)
/* generic color; change as needed */
{ "~~", "~" }, /* escape raw tildes */
{ "{", "{{" }, /* escape our color character */
#else
/* no color support */
{ "~~", "~" }, /* escape raw tildes */
#endif
};
#define numtrans (sizeof(trans_table)/sizeof(trans_table[0]))
/* convert from imc color -> mud color */
const char *color_itom(const char *s)
{
char *buf=imc_getsbuf(IMC_DATA_LENGTH);
const char *current;
char *out;
int i, l;
int count;
for (current=s, out=buf, count=0; *current && count<IMC_DATA_LENGTH; )
{
if (*current=='~' || *current==IMC_COLORCHAR || *current==IMC_COLORCHAR2)
{
for (i=0; i<numtrans; i++)
{
l=strlen(trans_table[i].imc);
if (l && !strncmp(current, trans_table[i].imc, l))
break;
}
if (i!=numtrans) /* match */
{
int len;
len=strlen(trans_table[i].mud);
count+=len;
if (count >= IMC_DATA_LENGTH)
break;
memcpy(out, trans_table[i].mud, len);
out+=len;
current+=l;
continue;
}
}
*out++=*current++;
count++;
}
*out=0;
imc_shrinksbuf(buf);
return buf;
}
/* convert from mud color -> imc color */
const char *color_mtoi(const char *s)
{
char *buf=imc_getsbuf(IMC_DATA_LENGTH);
const char *current;
char *out;
int i, l;
int count;
for (current=s, out=buf, count=0; *current && count<IMC_DATA_LENGTH; )
{
if (*current=='~' || *current==IMC_COLORCHAR || *current==IMC_COLORCHAR2)
{
for (i=0; i<numtrans; i++)
{
l=strlen(trans_table[i].mud);
if (l && !strncmp(current, trans_table[i].mud, l))
break;
}
if (i!=numtrans) /* match */
{
int len;
len=strlen(trans_table[i].imc);
count+=len;
if (count>=IMC_DATA_LENGTH)
break;
memcpy(out, trans_table[i].imc, len);
out+=len;
current+=l;
continue;
}
}
*out++=*current++;
count++;
}
*out=0;
imc_shrinksbuf(buf);
return buf;
}
/* #ifdefs here are ugly, but will eventually disappear */
static struct {
int number;
const char *name;
const char *chatstr;
const char *emotestr;
long flag;
int minlevel;
char *to;
} channels[]=
{
#ifdef ACK
/* Ack!-specific formatting - ick */
{
0, /* channel number */
"RChat", /* channel name */
"@@W[@@yRCHAT@@W] @@a%s@@W:'@@g%s@@W'@@N\n\r", /* normal transmission */
"@@W[@@yRCHAT@@W] @@a%s@@W %s\n\r", /* format for emoting */
IMC_RCHAT, /* flag for this channel */
20, /* min. level to see it */
"*" /* muds to send to */
},
{
1,
"RImm",
"@@W[@@mRIMM@@W] @@a%s@@W:'@@g%s@@W'@@N\n\r",
"@@W[@@mRIMM@@W] @@a%s@@W %s\n\r",
IMC_RIMM,
L_SUP,
"*"
},
{
2,
"RInfo",
"@@W[@@aRINFO@@W] @@a%s@@W:'@@g%s@@W'@@N\n\r",
"@@W[@@aRINFO@@W] @@a%s@@W %s@@N\n\r",
IMC_RINFO,
L_SUP,
"*",
},
{
3,
"RCode",
"@@W[@@eRCODE@@W] @@a%s@@W:'@@g%s@@W'@@N\n\r",
"@@W[@@eRCODE@@W] @@a%s@@W %s@@N\n\r",
IMC_RCODE,
L_SUP,
"*"
},
/* Zen's inter-Ack! channel */
{
243,
"InterAck",
"@@W[@@pInterAck@@W] @@a%sWW@:'@@g%s@@W'@@N\n\r",
"@@W[@@pInterAck@@W] @@a%s@@W %s@@N\n\r",
IMC_INTERACK,
L_SUP,
"SOE SOETEST SOEBLD LCN LotS AA AABLD Jolly"
},
#else /* non-Ack! */
{
0, /* channel number */
"RChat", /* channel name */
"%s rchats '%s" _C(d) "'\n\r", /* format for normal transmission */
"[RChat] %s %s\n\r" _C(d), /* format for emoting */
IMC_RCHAT, /* flag for this channel */
5, /* min. level to see it */
"*" /* muds to send to */
},
{
1,
"RImm",
"%s rimms '%s" _C(d) "'\n\r",
"[RImm] %s %s\n\r" _C(d),
IMC_RIMM,
LEVEL_IMMORTAL,
"*"
},
{
2,
"RInfo",
/* why didn't I think of this? :) */
"%s announces '%s" _C(d) "'\n\r",
"[RInfo] %s %s\n\r" _C(d),
IMC_RINFO,
LEVEL_IMMORTAL,
"*",
},
{
3,
"RCode",
"%s rcodes '%s" _C(d) "'\n\r",
"[RCode] %s %s\n\r" _C(d),
IMC_RCODE,
LEVEL_IMMORTAL,
"*"
}
#endif /* #ifdef ACK */
/*
* An example of how to set up a channel that is only distributed between
* the three muds 'mud1', 'mud2', and 'mud3'.
{
76, -- channel number to use, change this!
"LocalChannel", -- the channel name
"%s localchannels '%s'\n\r", -- format for a normal message
"[LocalChannel] %s %s\n\r", -- format for an emote
IMC_LOCALCHANNEL, -- flag in imc_deaf, etc
LEVEL_IMMORTAL, -- min. level for channel
"mud1 mud2 mud3" -- muds to distribute to (include your own)
}
* (see the interack channel in #ifdef ACK, above, for an example)
*
*/
};
#define numchannels (sizeof(channels)/sizeof(channels[0]))
static int getlevel(int l)
{
if (l<LEVEL_HERO)
return l;
else
return l-MAX_LEVEL-1;
}
static const imc_char_data *getdata(CHAR_DATA *ch)
{
static imc_char_data d;
if (!ch) /* fake system character */
{
d.wizi=d.invis=d.see=0;
d.level=-1;
#if 0
d.sex=2;
#endif
strcpy(d.name, "*");
return &d;
}
#ifdef ROM
d.wizi=getlevel(ch->invis_level>ch->incog_level ?
ch->invis_level : ch->incog_level);
#elif defined(SMAUG)
d.wizi=getlevel(IS_SET(ch->act, PLR_WIZINVIS) ? ch->pcdata->wizinvis : 0);
#elif defined(ACK)
d.wizi=getlevel(IS_SET(ch->act, PLR_WIZINVIS) ? ch->invis : 0);
#else
d.wizi=getlevel(IS_SET(ch->act, PLR_WIZINVIS) ? get_trust(ch) : 0);
#endif
d.invis=0;
if (IS_AFFECTED(ch, AFF_INVISIBLE))
d.invis|=IMC_INVIS;
if (IS_AFFECTED(ch, AFF_SNEAK))
d.invis|=IMC_HIDDEN;
d.see=0;
if (IS_AFFECTED(ch, AFF_DETECT_INVIS))
d.see|=IMC_INVIS;
if (IS_AFFECTED(ch, AFF_DETECT_HIDDEN))
d.see|=IMC_HIDDEN;
d.level=getlevel(get_trust(ch));
strcpy(d.name, ch->name);
#if 0
d.sex=(ch->sex+1)%2;
#endif
return &d;
}
static int visible(const imc_char_data *viewer, const imc_char_data *viewed)
{
/* If you can follow this, you're better than me :) .. I've got it wrong
* at least 3 times now -- Spectrum
*/
return /* work out what they _can't_ see and invert - clearer like this */
!(
(viewer->level>=0 && /* mortal viewer */
(viewer->see & viewed->invis)!=viewed->invis) || /* cant see normally */
(viewed->wizi<0 && /* imm level wizi */
(viewer->level>=0 || /* mortal viewer */
viewer->level<viewed->wizi)) || /* imm less than wizi level */
(viewed->wizi>0 && /* mortal level wizi */
viewer->level>=0 && /* mortal viewer */
viewer->level<viewed->wizi) /* level less than wizi */
);
}
static const char *getname(CHAR_DATA *ch, const imc_char_data *vict)
{
const char *mud, *name;
const imc_char_data *chdata;
mud=imc_mudof(vict->name);
name=imc_nameof(vict->name);
chdata=getdata(ch);
if (!str_cmp(mud, imc_name))
#ifdef ACK
return visible(chdata,vict) ? imc_nameof(name)
: (chdata->wizi ? "A Mystical Being" : "someone");
#else
return visible(getdata(ch),vict) ? imc_nameof(name) : "someone";
#endif
else
{
if (visible(getdata(ch),vict))
return vict->name;
else
{
char *buf=imc_getsbuf(IMC_NAME_LENGTH);
#ifdef ACK
sprintf(buf, "%s@%s",
(getdata(ch))->wizi ? "A Mystical Being" : "someone", mud);
#else
sprintf(buf, "someone@%s", mud);
#endif
imc_shrinksbuf(buf);
return buf;
}
}
}
static void send_rchannel(CHAR_DATA *ch, char *argument, int number)
{
char arg[MAX_STRING_LENGTH];
char *arg2;
int chan;
CHECKIMC(ch);
for (chan=0; chan<numchannels; chan++)
if (channels[chan].number==number)
break;
if (chan==numchannels)
{
send_to_char("That channel doesn't seem to exist!\n\r", ch);
bug("IMC channel %d doesn't exist?!", number);
return; /* oops */
}
if (!CAN(ch, channels[chan].flag, channels[chan].minlevel))
{
sprintf(arg, "You are not authorised to use %s.\n\r",
channels[chan].name);
send_to_char(arg, ch);
return;
}
if (!argument[0])
{
if (IS_SET(ch->pcdata->imc_deaf, channels[chan].flag))
{
sprintf(arg, "%s channel is now ON.\n\r", channels[chan].name);
send_to_char(arg, ch);
REMOVE_BIT(ch->pcdata->imc_deaf, channels[chan].flag);
return;
}
sprintf(arg, "%s channel is now OFF.\n\r", channels[chan].name);
send_to_char(arg, ch);
SET_BIT(ch->pcdata->imc_deaf, channels[chan].flag);
return;
}
if (IS_NOCHAN(ch))
{
send_to_char("The gods have revoked your channel priviliges.\n\r", ch);
return;
}
#ifdef ROM
if (IS_SET(ch->comm, COMM_QUIET))
{
send_to_char("You must turn off quiet mode first.\n\r", ch);
return;
}
#endif
if (IS_SILENT(ch))
{
send_to_char ("You can't seem to break the silence.\n\r",ch);
return;
}
if (IS_RINVIS(ch))
{
send_to_char ("You cannot use IMC channels while invisible to IMC.\n\r", ch);
return;
}
REMOVE_BIT(ch->pcdata->imc_deaf, channels[chan].flag);
/* NargoRoth's bugfix here */
arg2=one_argument(argument, arg);
if (!str_cmp(arg, ",") || !str_cmp(arg, "emote"))
imc_send_emote(getdata(ch), number, color_mtoi(arg2), channels[chan].to);
else
imc_send_chat(getdata(ch), number, color_mtoi(argument),
channels[chan].to);
}
void do_rchat(CHAR_DATA *ch, char *argument)
{
send_rchannel(ch, argument, 0);
}
void do_rimm(CHAR_DATA *ch, char *argument)
{
send_rchannel(ch, argument, 1);
}
void do_rinfo(CHAR_DATA *ch, char *argument)
{
send_rchannel(ch, argument, 2);
}
void do_rcode(CHAR_DATA *ch, char *argument)
{
send_rchannel(ch, argument, 3);
}
#ifdef ACK
void do_interack(CHAR_DATA *ch, char *argument)
{
send_rchannel(ch, argument, 243);
}
#endif
void do_rtell(CHAR_DATA *ch, char *argument)
{
char buf[MAX_STRING_LENGTH], buf1[MAX_STRING_LENGTH];
CHECKIMC(ch);
argument=one_argument(argument, buf);
if (!buf[0] || !strchr(buf, '@') || !argument[0])
{
send_to_char("rtell who@where what?\n\r", ch);
return;
}
if (!CAN(ch, IMC_RTELL, IMC_LEVEL_RTELL))
{
send_to_char("You are not authorised to use rtell.\n\r", ch);
return;
}
if (IS_NOTELL(ch))
{
send_to_char("You cannot tell!\n\r", ch);
return;
}
if (IS_RINVIS(ch))
{
send_to_char ("You cannot rtell while invisible to IMC.\n\r", ch);
return;
}
if (IS_SET(ch->pcdata->imc_deaf, IMC_RTELL))
{
send_to_char("Enable incoming rtells first ('rchannel +rtell').\n\r", ch);
return;
}
#ifdef ACK
if (IS_SET(ch->pcdata->pflags, PFLAG_AFK))
{
send_to_char("Turn off AFK mode first.\n\r", ch);
return;
}
#endif
#ifdef ROM
if (IS_SET(ch->comm, COMM_AFK))
{
send_to_char("Turn off AFK mode first.\n\r", ch);
return;
}
if (IS_SET(ch->comm, COMM_QUIET))
{
send_to_char("You must turn off quiet mode first.\n\r", ch);
return;
}
if (IS_SET(ch->comm, COMM_DEAF))
{
send_to_char("You must turn off deaf mode first.\n\r", ch);
return;
}
#endif
CHECKMUDOF(ch, buf);
imc_send_tell(getdata(ch), buf, color_mtoi(argument), 0);
sprintf(buf1,
RTELL_FORMAT_1,
buf, argument);
send_to_char(buf1, ch);
}
void do_rreply(CHAR_DATA *ch, char *argument)
{
char buf1[MAX_STRING_LENGTH];
CHECKIMC(ch);
if (!ch->pcdata->rreply)
{
send_to_char("rreply to who?\n\r", ch);
return;
}
if (!argument[0])
{
send_to_char("rreply what?\n\r", ch);
return;
}
/* just check for deny, since you can rtell someone < IMC_LEVEL_RTELL */
if (IS_SET(ch->pcdata->imc_deny, IMC_RTELL))
{
send_to_char("You are not authorised to use rreply.\n\r", ch);
return;
}
if (IS_NOTELL(ch))
{
send_to_char("You cannot tell!\n\r", ch);
return;
}
if (IS_RINVIS(ch))
{
send_to_char ("You cannot rreply while invisible to IMC.\n\r", ch);
return;
}
if (IS_SET(ch->pcdata->imc_deaf, IMC_RTELL))
{
send_to_char("Enable incoming rtells first ('rchannel +rtell').\n\r", ch);
return;
}
#ifdef ACK
if (IS_SET(ch->pcdata->pflags, PFLAG_AFK))
{
send_to_char("Turn off AFK mode first.\n\r", ch);
return;
}
#endif
#ifdef ROM
if (IS_SET(ch->comm, COMM_AFK))
{
send_to_char("Turn off AFK mode first.\n\r", ch);
return;
}
if (IS_SET(ch->comm, COMM_QUIET))
{
send_to_char("You must turn off quiet mode first.\n\r", ch);
return;
}
if (IS_SET(ch->comm, COMM_DEAF))
{
send_to_char("You must turn off deaf mode first.\n\r",ch);
return;
}
#endif
CHECKMUDOF(ch, ch->pcdata->rreply);
imc_send_tell(getdata(ch), ch->pcdata->rreply, color_mtoi(argument), 1);
sprintf(buf1,
RTELL_FORMAT_1,
ch->pcdata->rreply_name, argument);
send_to_char(buf1, ch);
}
void do_rwho(CHAR_DATA *ch, char *argument)
{
char arg[MAX_STRING_LENGTH];
CHECKIMC(ch);
argument=one_argument(argument, arg);
if (!arg[0])
{
send_to_char("rwho where?\n\r", ch);
return;
}
CHECKMUD(ch, arg);
imc_send_who(getdata(ch), arg, argument[0] ? argument : "who");
}
void do_rwhois(CHAR_DATA *ch, char *argument)
{
char arg[MAX_STRING_LENGTH];
CHECKIMC(ch);
argument=one_argument(argument, arg);
if (!arg[0])
{
send_to_char("rwho whom?\n\r", ch);
return;
}
imc_send_whois(getdata(ch), arg);
}
void do_rfinger(CHAR_DATA *ch, char *argument)
{
char arg[MAX_STRING_LENGTH];
char name[MAX_STRING_LENGTH];
CHECKIMC(ch);
argument=one_argument(argument, arg);
if (!arg[0] || !strchr(arg, '@'))
{
send_to_char("rfinger who@where?\n\r", ch);
return;
}
CHECKMUD(ch, imc_mudof(arg));
sprintf(name, "finger %s", imc_nameof(arg));
imc_send_who(getdata(ch), imc_mudof(arg), name);
}
void do_rquery(CHAR_DATA *ch, char *argument)
{
char arg[MAX_STRING_LENGTH];
CHECKIMC(ch);
argument=one_argument(argument, arg);
if (!arg[0])
{
send_to_char("rquery where?\n\r", ch);
return;
}
CHECKMUD(ch, arg);
imc_send_who(getdata(ch), arg, argument[0] ? argument : "help");
}
void do_rbeep(CHAR_DATA *ch, char *argument)
{
char buf[MAX_STRING_LENGTH];
CHECKIMC(ch);
if (!argument[0] || !strchr(argument, '@'))
{
send_to_char("rbeep who@where?\n\r", ch);
return;
}
if (!CAN(ch, IMC_RBEEP, IMC_LEVEL_RBEEP))
{
send_to_char("You are not authorised to rbeep.\n\r", ch);
return;
}
if (IS_NOTELL(ch))
{
send_to_char("You cannot beep!\n\r", ch);
return;
}
if (IS_RINVIS(ch))
{
send_to_char ("You cannot rbeep while invisible to IMC.\n\r", ch);
return;
}
#ifdef ROM
if (IS_SET(ch->comm, COMM_QUIET))
{
send_to_char("You must turn off quiet mode first.\n\r", ch);
return;
}
if (IS_SET(ch->comm, COMM_DEAF))
{
send_to_char("You must turn off deaf mode first.\n\r", ch);
return;
}
#endif
CHECKMUDOF(ch, argument);
imc_send_beep(getdata(ch), argument);
sprintf(buf, RBEEP_FORMAT_1, argument);
send_to_char(buf, ch);
}
void do_imclist(CHAR_DATA *ch, char *argument)
{
if (!argument[0])
page_to_char(imc_list(3), ch);
else if (!str_prefix(argument, "direct"))
{
if (get_trust(ch)>=MAX_LEVEL-1)
page_to_char(imc_list(2), ch);
else if (IS_IMMORTAL(ch))
page_to_char(imc_list(1), ch);
else
page_to_char(imc_list(0), ch);
}
else if (!str_prefix(argument, "config"))
{
if (IS_IMMORTAL(ch))
page_to_char(imc_list(5), ch);
else
page_to_char(imc_list(4), ch);
}
else
send_to_char("Unknown option.", ch);
send_to_char("\n\r", ch);
}
void do_rsockets(CHAR_DATA *ch, char *argument)
{
CHECKIMC(ch);
page_to_char(imc_sockets(), ch);
}
void do_imc(CHAR_DATA *ch, char *argument)
{
int r;
r=imc_command(argument);
if (r>0)
{
send_to_char("Ok.\n\r", ch);
return;
}
else if (r==0)
{
send_to_char("Syntax: imc add <mudname>\n\r"
" imc delete <mudname>\n\r"
" imc set <mudname> all <host> <port> <clientpw> <serverpw>\n\r"
" <rcvstamp> <noforward> <flags>\n\r"
" imc set <mudname> host|port|clientpw|serverpw|rcvstamp|\n\r"
" noforward|flags <value>\n\r"
" imc rename <oldmudname> <newmudname>\n\r"
" imc localname <mudname>\n\r"
" imc localport <portnum>\n\r"
" imc reload\n\r",
ch);
return;
}
send_to_char(imc_error(), ch);
send_to_char("\n\r", ch);
}
void do_rignore(CHAR_DATA *ch, char *argument)
{
send_to_char(imc_ignore(argument), ch);
send_to_char("\n\r", ch);
}
void do_rconnect(CHAR_DATA *ch, char *argument)
{
CHECKIMC(ch);
if (!argument[0])
{
send_to_char("rconnect to where?\n\r", ch);
return;
}
if (imc_connect_to(argument))
{
send_to_char("Ok.\n\r", ch);
return;
}
send_to_char(imc_error(), ch);
send_to_char("\n\r", ch);
}
void do_rdisconnect(CHAR_DATA *ch, char *argument)
{
CHECKIMC(ch);
if (!argument[0])
{
send_to_char("rdisconnect where?\n\r", ch);
return;
}
if (imc_disconnect(argument))
{
send_to_char("Ok.\n\r", ch);
return;
}
send_to_char(imc_error(), ch);
send_to_char("\n\r", ch);
}
void do_mailqueue(CHAR_DATA *ch, char *argument)
{
CHECKIMC(ch);
page_to_char(imc_mail_showqueue(), ch);
}
void do_istats(CHAR_DATA *ch, char *argument)
{
CHECKIMC(ch);
send_to_char(imc_getstats(), ch);
}
void do_rchannels(CHAR_DATA *ch, char *argument)
{
char buf[MAX_STRING_LENGTH];
char arg[MAX_STRING_LENGTH];
bool toggle;
int i;
const char *name;
long flag;
if (IS_NPC(ch))
{
send_to_char("NPCs cannot use IMC.\n\r", ch);
return;
}
one_argument(argument, arg);
if (!arg[0])
{
/* list channel status */
bool found=FALSE;
strcpy(buf,
"channel status\n\r"
"-------------------\n\r");
for (i=0; i<numchannels; i++)
{
if (IS_SET(ch->pcdata->imc_deny, channels[i].flag))
{
sprintf(buf+strlen(buf),
"%-10s : you are denied from this channel.\n\r",
channels[i].name);
found=TRUE;
}
else if (CAN(ch, channels[i].flag, channels[i].minlevel))
{
sprintf(buf+strlen(buf),
"%-10s : %s\n\r",
channels[i].name,
(IS_SET(ch->pcdata->imc_deaf, channels[i].flag) ?
"OFF" : "ON"));
found=TRUE;
}
}
if (IS_SET(ch->pcdata->imc_deny, IMC_RTELL))
{
strcat(buf, "RTells : you cannot rtell.\n\r");
found=TRUE;
}
else if (CAN(ch, IMC_RTELL, IMC_LEVEL_RTELL))
{
sprintf(buf+strlen(buf), "%-10s : %s\n\r", "RTell",
IS_SET(ch->pcdata->imc_deaf, IMC_RTELL) ? "OFF" : "ON");
found=TRUE;
}
if (IS_SET(ch->pcdata->imc_deny, IMC_RBEEP))
{
strcat(buf, "RBeeps : you cannot rbeep.\n\r");
found=TRUE;
}
else if (CAN(ch, IMC_RBEEP, IMC_LEVEL_RBEEP))
{
sprintf(buf+strlen(buf), "%-10s : %s\n\r", "RBeep",
IS_SET(ch->pcdata->imc_deaf, IMC_RBEEP) ? "OFF" : "ON");
found=TRUE;
}
if (IS_SET(ch->pcdata->imc_deaf, IMC_RINVIS))
sprintf(buf+strlen(buf), "You are not visible to others over IMC.\n\r");
if (!found)
send_to_char("You have access to no IMC channels.\n\r", ch);
else
send_to_char(buf, ch);
return;
}
/* turn some things on or off */
while((argument=one_argument(argument, arg)), arg[0])
{
if (arg[0]=='-')
toggle=FALSE;
else if (arg[0]=='+')
toggle=TRUE;
else
{
send_to_char("Syntax: rchannels displays current IMC channels\n\r"
" rchannels +chan turn on a channel\n\r"
" rchannels -chan turn off a channel\n\r"
"chan may be an IMC channel name, 'rbeep', 'rtell', 'rinvis', or 'all'.\n\r"
"Multiple settings may be given in one command.\n\r", ch);
return;
}
if (!str_cmp(arg+1, "all"))
{
if (toggle)
{
send_to_char("ALL available IMC channels are now on.\n\r", ch);
ch->pcdata->imc_deaf=0;
}
else
{
send_to_char("ALL available IMC channels are now off.\n\r", ch);
ch->pcdata->imc_deaf=-1L;
}
continue;
}
else if (!str_cmp(arg+1, "rtell") && CAN(ch, IMC_RTELL, IMC_LEVEL_RTELL))
{
name="RTell";
flag=IMC_RTELL;
}
else if (!str_cmp(arg+1, "rbeep") && CAN(ch, IMC_RBEEP, IMC_LEVEL_RBEEP))
{
name="RBeep";
flag=IMC_RBEEP;
}
else if (!str_cmp(arg+1, "rinvis"))
{
name="RInvis";
flag=IMC_RINVIS;
toggle=!toggle;
}
else
{
for (i=0; i<numchannels; i++)
{
if (CAN(ch, channels[i].flag, channels[i].minlevel) &&
!str_cmp(channels[i].name, arg+1))
break;
}
if (i==numchannels)
{
sprintf(buf, "You don't have access to an IMC channel called \"%s\".\n\r", arg);
send_to_char(buf, ch);
continue;
}
name=channels[i].name;
flag=channels[i].flag;
}
if (toggle && !IS_SET(ch->pcdata->imc_deaf, flag))
{
if (flag==IMC_RINVIS)
strcpy(buf, "You are already visible on IMC.\n\r");
else
sprintf(buf, "%s is already on.\n\r", name);
send_to_char(buf, ch);
continue;
}
if (!toggle && IS_SET(ch->pcdata->imc_deaf, flag))
{
if (flag==IMC_RINVIS)
strcpy(buf, "You are already invisible on IMC.\n\r");
else
sprintf(buf, "%s is already off.\n\r", name);
send_to_char(buf, ch);
continue;
}
if (toggle)
{
if (flag==IMC_RINVIS)
strcpy(buf, "You are no longer invisible to IMC.\n\r");
else
sprintf(buf, "%s is now ON.\n\r", name);
REMOVE_BIT(ch->pcdata->imc_deaf, flag);
}
else
{
if (flag==IMC_RINVIS)
strcpy(buf, "You are now invisible to rwho, rtell and rbeep on IMC.\n\r");
else
sprintf(buf, "%s is now OFF.\n\r", name);
SET_BIT(ch->pcdata->imc_deaf, flag);
}
send_to_char(buf, ch);
}
}
void do_rchanset(CHAR_DATA *ch, char *argument)
{
char arg[MAX_STRING_LENGTH];
CHAR_DATA *victim;
int flag, i;
const char *name;
int fn;
bool found=FALSE;
char buf[MAX_STRING_LENGTH];
argument=one_argument(argument, arg);
if (!arg[0])
{
send_to_char("Syntax: rchanset <char> - check flag settings\n\r"
" rchanset <char> +<channel> - set allow flag\n\r"
" rchanset <char> -<channel> - set deny flag\n\r"
" rchanset <char> =<channel> - reset allow/deny\n\r",
ch);
return;
}
if (!(victim=get_char_world(ch, arg)))
{
send_to_char("They're not here.\n\r", ch);
return;
}
if (IS_NPC(victim))
{
send_to_char("Can't set rchannel status on NPCs.\n\r", ch);
return;
}
if (get_trust(victim) >= get_trust(ch))
{
send_to_char("You failed.\n\r", ch);
return;
}
if (!argument[0])
{
sprintf(buf,
"%s's IMC channel flags:\n\r"
"------------------------------\n\r",
victim->name);
for (i=0; i<numchannels; i++)
{
if (IS_SET(victim->pcdata->imc_allow, channels[i].flag))
{
sprintf(buf+strlen(buf), "%-10s : allow flag set.\n\r",
channels[i].name);
found=TRUE;
}
if (IS_SET(victim->pcdata->imc_deny, channels[i].flag))
{
sprintf(buf+strlen(buf), "%-10s : deny flag set.\n\r",
channels[i].name);
found=TRUE;
}
}
if (IS_SET(victim->pcdata->imc_allow, IMC_RTELL))
{
sprintf(buf+strlen(buf), "%-10s : allow flag set.\n\r",
"RTell");
found=TRUE;
}
if (IS_SET(victim->pcdata->imc_deny, IMC_RTELL))
{
sprintf(buf+strlen(buf), "%-10s : deny flag set.\n\r",
"RTell");
found=TRUE;
}
if (IS_SET(victim->pcdata->imc_allow, IMC_RBEEP))
{
sprintf(buf+strlen(buf), "%-10s : allow flag set.\n\r",
"RBeep");
found=TRUE;
}
if (IS_SET(victim->pcdata->imc_deny, IMC_RBEEP))
{
sprintf(buf+strlen(buf), "%-10s : deny flag set.\n\r",
"RBeep");
found=TRUE;
}
if (!found)
sprintf(buf, "%s has no IMC flags set.\n\r", victim->name);
send_to_char(buf, ch);
return;
}
if (argument[0]=='-')
fn=0;
else if (argument[0]=='+')
fn=1;
else if (argument[0]=='=')
fn=2;
else
{
send_to_char("Channel name must be preceeded by +, -, or =.\n\r", ch);
return;
}
argument++;
if (!str_cmp(argument, "rtell"))
{
flag=IMC_RTELL;
name="RTell";
}
else if (!str_cmp(argument, "rbeep"))
{
flag=IMC_RBEEP;
name="RBeep";
}
else
{
for (i=0; i<numchannels; i++)
if (!str_cmp(channels[i].name, argument))
break;
if (i==numchannels)
{
send_to_char("No such channel.\n\r", ch);
return;
}
flag=channels[i].flag;
name=channels[i].name;
}
switch(fn)
{
case 0: /* set deny flag */
if (IS_SET(victim->pcdata->imc_deny, flag))
{
send_to_char("Deny flag already set.\n\r", ch);
return;
}
SET_BIT(victim->pcdata->imc_deny, flag);
REMOVE_BIT(victim->pcdata->imc_allow, flag);
sprintf(buf, "The gods have revoked your %s priviliges.\n\r", name);
send_to_char(buf, victim);
send_to_char("Ok.\n\r", ch);
#ifdef ROM
sprintf(buf, "$N revokes %s's access to %s.", victim->name, name);
wiznet(buf, ch, NULL, WIZ_PENALTIES, WIZ_SECURE, 0);
#endif
return;
case 1: /* set allow flag */
if (IS_SET(victim->pcdata->imc_allow, flag))
{
send_to_char("Allow flag already set.\n\r", ch);
return;
}
SET_BIT(victim->pcdata->imc_allow, flag);
REMOVE_BIT(victim->pcdata->imc_deny, flag);
sprintf(buf, "The gods have allowed you access to %s.\n\r", name);
send_to_char(buf, victim);
send_to_char("Ok.\n\r", ch);
#ifdef ROM
sprintf(buf, "$N allows %s access to %s.", victim->name, name);
wiznet(buf, ch, NULL, WIZ_PENALTIES, WIZ_SECURE, 0);
#endif
return;
case 2: /* clears flags */
if (IS_SET(victim->pcdata->imc_allow, flag))
{
REMOVE_BIT(victim->pcdata->imc_allow, flag);
sprintf(buf, "The gods have removed your special access to %s.\n\r",
name);
send_to_char(buf, victim);
#ifdef ROM
sprintf(buf, "$N removes %s's access to %s.", victim->name, name);
wiznet(buf, ch, NULL, WIZ_PENALTIES, WIZ_SECURE, 0);
#endif
found=TRUE;
}
if (IS_SET(victim->pcdata->imc_deny, flag))
{
REMOVE_BIT(victim->pcdata->imc_deny, flag);
sprintf(buf, "The gods have restored your %s priviliges.\n\r", name);
send_to_char(buf, victim);
#ifdef ROM
sprintf(buf, "$N restores %s to %s.", name, victim->name);
wiznet(buf, ch, NULL, WIZ_PENALTIES, WIZ_SECURE, 0);
#endif
found=TRUE;
}
if (!found)
send_to_char("They have no flags to clear.\n\r", ch);
else
send_to_char("Ok.\n\r", ch);
return;
}
}
/* renamed from do_rchannel */
static void do_imcchannel(const imc_char_data *from, int number,
const char *argument, int emote)
{
DESCRIPTOR_DATA *d;
CHAR_DATA *victim;
const char *str;
const char *arg;
char buf[IMC_DATA_LENGTH];
int chan;
for (chan=0; chan<numchannels; chan++)
if (channels[chan].number==number)
break;
if (chan==numchannels)
return;
str=emote ? channels[chan].emotestr : channels[chan].chatstr;
arg=color_itom(argument);
for (d=descriptor_list; d; d=d->next)
{
if (d->connected==CON_PLAYING &&
(victim=d->original ? d->original : d->character)!=NULL &&
#ifdef ROM
!IS_SET(victim->comm, COMM_QUIET) &&
#endif
!IS_SILENT(victim) &&
!IS_SET(victim->pcdata->imc_deaf, channels[chan].flag) &&
CAN(victim, channels[chan].flag, channels[chan].minlevel))
{
#if NO_VSNPRINTF
sprintf(buf, str, getname(victim, from), arg);
#else
snprintf(buf, IMC_DATA_LENGTH, str, getname(victim, from), arg);
#endif
send_to_char(buf, victim);
}
}
}
void imc_recv_chat(const imc_char_data *from, int channel,
const char *argument)
{
do_imcchannel(from, channel, argument, 0);
}
void imc_recv_emote(const imc_char_data *from, int channel,
const char *argument)
{
do_imcchannel(from, channel, argument, 1);
}
/* new imc_whoreply_* support, see imc-interp.c */
/* expanded for minimal mud-specific code. I really don't want to replicate
* stock in-game who displays here, since it's one of the most commonly
* changed pieces of code. shrug.
*/
static void process_rwho(const imc_char_data *from, const char *argument)
{
CHAR_DATA *victim;
int count=0;
char output[MAX_STRING_LENGTH];
DESCRIPTOR_DATA *d;
imc_whoreply_start(from->name);
#ifdef ACK
imc_whoreply_add(color_mtoi("@@RWho's Playing " mudnamecolor ":\n\r"));
#endif
for (d = descriptor_list; d; d = d->next)
{
victim = ( d->original ) ? d->original : d->character;
if (d->connected != CON_PLAYING || !visible(from, getdata(victim)) ||
IS_RINVIS(victim) || IS_NPC(victim))
continue;
count++;
#ifdef ACK
sprintf(output,
"@@W[@@p%s@@W] @@G%s@@N%s@@N\n\r",
((IS_IMMORTAL(victim) ||
(victim->adept_level>0)) ? victim->pcdata->who_name
: is_remort(victim) ? " @@mREMORT@@N "
: " @@cMORTAL@@N "),
victim->name, victim->pcdata->title);
#else
sprintf(output, "%s%s\n\r",
victim->name,
victim->pcdata->title);
#endif
imc_whoreply_add(color_mtoi(output));
}
sprintf(output, "\n\rRWHO for %s [%d players found]\n\r", imc_name, count);
imc_whoreply_add(output);
imc_whoreply_end();
}
/* edit this if you want to support rfinger */
static void process_rfinger(const imc_char_data *from, const char *argument)
{
imc_send_whoreply(from->name,
"Sorry, no information is available of that type.\n\r", -1);
}
void imc_recv_who(const imc_char_data *from, const char *type)
{
char arg[MAX_STRING_LENGTH];
char output[MAX_STRING_LENGTH];
type=imc_getarg(type, arg, MAX_STRING_LENGTH);
if (!str_cmp(arg, "who"))
{
process_rwho(from, type);
return;
}
else if (!str_cmp(arg, "finger"))
{
process_rfinger(from, type);
return;
}
else if (!str_cmp(arg, "info"))
strcpy(output, IMC_MUD_INFO);
else if (!str_cmp(arg, "list"))
strcpy(output, imc_list(3));
else if (!str_cmp(arg, "config"))
strcpy(output, imc_list(4));
else if (!str_cmp(arg, "direct"))
strcpy(output, imc_list(0));
else if (!str_cmp(arg, "options") ||
!str_cmp(arg, "services") ||
!str_cmp(arg, "help"))
strcpy(output,
"Available rquery types:\n\r"
"help - this list\n\r"
"who - who listing\n\r"
"info - mud information\n\r"
"list - active IMC connections\n\r"
"direct - direct IMC connections\n\r"
"config - local IMC configuration\n\r"
/* uncomment if you support rfinger */
/* "finger xxx - finger player xxx\n\r" */
);
else
strcpy(output, "Sorry, no information is available of that type.\n\r");
imc_send_whoreply(from->name, color_mtoi(output), -1);
}
void imc_recv_whoreply(const char *to, const char *text, int sequence)
{
DESCRIPTOR_DATA *d;
CHAR_DATA *victim;
for (d=descriptor_list; d; d=d->next)
{
if (d->connected==CON_PLAYING &&
(victim=d->original ? d->original : d->character)!=NULL &&
is_name((char *)to, victim->name))
{
page_to_char(color_itom(text), victim);
return;
}
}
}
void imc_recv_whois(const imc_char_data *from, const char *to)
{
DESCRIPTOR_DATA *d;
CHAR_DATA *victim;
char buf[MAX_STRING_LENGTH];
for (d=descriptor_list; d; d = d->next)
{
if (d->connected==CON_PLAYING &&
(victim = d->original ? d->original : d->character)!=NULL &&
!IS_NPC(victim) &&
!IS_RINVIS(victim) && /* ADD IN CHECK FOR !IS_RINVIS, thanks Titania@aa/Sylvana@lcn */
visible(from, getdata(victim)) &&
(!str_cmp(to, victim->name) ||
(strlen(to)>3 && !str_prefix(to, victim->name))))
{
sprintf(buf, "rwhois %s : %s@%s is online.\n\r", to,
victim->name, imc_name);
imc_send_whoisreply(from->name, buf);
}
}
}
void imc_recv_whoisreply(const char *to, const char *text)
{
DESCRIPTOR_DATA *d;
CHAR_DATA *victim;
for (d=descriptor_list; d; d=d->next)
{
if (d->connected==CON_PLAYING &&
(victim=d->original ? d->original : d->character)!=NULL &&
!str_cmp((char *)to, victim->name))
{
send_to_char(color_itom(text), victim);
return;
}
}
}
void imc_recv_tell(const imc_char_data *from, const char *to,
const char *argument, int isreply)
{
DESCRIPTOR_DATA *d;
CHAR_DATA *victim, *vch;
char buf[IMC_DATA_LENGTH];
if (!strcmp(to, "*")) /* ignore messages to system */
return;
victim=NULL;
for (d=descriptor_list; d; d=d->next)
{
if (d->connected==CON_PLAYING &&
(vch=d->original ? d->original : d->character)!=NULL &&
!IS_NPC(vch) && /* sanity check */
!IS_RINVIS(vch) &&
(isreply || visible(from, getdata(vch))))
{
if (!str_cmp((char *)to, vch->name))
{
victim=vch;
break;
}
if (is_name((char *)to, vch->name))
victim=vch;
}
}
if (victim)
{
if (IS_SET(victim->pcdata->imc_deaf, IMC_RTELL) ||
#ifdef ROM
IS_SET(victim->comm, COMM_QUIET) ||
IS_SET(victim->comm, COMM_DEAF) ||
#endif
#ifdef ACK
IS_SET(victim->pcdata->pflags, PFLAG_AFK) ||
#endif
IS_SILENT(victim) ||
IS_SET(victim->pcdata->imc_deny, IMC_RTELL))
{
if (str_cmp(imc_nameof(from->name), "*"))
{
sprintf(buf, "%s is not receiving tells.", to);
imc_send_tell(NULL, from->name, buf, 1);
}
return;
}
#ifdef ROM
if (IS_SET(victim->comm, COMM_AFK) &&
str_cmp(imc_nameof(from->name), "*"))
{
sprintf(buf, "%s is AFK, but your tell will go through when they "
"return.", to);
imc_send_tell(NULL, from->name, buf, 1);
}
else if (!victim->desc &&
str_cmp(imc_nameof(from->name), "*"))
{
sprintf(buf, "%s is switched, but your tell will go through when "
"they return.", to);
imc_send_tell(NULL, from->name, buf, 1);
}
#endif
if (str_cmp(imc_nameof(from->name), "*")) /* not a system message */
{
if (victim->pcdata->rreply)
imc_strfree(victim->pcdata->rreply);
if (victim->pcdata->rreply_name)
imc_strfree(victim->pcdata->rreply_name);
victim->pcdata->rreply=imc_strdup(from->name);
victim->pcdata->rreply_name=imc_strdup(getname(victim, from));
}
#if NO_VSNPRINTF
sprintf(buf,
RTELL_FORMAT_2,
getname(victim, from),
color_itom(argument));
#else
snprintf(buf, IMC_DATA_LENGTH,
RTELL_FORMAT_2,
getname(victim, from), color_itom(argument));
#endif
#ifdef ROM
if (IS_SET(victim->comm, COMM_AFK) || !victim->desc)
add_buf(victim->pcdata->buffer, buf);
else
page_to_char(buf, victim);
#else
page_to_char(buf, victim);
#endif
}
else
{
sprintf(buf, "%s is not here.", to);
imc_send_tell(NULL, from->name, buf, 1);
}
}
void imc_recv_beep(const imc_char_data *from, const char *to)
{
DESCRIPTOR_DATA *d;
CHAR_DATA *victim, *vch;
char buf[IMC_DATA_LENGTH];
if (!strcmp(to, "*")) /* ignore messages to system */
return;
victim=NULL;
for (d=descriptor_list; d; d=d->next)
{
if (d->connected==CON_PLAYING &&
(vch=d->original ? d->original : d->character)!=NULL &&
!IS_RINVIS(vch) &&
visible(from, getdata(vch)))
{
if (!str_cmp((char *)to, vch->name))
{
victim=vch;
break;
}
if (is_name((char *)to, vch->name))
victim=vch;
}
}
if (victim)
{
if (IS_SET(victim->pcdata->imc_deaf, IMC_RBEEP) ||
IS_SILENT(victim) ||
!CAN(victim, IMC_RTELL, IMC_LEVEL_RTELL))
{
sprintf(buf, "%s is not receiving beeps.", to);
imc_send_tell(NULL, from->name, buf, 1);
return;
}
/* always display the true name here */
sprintf(buf, RBEEP_FORMAT_2, from->name);
send_to_char(buf, victim);
}
else
{
sprintf(buf, "%s is not here", to);
imc_send_tell(NULL, from->name, buf, 1);
}
}
/** IMC MAIL **/
/* shell for sending IMC mail */
void imc_post_mail(CHAR_DATA *from,
const char *sender,
const char *to_list,
const char *subject,
const char *date,
const char *text)
{
char arg[MAX_STRING_LENGTH];
const char *temp;
CHECKIMC(from);
if (!strchr(to_list, '@'))
return;
for (temp=one_argument((char *)to_list, arg); arg[0]; /* blech */
temp=one_argument((char *)temp, arg))
if (strchr(arg, '@'))
CHECKMUD(from, imc_mudof(arg));
imc_send_mail(sender, to_list, subject, date, color_mtoi(text));
}
/* Since there are half-a-dozen different ways that people do this, I'm
* sticking to the stock code, plus Erwin's board system.
*/
#ifdef SMAUG
/*
* Find the IMC mail board. It SHOULD exist.. :)
*/
BOARD_DATA *imc_find_board(void)
{
BOARD_DATA *board;
for (board = first_board; board; board = board->next)
if (board->board_obj == sysdata.imc_mail_vnum)
return board;
return NULL;
}
char *imc_mail_arrived (const char *from, const char *to, const char *date,
const char *subject, const char *text)
{
void write_board(BOARD_DATA *board);
BOARD_DATA *board;
NOTE_DATA *pnote;
char buf[MAX_STRING_LENGTH];
/* don't let people write to 'all' over IMC */
/* yeesh, why doesn't anyone maintain 'const'-ness any more? */
if (is_name("all", (char *)to))
return "Notes to 'all' are not accepted.";
if ( !(board = imc_find_board()) )
return "Could not find the IMC board.";
if ( board->num_posts >= board->max_posts )
return "There is no room on the IMC board to post your note.";
CREATE( pnote, NOTE_DATA, 1 );
/* Smash all the tildes, just in case
* This is a complete mess, but smaug's string hasher would do bad things
* if we smash_tilde'd a STRALLOC'd string..
*/
#define SET_STR(new, old) \
do { \
strcpy(buf, old); \
smash_tilde(buf); \
pnote->new = STRALLOC(buf); \
} while(0)
SET_STR(sender, from);
SET_STR(to_list, to);
SET_STR(date, date);
SET_STR(subject, color_itom(subject));
SET_STR(text, text);
#undef SET_STR
pnote->voting = 0;
pnote->yesvotes = str_dup("");
pnote->novotes = str_dup("");
pnote->abstentions = str_dup("");
LINK(pnote, board->first_note, board->last_note, next, prev);
board->num_posts++;
write_board( board );
return NULL; /* Errors? What errors? <G> */
}
#endif /* SMAUG */
#if defined(ACK)
/* Added support for ackmud boards.
* You must configure IMC_BOARD_PUBLIC and IMC_BOARD_IMMORTAL
* in imc-mercbase.h to suit your mud!
*/
#ifndef IMC_BOARD_PUBLIC
#error You must #define a value for IMC_BOARD_VNUM in imc-mercbase.h!
#endif
#ifndef IMC_BOARD_IMMORTAL
#error You must #define a value for IMC_BOARD_VNUM in imc-mercbase.h!
#endif
char *imc_mail_arrived(const char *from, const char *to, const char *date,
const char *subject, const char *text)
{
BOARD_DATA *board;
MESSAGE_DATA *msg;
char buf[MAX_STRING_LENGTH];
const char *temp=to;
int vnum;
int toimm=0;
char toname[MAX_STRING_LENGTH];
toname[0]=0;
while ((temp=imc_getarg(temp, buf, MAX_STRING_LENGTH)), buf[0])
{
if (!strchr(buf, '@'))
{
if (toname[0])
return "Sorry, multiple to: names over IMC are not supported here.";
strcpy(toname, buf);
}
}
if (str_cmp("all", toname))
return "Notes to 'all' are not accepted.";
if (str_cmp("immortal", toname) || str_cmp("imm", toname) ||
str_cmp("imms", toname) || str_cmp("immortals", toname))
{
vnum=IMC_BOARD_IMMORTAL;
toimm=1;
}
else
vnum=IMC_BOARD_PUBLIC;
/* First find the board, and if not there, create one. */
for (board=first_board; board != NULL; board=board->next)
{
if (board->vnum==vnum)
break;
}
if (board==NULL)
{
/* uh oh.. */
OBJ_INDEX_DATA *pObj;
int i;
for (i=0; i<MAX_KEY_HASH; i++)
for (pObj=obj_index_hash[i]; pObj; pObj=pObj->next)
if (pObj->item_type==ITEM_BOARD && pObj->value[3]==vnum)
break;
if (!pObj)
return "Couldn't find a board to post the note on.";
board=load_board(pObj);
}
GET_FREE(msg, message_free);
msg->datetime=time(NULL);
/* erk.. this is messy.
* assume that notes to 'immortal' are public
* assume that anything else is private
*/
if (toimm)
sprintf(buf, "%s @@a%s@@N\n\r", subject, date);
else
sprintf(buf, "to: %s @@a%s@@N\n\r", toname, date);
msg->title=str_dup(buf);
msg->author=str_dup(from);
msg->board=board;
msg->message=str_dup(color_itom(text));
LINK(msg, board->first_message, board->last_message, next, prev);
return NULL;
}
#endif /* ACK */
/* #define ERWIN -- to use the code for Erwin's boards */
#if defined(MERC) || defined(ROM) || defined(ENVY)
#if !defined(ERWIN)
/* post a note; currently all rnotes go to the default note spool */
char *imc_mail_arrived(const char *from, const char *to, const char *date,
const char *subject, const char *text)
{
NOTE_DATA *pnote;
#if defined(MERC) || defined(ENVY)
NOTE_DATA *prev_note;
FILE *fp;
#endif
/* don't let people write to 'all' over IMC */
/* yeesh, why doesn't anyone maintain 'const'-ness any more? */
if (is_name("all", (char *)to))
return "Notes to 'all' are not accepted.";
#ifdef ROM
pnote=new_note();
pnote->type=NOTE_NOTE;
#else
pnote=alloc_perm(sizeof(*pnote));
#endif
pnote->sender=str_dup(from);
pnote->to_list=str_dup(to);
pnote->date=str_dup(date);
pnote->subject=str_dup(subject);
pnote->text=str_dup(color_itom(text));
pnote->date_stamp=current_time;
pnote->next=NULL;
/* a bit of paranoia re. tildes here.. */
smash_tilde(pnote->sender);
smash_tilde(pnote->to_list);
smash_tilde(pnote->date);
smash_tilde(pnote->subject);
smash_tilde(pnote->text);
#ifdef ROM
append_note(pnote);
#else
if (!note_list)
{
note_list = pnote;
}
else
{
for (prev_note = note_list; prev_note->next; prev_note = prev_note->next)
;
prev_note->next = pnote;
}
fclose (fpReserve);
if (!(fp = fopen (NOTE_FILE, "a")))
{
perror (NOTE_FILE);
fpReserve = fopen (NULL_FILE, "r");
return "Couldn't open the note file";
}
else
{
fprintf (fp, "Sender %s~\n", pnote->sender);
fprintf (fp, "Date %s~\n", pnote->date);
fprintf (fp, "Stamp %ld\n", (unsigned long) pnote->date_stamp);
fprintf (fp, "To %s~\n", pnote->to_list);
fprintf (fp, "Subject %s~\n", pnote->subject);
fprintf (fp, "Text\n%s~\n\n", pnote->text);
fclose (fp);
}
fpReserve = fopen (NULL_FILE, "r");
#endif
return NULL; /* Errors? What errors? <G> */
}
#else
/*
* If you are using my code (ftp://pip.dknet.dk/pub/pip1773/board-2.tgz)
* there is another imc_mail_arrived() below - Erwin
*
* Note that this assumes that your make_note() does a smash_tilde(), the
* latest version of the board snippet does, but your may not. Oh well.
*/
char *imc_mail_arrived (const char *from, const char *to, const char *date,
const char *subject, const char *text)
{
/* don't let people write to 'all' over IMC */
/* yeesh, why doesn't anyone maintain 'const'-ness any more? */
if (is_name("all", (char *)to))
return "Notes to 'all' are not accepted.";
make_note ("Personal", from, to, subject, 14, color_itom(text));
return NULL;
}
#endif /* Erwin's board code */
#endif /* merc/rom/envy */
void imc_log(const char *string)
{
char buf[MAX_STRING_LENGTH];
sprintf(buf, "imc: %s", string);
log_string(buf);
#ifdef ACK
monitor_chan(buf, MONITOR_CONNECT);
#endif
#ifdef ROM
/* ick, wiznet is a bit broken wrt. passing non-objects to act..
* it should really take a void * as its 3rd argument
*/
wiznet("imc: $t", NULL, (OBJ_DATA *)string, WIZ_IMC, 0, 0);
#endif
}
void imc_debug(const imc_connect *c, int out, const char *string)
{
#ifdef ROM
char buf[MAX_STRING_LENGTH];
char *dir;
dir=out ? "<" : ">";
/* chop to 130 chars (should fit on 2 lines) */
sprintf(buf, "%s %s %-.130s", imc_getconnectname(c), dir, string);
wiznet("$t", NULL, (OBJ_DATA *)buf, WIZ_IMCDEBUG, 0, 0);
#endif
}