/**************************************************************************
* Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, *
* Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe. *
* *
* Merc Diku Mud improvements copyright (C) 1992, 1993 by Michael *
* Chastain, Michael Quan, and Mitchell Tse. *
* *
* In order to use any part of this Merc Diku Mud, you must comply with *
* both the original Diku license in 'license.doc' as well the Merc *
* license in 'license.txt'. In particular, you may not remove either of *
* these copyright notices. *
* *
* Much time and thought has gone into this software and you are *
* benefiting. We hope that you share your changes too. What goes *
* around, comes around. *
***************************************************************************
* ROM 2.4 is copyright 1993-1998 Russ Taylor *
* ROM has been brought to you by the ROM consortium *
* Russ Taylor (rtaylor@hypercube.org) *
* Gabrielle Taylor (gtaylor@hypercube.org) *
* Brian Moore (zump@rom.org) *
* By using this code, you have agreed to follow the terms of the *
* ROM license, in the file Rom24/doc/rom.license *
***************************************************************************
* 1stMud ROM Derivative (c) 2001-2004 by Markanth *
* http://www.firstmud.com/ <markanth@firstmud.com> *
* By using this code you have agreed to follow the term of *
* the 1stMud license in ../doc/1stMud/LICENSE *
***************************************************************************/
#include "merc.h"
#include "recycle.h"
#include "interp.h"
#include "tables.h"
#ifndef IMAGE_URL
#define IMAGE_URL FORMATF("http://www.%s/~%s/images/", HOSTNAME, UNAME)
#endif
#ifndef SOUND_URL
#define SOUND_URL FORMATF("http://www.%s/~%s/msp/", HOSTNAME, UNAME)
#endif
void setup_mxp(Descriptor * d)
{
if (!IsMXP(d))
return;
d_print(d, MXPTAG("!ELEMENT RName FLAG=\"RoomName\""));
d_print(d, MXPTAG("!ELEMENT RDesc FLAG='RoomDesc' OPEN"));
d_print(d, MXPTAG("!ELEMENT RExits FLAG='RoomExit' OPEN"));
d_print(d, MXPTAG("!ELEMENT Ex '<SEND>;'"));
d_print(d, MXPTAG("!ELEMENT Prompt FLAG=\"Prompt\" OPEN"));
d_print(d, MXPTAG("!ELEMENT Hp FLAG=\"Set hp\" OPEN"));
d_print(d, MXPTAG("!ELEMENT MaxHp FLAG=\"Set maxhp\" OPEN"));
d_print(d, MXPTAG("!ELEMENT Mana FLAG=\"Set mana\" OPEN"));
d_print(d, MXPTAG("!ELEMENT MaxMana FLAG=\"Set maxmana\" OPEN"));
d_print(d, MXPTAG("!ELEMENT Move FLAG=\"Set move\" OPEN"));
d_print(d, MXPTAG("!ELEMENT MaxMove FLAG=\"Set maxmove\" OPEN"));
d_print(d,
MXPTAG("!ELEMENT Bid \"<send href='bid '&name;'' "
"hint='Bid for &desc;' prompt>\" ATT='name desc'"));
d_print(d,
MXPTAG("!ELEMENT Help \"<send href='help '&name;'' "
"hint='Help on &desc;'>\" ATT='name desc'"));
d_print(d,
MXPTAG("!ELEMENT List \"<send href='buy '&name;'' "
"hint='Buy &desc;'>\" ATT='name desc'"));
d_print(d,
MXPTAG("!ELEMENT Tell \"<send href='tell '&name;' ' "
"hint='print a message to &name;' prompt>\" ATT='name'"));
d_print(d,
MXPTAG("!ELEMENT Fwho \"<send href='whois '&name;'|"
"buddy '&name;'' "
"hint='Right mouse click to use this object|Whois &desc;|"
"Buddy &desc;'>\" ATT='name desc'"));
d_print(d,
MXPTAG("!ELEMENT Olc \"<send href='commands|show|done' "
"hint='Show commands|Show|Finish editing'>\""));
d_print(d,
MXPTAG("!ELEMENT Pager \"<send href='help|refresh|back|continue' "
"hint='Help|Refresh page|Go back a page|Continue to next page'>\""));
return;
}
void init_mxp(Descriptor * d)
{
d_print(d, MXPTAG("VERSION"));
d_print(d, MXPTAG("SUPPORT"));
}
Do_Fun(do_mxp)
{
if (!ch->desc || IsNPC(ch))
{
chprintln(ch, "No descriptor.");
return;
}
set_on_off(ch, &ch->desc->desc_flags, DESC_MXP,
"Mud eXtension Protocol enabled.",
"Mud eXtension Protocol disabled.");
if (IsSet(ch->desc->desc_flags, DESC_MXP))
{
if ((ch->desc->mxp.mxp_ver * 10) < 4)
init_mxp(ch->desc);
else
setup_mxp(ch->desc);
}
}
void init_color_data(colatt_t * col)
{
int x;
for (x = 0; x < CT_MAX; x++)
getcol(col, x) = CL_NONE;
}
bool convert_color_mxp_tags(Descriptor * d)
{
bool bInTag = false, bInEntity = false;
bool bMXP = IsSet(d->desc_flags, DESC_MXP);
char output[MSL];
register char *result, *ps;
bool success = true;
int written;
colatt_t col;
CharData *ch = CH(d);
char buf[MIL];
memset(output, 0, sizeof(output));
result = output;
init_color_data(&col);
buf[0] = NUL;
for (ps = d->outbuf; *ps != NUL && (int) (ps - d->outbuf) < d->outtop;
ps++)
{
if ((int) (result - output) >= MSL - 32)
{
*result++ = '\0';
written = d_write(d, output, (int) (result - output));
if (!(success = written >= 0))
break;
memset(output, 0, sizeof(output));
result = output;
}
if (*ps == COLORCODE && !VT100_SET(ch, SHOW_CODES))
{
ps++;
if (isdigit(*ps))
{
int slot = *ps - '0';
if (VALID_CL(slot))
{
col[CT_SAVE] = (color_value_t) slot;
}
if (*(ps + 1) == '+' && *(ps + 2))
{
ps += 2;
}
else
continue;
}
if (*ps == '=')
{
ps++;
col[CT_SAVE] = (color_value_t) (col[CT_FORE]);
}
if (IsSet(d->desc_flags, DESC_COLOR))
{
switch (*ps)
{
case '}':
if (!VT100_SET(ch, NO_NEWLINE))
strcpy(buf, NEWLINE);
break;
case '-':
strcpy(buf, "~");
break;
case 'n':
strcpy(buf, mud_info.name);
break;
case 'N':
strcpy(buf, strupper(mud_info.name));
break;
case 't':
case 'T':
if (*(ps + 1) == '+' && *(ps + 2) == '"' && *(ps + 3))
{
char fmt[800];
size_t t = 0;
ps += 3;
do
{
fmt[t++] = *ps++;
}
while (*ps && *ps != '"' && t < sizeof(fmt));
fmt[t] = '\0';
strcpy(buf,
str_time(-1, ch ? GetTzone(ch) : -1, fmt));
}
else
strcpy(buf,
str_time(-1, ch ? GetTzone(ch) : -1,
NULL));
break;
case 'P':
case 'p':
if (!VT100_SET(ch, NO_BEEPS))
strcpy(buf, "\007");
break;
case COLORCODE:
sprintf(buf, "%c", COLORCODE);
break;
case 'X':
init_color_data(&col);
strcpy(buf, CL_DEFAULT);
break;
case 'x':
init_color_data(&col);
if (ch)
strcpy(buf,
make_color(ch,
&ch->pcdata->colors[_DEFAULT]));
else
strcpy(buf, CL_DEFAULT);
break;
default:
set_col_attr(*ps, &col, ch);
strcpy(buf, make_color(ch, &col));
break;
}
add_text(buf, result);
}
}
else if (*ps == CUSTOMSTART)
{
int slot = _NONE;
do
{
ps++;
if (isdigit(*ps))
{
if (slot == _NONE)
slot = 0;
slot = (slot * 10) + (*ps - '0');
}
}
while (*ps && *ps != CUSTOMEND);
if (IsSet(d->desc_flags, DESC_COLOR)
&& !VT100_SET(ch, SHOW_CODES))
{
if (!VALID_COLOR(slot))
{
bug("get_color(): invalid custom color");
strcpy(buf, CL_DEFAULT);
}
else
{
copy_color(col, ch->pcdata->colors[slot]);
strcpy(buf, make_color(ch, &col));
}
add_text(buf, result);
}
}
else if (bInTag)
{
if (*ps == MXP_ENDc)
{
bInTag = false;
if (bMXP)
*result++ = '>';
if (buf[0] != NUL)
add_text(buf, result);
}
else if (bMXP)
*result++ = *ps;
}
else if (bInEntity)
{
if (bMXP)
*result++ = *ps;
if (*ps == ';')
bInEntity = false;
}
else
{
switch (*ps)
{
case MXP_BEGc:
bInTag = true;
if (bMXP)
{
add_text(MXPMODE(1), result);
*result++ = '<';
}
break;
case MXP_ENDc:
bInTag = false;
if (bMXP)
*result++ = '>';
break;
case MXP_ENTc:
bInEntity = true;
if (bMXP)
*result++ = '&';
break;
default:
if (bMXP && !d->pString && d->connected == CON_PLAYING)
{
switch (*ps)
{
case HTML_LTc:
add_text(HTML_LT, result);
break;
case HTML_GTc:
add_text(HTML_GT, result);
break;
case HTML_AMPc:
add_text(HTML_AMP, result);
break;
case HTML_QUOTEc:
add_text(HTML_QUOTE, result);
break;
default:
*result++ = *ps;
break;
}
}
else
*result++ = *ps;
break;
}
}
}
*result = '\0';
written = d_write(d, output, (int) (result - output));
success = (success && (written >= 0));
d->outtop = 0;
return success;
}
// converts '<' into MXP_BEGIN_TAG and '>' into MXP_END_TAG
char *mxp_tagify(const char *mxp_text_with_unencoded_tags)
{
static char result[5][MSL * 2];
static int i;
const char *p;
char *r;
++i;
i %= 5;
r = result[i];
for (p = mxp_text_with_unencoded_tags; !NullStr(p); p++)
{
if (*p == '&')
{
*r++ = MXP_ENTc;
}
else if (*p == '<')
{
*r++ = MXP_BEGc;
}
else if (*p == '>')
{
*r++ = MXP_ENDc;
}
else
{
*r++ = *p;
}
}
*r = '\0';
return result[i];
}
// converts '<' into <, '>' into > and & into &
char *mxp_convert_to_mnemonics(const char *text_with_raw_characters)
{
static char result[5][MSL * 2];
static int i;
const char *p;
char *r;
++i, i %= 5;
r = result[i];
for (p = text_with_raw_characters; !NullStr(p); p++)
{
if (*p == '&')
{
add_text(HTML_AMP, r);
}
else if (*p == '<')
{
add_text(HTML_LT, r);
}
else if (*p == '>')
{
add_text(HTML_GT, r);
}
else
{
*r++ = *p;
}
}
*r = '\0';
return result[i];
}
const char *mxp_create_tag(CharData * ch, const char *tagname,
const char *txt)
{
static int i;
static char result[5][MSL * 2];
const char *p, *t;
char *r;
if (!IsMXP(ch->desc) || NullStr(tagname))
{
return txt;
}
++i, i %= 5;
r = result[i]; // r is a pointer to what will be returned
p = txt; // p is a pointer to the source text
t = NULL; // t is a misc pointer used for various tasks
// copy any leading whitespace from txt into the tag
while (isspace(*p))
{
*r++ = *p++;
}
// if there is no more source text left then we have just formatted
// an empty string or a string of whitespace - regardless return it.
if (*p == '\0')
{
*r = '\0'; // terminate the result first
return result[i];
}
// we now have any leading whitespace outside of where the tag
// starts, now start the tag
if (IsMXP(ch->desc))
{
*r++ = MXP_BEGc;
t = tagname;
while (*t)
{
*r++ = *t++;
}
*r++ = MXP_ENDc;
// r now points at where the non whitespace text will begin
// p points at the first non whitespace, non null character in the input text
// next find the last non whitespace character in the input text
for (t = p; *t; t++)
{
// fast forward to the end of the input text
}
t--; // jump back to the last character in the string
// now backup till we hit the last non whitespace character in the string
while (isspace(*t))
{
t--;
}
// copy from p into r until p is a character past t (the last non whitespace character)
while (p <= t)
{
*r++ = *p++;
}
// put the closing tag on the result
*r++ = MXP_BEGc;
*r++ = '/';
t = tagname;
// close the tag up to the end of the string or first whitespace
while (*t && !isspace(*t))
{
*r++ = *t++;
}
*r++ = MXP_ENDc;
// copy the remaining whitespace from p to r
while (*p)
{
*r++ = *p++;
}
}
// terminate the result
*r = '\0';
// return the result :)
return result[i];
}
const char *mxp_create_tagf(CharData * ch, const char *tagname,
const char *fmt, ...)
{
static int i;
static char result[5][MSL * 2];
char *r;
va_list args;
++i, i %= 5;
r = result[i];
va_start(args, fmt);
vsnprintf(r, sizeof(result[i]), fmt, args);
va_end(args);
if (IsMXP(ch->desc))
{
return mxp_create_tag(ch, tagname, r);
}
return r;
}
FlagTable mxp_support_flags[] = {
{"a", BIT_A, false}
,
{"a.href", BIT_B, false}
,
{"a.xch_cmd", BIT_C, false}
,
{"a.xch_hint", BIT_D, false}
,
{"b", BIT_E, false}
,
{"body", BIT_F, false}
,
{"bold", BIT_G, false}
,
{"br", BIT_H, false}
,
{"c", BIT_I, false}
,
{"c.back", BIT_J, false}
,
{"c.fore", BIT_K, false}
,
{"color", BIT_L, false}
,
{"color.back", BIT_M, false}
,
{"color.fore", BIT_N, false}
,
{"em", BIT_O, false}
,
{"expire", BIT_P, false}
,
{"font", BIT_Q, false}
,
{"font.back", BIT_R, false}
,
{"font.bgcolor", BIT_S, false}
,
{"font.color", BIT_T, false}
,
{"font.fgcolor", BIT_U, false}
,
{"gauge", BIT_V, false}
,
{"h", BIT_W, false}
,
{"head", BIT_X, false}
,
{"high", BIT_Y, false}
,
{"hr", BIT_Z, false}
,
{"html", BIT_a, false}
,
{"i", BIT_b, false}
,
{"image", BIT_c, false}
,
{"image.url", BIT_d, false}
,
{"img", BIT_e, false}
,
{"img.src", BIT_f, false}
,
{"img.xch_mode", BIT_Ax, false}
,
{"italic", BIT_Bx, false}
,
{"li", BIT_Cx, false}
,
{"music", BIT_Dx, false}
,
{"mxp", BIT_Ex, false}
,
{"mxp.off", BIT_Fx, false}
,
{"nobr", BIT_Gx, false}
,
{"ol", BIT_Hx, false}
,
{"option", BIT_Ix, false}
,
{"p", BIT_Jx, false}
,
{"pass", BIT_Kx, false}
,
{"password", BIT_Lx, false}
,
{"pre", BIT_Mx, false}
,
{"relocate", BIT_Nx, false}
,
{"reset", BIT_Ox, false}
,
{"s", BIT_Px, false}
,
{"samp", BIT_Qx, false}
,
{"sbr", BIT_Rx, false}
,
{"send", BIT_Sx, false}
,
{"send.hint", BIT_Tx, false}
,
{"send.href", BIT_Ux, false}
,
{"send.prompt", BIT_Vx, false}
,
{"send.xch_cmd", BIT_Wx, false}
,
{"send.xch_hint", BIT_Xx, false}
,
{"sound", BIT_Yx, false}
,
{"stat", BIT_Zx, false}
,
{NULL, 0, false}
};
FlagTable mxp_support_flags2[] = {
{"strike", BIT_A, false}
,
{"strong", BIT_B, false}
,
{"support", BIT_C, false}
,
{"title", BIT_D, false}
,
{"u", BIT_E, false}
,
{"ul", BIT_F, false}
,
{"underline", BIT_G, false}
,
{"user", BIT_H, false}
,
{"username", BIT_I, false}
,
{"v", BIT_J, false}
,
{"var", BIT_K, false}
,
{"version", BIT_L, false}
,
{"xch_page", BIT_M, false}
,
{"dd", BIT_N, false}
,
{"dest", BIT_O, false}
,
{"dl", BIT_P, false}
,
{"dt", BIT_Q, false}
,
{"frame", BIT_R, false}
,
{"h1", BIT_S, false}
,
{"h2", BIT_T, false}
,
{"h3", BIT_U, false}
,
{"h4", BIT_V, false}
,
{"h5", BIT_W, false}
,
{"h6", BIT_X, false}
,
{"small", BIT_Y, false}
,
{"tt", BIT_Z, false}
,
{"xch_mudtext", BIT_a, false}
,
{"xch_pane", BIT_b, false}
,
{NULL, 0, false}
};
flag_t mxp_lookup(const char *name, FlagTable * flag_table)
{
int flag;
for (flag = 0; flag_table[flag].name != NULL; flag++)
{
if (tolower(name[0]) == tolower(flag_table[flag].name[0])
&& !str_cmp(name, flag_table[flag].name))
return flag_table[flag].bit;
}
return 0;
}
void mxp_support(Descriptor * d, int i, unsigned char *inbuf)
{
unsigned char *buf = &inbuf[i];
const char *supports;
char arg[MIL];
const char *argument;
static char tbuf[MSL];
int n = 10;
flag_t bit;
do
{
n++;
}
while (buf[n] != '>');
buf[n] = NUL;
sprintf(tbuf, "%s", buf + 10);
buf[n] = '>';
n++;
supports = str_dup(tbuf);
for (;;)
{
switch (buf[n])
{
default:
case NUL:
break;
case '\n':
case '\r':
n++;
continue;
break;
}
break;
}
telopt_lskip = n + 9;
if (supports)
{
argument = supports;
tbuf[0] = NUL;
do
{
argument = one_argument(argument, arg);
if (arg[0] != NUL)
{
if ((bit = mxp_lookup(arg + 1, mxp_support_flags)) > 0)
{
SetBit(d->mxp.flags, bit);
}
else if ((bit = mxp_lookup(arg + 1, mxp_support_flags2)) > 0)
{
SetBit(d->mxp.flags2, bit);
}
else
sprintf(tbuf + strlen(tbuf), " %s", arg);
}
}
while (arg[0] != NUL);
free_string(supports);
replace_str(&d->mxp.supports, tbuf);
}
return;
}
void mxp_version(Descriptor * d, int i, unsigned char *inbuf)
{
unsigned char *buf = &inbuf[i];
char cbuf[MIL];
char rbuf[MIL];
char *arg;
int n = 0;
int c = 0;
cbuf[0] = NUL;
rbuf[0] = NUL;
do
{
buf[n] = toupper(buf[n]);
n++;
}
while (buf[n] != '>');
c = n;
buf[c] = NUL;
arg = (char *) &buf[5];
do
{
do
{
arg++;
}
while (*arg != ' ' && *arg != NUL);
if (*arg == NUL)
break;
switch (toupper(*(arg + 1)))
{
default:
break;
case 'C':
sscanf(arg, " CLIENT=%s", cbuf);
break;
case 'M':
sscanf(arg, " MXP=%f", &d->mxp.mxp_ver);
break;
case 'R':
sscanf(arg, " REGISTERED=%s", rbuf);
break;
case 'S':
sscanf(arg, " STYLE=%f", &d->mxp.style_ver);
break;
case 'V':
sscanf(arg, " VERSION=%f", &d->mxp.client_ver);
break;
}
}
while (*arg != NUL);
replace_str(&d->mxp.client, cbuf);
d->mxp.registered = NullStr(rbuf) ? 0 : (toupper(rbuf[0]) == 'Y') ? 2 : 1;
n = c + 1;
buf[c] = '>';
for (;;)
{
switch (buf[n])
{
default:
case NUL:
break;
case '\n':
case '\r':
n++;
continue;
break;
}
break;
}
telopt_lskip = n - 1;
if ((d->mxp.mxp_ver * 10) >= 4)
{
setup_mxp(d);
}
else
RemBit(d->desc_flags, DESC_MXP);
}
void list_mxp_flags(CharData * ch, Descriptor * d)
{
int flag;
char *color;
int max_col, col = 0;
max_col = get_scr_cols(ch) / 13;
for (flag = 0; mxp_support_flags[flag].name != NULL; flag++)
{
if (IsSet(d->mxp.flags, mxp_support_flags[flag].bit))
color = "{G";
else
color = "{r";
chprintf(ch, "|%s%s{x", color,
stringf(ch, 12, Center, NULL, mxp_support_flags[flag].name));
if (++col % max_col == 0)
chprintln(ch, "|");
}
for (flag = 0; mxp_support_flags2[flag].name != NULL; flag++)
{
if (IsSet(d->mxp.flags, mxp_support_flags2[flag].bit))
color = "{G";
else
color = "{r";
chprintf(ch, "|%s%s{x", color,
stringf(ch, 12, Center, NULL,
mxp_support_flags2[flag].name));
if (++col % max_col == 0)
chprintln(ch, "|");
}
if (col % max_col != 0)
chprintln(ch, "|");
}
void mxp_details(CharData * ch, Descriptor * d)
{
if (IsSet(d->desc_flags, DESC_MXP))
{
chprintlnf(ch, "Status: {G%s{x", IsMXP(d) ? "ON" : "OFF");
chprintlnf(ch, "Client: {G%s %1.2f %s{x", d->mxp.client,
d->mxp.client_ver,
d->mxp.registered ==
1 ? "{D[{RUnregistered{D]" : d->mxp.registered ==
2 ? "{D[{GRegistered{D]" : "");
chprintlnf(ch, "MXP Version: {Y%1.2f{x", d->mxp.mxp_ver);
if (d->mxp.style_ver > 0)
chprintlnf(ch, "Style Version: {M%1.2f{x", d->mxp.style_ver);
if (!NullStr(d->mxp.supports))
chprintlnf(ch, "MXP Info: %s", d->mxp.supports);
chprintln(ch, draw_line(ch, NULL, 0));
if (d->mxp.flags || d->mxp.flags2)
list_mxp_flags(ch, d);
chprintln(ch, draw_line(ch, NULL, 0));
}
}
void send_portal(Descriptor * d, const char *format, ...)
{
char out[MSL];
char buf[MSL];
va_list args;
int len;
if (!IsPortal(d) || NullStr(format))
return;
va_start(args, format);
len = vsnprintf(buf, sizeof(buf), format, args);
va_end(args);
sprintf(out, "#K%%%05u%03d%s", d->portal.keycode, len, buf);
d_write(d, out, 0);
}
void portal_sound(CharData * ch, MspData * sound)
{
send_portal(ch->desc, "%s%s", CL_SEND_SOUND, sound->file);
}
void portal_music(CharData * ch, MspData * sound)
{
send_portal(ch->desc, "%s%s~%d", CL_SEND_MUSIC, sound->file, sound->loop);
}
void portal_image(CharData * ch, const char *img)
{
send_portal(ch->desc, "%s%s~%s", CL_SEND_IMAGE, img, img);
}
void portal_map(CharData * ch, RoomIndex * pRoom)
{
int i;
char buf[MSL];
bool found = false;
if (!IsPortal(ch->desc) || !pRoom)
return;
buf[0] = NUL;
for (i = 0; i < MAX_DIR; i++)
{
if (pRoom->exit[i] != NULL)
{
strcat(buf, " ");
strcat(buf, &dir_name[i][0]);
found = true;
}
}
if (found)
send_portal(ch->desc, "%s%s", CL_SEND_ROOMCODE, buf + 1);
}
void portal_chat(CharData * source, CharData * target, const char *command,
const char *channel, const char *text)
{
if (IsPortal(target->desc))
{
send_portal(target->desc, "%s%s~%s~%s~%s: %s", CL_SEND_CHAT, command,
strip_color(channel), Pers(source, target), Pers(source,
target),
strip_color(text));
}
}
bool bust_a_portal(CharData * ch)
{
static char buf[MSL];
char buf2[MSL];
Descriptor *d = ch->desc;
CharData *victim;
if (!IsPortal(d))
return false;
buf[0] = NUL;
strcat(buf, CL_SEND_COMPOSITE);
sprintf(buf2, "%s%ld", CL_SEND_HP, ch->hit);
strcat(buf, buf2);
sprintf(buf2, "~%s%ld", CL_SEND_MAXHP, ch->max_hit);
strcat(buf, buf2);
sprintf(buf2, "~%s%ld", CL_SEND_SP, ch->mana);
strcat(buf, buf2);
sprintf(buf2, "~%s%ld", CL_SEND_MAXSP, ch->max_mana);
strcat(buf, buf2);
sprintf(buf2, "~%s%ld", CL_SEND_GP1, ch->move);
strcat(buf, buf2);
sprintf(buf2, "~%s%ld", CL_SEND_MAXGP1, ch->max_move);
strcat(buf, buf2);
victim = ch->fighting;
if (victim && can_see(ch, victim))
{
int percent;
if (victim->max_hit > 0)
percent = victim->hit * 100 / victim->max_hit;
else
percent = 0;
sprintf(buf2, "~%s%s", CL_SEND_ATTACKER, victim->short_descr);
strcat(buf, buf2);
sprintf(buf2, "~%s%d", CL_SEND_ATTCOND, percent);
strcat(buf, buf2);
}
else
{
sprintf(buf2, "~%s0", CL_SEND_ATTCOND);
strcat(buf, buf2);
}
sprintf(buf2,
"~%s<r[><sNext Level:> %d<sexp><r][><sPurse:> <y%ld> <sgold> <y%ld> <ssilver><r]>",
CL_SEND_GLINE2, (ch->level + 1) * exp_per_level(ch,
ch->
pcdata->points) -
ch->exp, ch->gold, ch->silver);
strcat(buf, buf2);
sprintf(buf2, "~%s<r", CL_SEND_GLINE1);
if (IsSet(ch->comm, COMM_AFK))
{
strcat(buf, "[><yAFK><r]");
}
strcat(buf, ">");
strcat(buf, buf2);
send_portal(d, buf);
return true;
}
Do_Fun(do_portal)
{
if (IsNPC(ch) || !ch->desc)
return;
set_on_off(ch, &ch->desc->desc_flags, DESC_PORTAL,
"You now recieve portal enhancements.",
"You no longer recieve portal enhancements.");
}
void send_imp(Descriptor * d, char *buf)
{
if (d == NULL)
return;
if (!IsFireCl(d))
return;
d_write(d, buf, 0);
}
void imp_sound(CharData * ch, MspData * sound)
{
char buf[MSL];
sprintf(buf, "<AUDIO FILE=%s%s>", sound->url, sound->file);
send_imp(ch->desc, buf);
}
void imp_image(CharData * ch, const char *img)
{
char buf[MSL];
sprintf(buf, "<IMG SRC=%s%s ALT=%s>", IMAGE_URL, img, img);
send_imp(ch->desc, buf);
}
void write_sound(FileData * fp, const char *name, MspData * snd)
{
if (NullStr(name))
f_printf(fp, "'%s' %s V=%d L=%d P=%d C=%d T=%s~ U=%s~ @" LF,
snd->file, write_flags(snd->to), snd->volume, snd->loop,
snd->priority, !snd->restart, flag_string(msp_types,
snd->type),
snd->url);
else if (snd)
f_printf(fp, "%s%s'%s' %s V=%d L=%d P=%d C=%d T=%s~ U=%s~ @" LF, name,
format_tabs(strlen(name)), snd->file, write_flags(snd->to),
snd->volume, snd->loop, snd->priority, !snd->restart,
flag_string(msp_types, snd->type), snd->url);
}
MspData *read_sound(FileData * fp)
{
MspData *sound = new_msp();
char letter;
sound->file = str_dup(read_word(fp));
sound->to = read_flag(fp);
letter = read_letter(fp);
while (letter != '@')
{
read_letter(fp);
switch (letter)
{
case 'V':
sound->volume = read_number(fp);
break;
case 'L':
sound->loop = read_number(fp);
break;
case 'P':
sound->priority = read_number(fp);
break;
case 'C':
{
bool res = read_number(fp);
sound->restart = !res;
}
break;
case 'T':
{
const char *str = read_string(fp);
int val = flag_value(msp_types, str);
free_string(str);
if (val == NO_FLAG)
sound->type = MSP_NONE;
else
sound->type = (msp_t) val;
}
break;
case 'U':
sound->url = read_string(fp);
break;
default:
break;
}
letter = read_letter(fp);
}
return sound;
}
Do_Fun(do_imp)
{
if (IsNPC(ch) || !ch->desc)
return;
set_on_off(ch, &ch->desc->desc_flags, DESC_IMP,
"Interactive Mudding Protocol on.",
"Interactive Mudding Protocol off.");
}
Do_Fun(do_pueblo)
{
if (IsNPC(ch) || !ch->desc)
return;
set_on_off(ch, &ch->desc->desc_flags, DESC_PUEBLO,
"You now recieve pueblo enhancements.",
"You no longer recieve pueblo enhancements.");
}
const char *convert_to_pueblo_tag(CharData * ch, const char *text)
{
if (!ch || !IsMXP(ch->desc))
return text;
return mxp_tagify(text);
}
void send_pueblo(CharData * ch, const char *fmt, ...)
{
char buf[MPL];
va_list args;
if (!ch || (!IsPueblo(ch->desc) && !IsMXP(ch->desc)) || NullStr(fmt))
return;
va_start(args, fmt);
vsnprintf(buf, sizeof(buf), fmt, args);
va_end(args);
d_print(ch->desc, convert_to_pueblo_tag(ch, buf));
}
void image_to_char(CharData * ch, const char *image)
{
if (!ch || !image)
return;
if (IsPueblo(ch->desc))
{
send_pueblo(ch,
"</xch_mudtext><img xch_mode=html>"
"<img src=\"%s%s\"><br><img xch_mode=text>", IMAGE_URL,
image);
}
else if (IsPortal(ch->desc))
{
portal_image(ch, image);
}
else if (IsFireCl(ch->desc))
imp_image(ch, image);
else if (IsMXP(ch->desc))
chprintf(ch, MXPTAG("IMAGE %s %s"), image, IMAGE_URL);
}
Do_Fun(do_msp)
{
if (IsNPC(ch) || !ch->desc)
return;
set_on_off(ch, &ch->desc->desc_flags, DESC_MSP, "Mud Sound Protocol on.",
"Mud Sound Protocol off.");
}
void send_sound(CharData * ch, MspData * snd)
{
if (!ch || !ch->desc || !snd || NullStr(snd->file))
return;
if (IsMXP(ch->desc))
d_printf(ch->desc, MXPTAG("SOUND %s V=%d L=%d P=%d C=%d T=%s U=%s"),
snd->file, snd->volume, snd->loop, snd->priority,
!snd->restart, flag_string(msp_types, snd->type),
GetStr(snd->url, SOUND_URL));
else if (IsMSP(ch->desc))
d_printf(ch->desc, "!!SOUND(%s V=%d L=%d P=%d C=%d T=%s U=%s)",
snd->file, snd->volume, snd->loop, snd->priority,
!snd->restart, flag_string(msp_types, snd->type),
GetStr(snd->url, SOUND_URL));
else if (IsPueblo(ch->desc))
send_pueblo(ch,
"</xch_mudtext><img xch_mode=html>"
"<img xch_sound=play xch_volume=%d src=\"%s%s\">"
"<br><img xch_mode=text>", GetStr(snd->url, SOUND_URL),
snd->file);
else if (IsPortal(ch->desc))
portal_sound(ch, snd);
else if (IsFireCl(ch->desc))
imp_sound(ch, snd);
}
void send_music(CharData * ch, MspData * snd)
{
if (!ch || !ch->desc || !snd || NullStr(snd->file))
return;
if (IsMXP(ch->desc))
d_printf(ch->desc, MXPTAG("MUSIC %s V=%d L=%d P=%d C=%d T=%s U=%s"),
snd->file, snd->volume, snd->loop, snd->priority,
!snd->restart, flag_string(msp_types, snd->type),
GetStr(snd->url, SOUND_URL));
else if (IsMSP(ch->desc))
d_printf(ch->desc, "!!MUSIC(%s V=%d L=%d P=%d C=%d T=%s U=%s)",
snd->file, snd->volume, snd->loop, snd->priority,
!snd->restart, flag_string(msp_types, snd->type),
GetStr(snd->url, SOUND_URL));
else if (IsPueblo(ch->desc))
send_pueblo(ch,
"</xch_mudtext><img xch_mode=html>"
"<img xch_sound=loop xch_volume=%d src=\"%s%s\">"
"<br><img xch_mode=text>", snd->volume, GetStr(snd->url,
SOUND_URL));
else if (IsPortal(ch->desc))
portal_music(ch, snd);
else if (IsFireCl(ch->desc))
imp_sound(ch, snd);
}
void music_off(CharData * ch)
{
if (IsMXP(ch->desc))
chprintf(ch, MXPTAG("MUSIC Off %s"), SOUND_URL);
else if (IsMSP(ch->desc))
chprintf(ch, "!!MUSIC(Off %s)", SOUND_URL);
else if (IsPueblo(ch->desc))
send_pueblo(ch,
"</xch_mudtext><img xch_mode=html><img xch_sound=stop>"
"<br><img xch_mode=text>");
else if (IsPortal(ch->desc))
send_portal(ch->desc, "%s", CL_SEND_MUSIC);
else if (IsFireCl(ch->desc))
send_imp(ch->desc, "<STOPAUDIO>");
}
#define SENDOK(ch, type) ((IsNPC(ch) || ((ch)->desc && (ch->desc->connected == CON_PLAYING))) \
&& (ch)->position >= min_pos)
void act_sound(MspData * sound, CharData * ch, const void *arg1, flag_t type,
position_t min_pos)
{
CharData *to = (CharData *) arg1;
if (!sound)
return;
if (IsSet(type, TO_CHAR))
{
if (ch && SENDOK(ch, type))
send_sound(ch, sound);
}
if (IsSet(type, TO_VICT))
{
if (to && SENDOK(to, type) && to != ch)
send_sound(to, sound);
}
if (IsSet(type, TO_ZONE | TO_ALL))
{
Descriptor *d;
for (d = descriptor_first; d; d = d->next)
{
to = CH(d);
if (to && SENDOK(to, type) && (to != ch)
&&
((IsSet
(type, TO_ALL) || (to->in_room
&& to->in_room->area ==
ch->in_room->area))))
send_sound(to, sound);
}
}
if (IsSet(type, TO_ROOM | TO_NOTVICT))
{
RoomIndex *room;
CharData *vch;
if (ch && ch->in_room != NULL)
room = ch->in_room;
else if (to && to->in_room != NULL)
room = to->in_room;
else
{
bugf("no valid target");
return;
}
for (vch = room->person_first; vch; vch = vch->next_in_room)
{
if (SENDOK(vch, type) && (vch != ch)
&& (IsSet(type, TO_ROOM) || (to != vch)))
send_sound(vch, sound);
}
}
return;
}
int print_stripped_client_code(Descriptor * to, const char *txt, int size)
{
int i, cnt = 0;
int tmp = 0;
char *dest;
alloc_mem(dest, char, size);
for (i = 0; i < size; i++)
{
if (txt[i] == ESCc && sscanf(&txt[i], ESC "[%dz", &tmp) == 1)
{
do
{
i += 2;
do
{
i++;
}
while (isdigit(txt[i]));
i++;
}
while (txt[i] == ESCc && sscanf(&txt[i], ESC "[%dz", &tmp) == 1);
if (txt[i] == '<')
{
do
{
i++;
}
while (txt[i] != '>');
}
}
else if (txt[i] == MXP_BEGc)
{
do
{
i++;
}
while (txt[i] != MXP_ENDc);
}
else if (txt[i] == '!'
&& (!memcmp(&txt[i], "!!SOUND(", 8)
|| !memcmp(&txt[i], "!!MUSIC(", 8)))
{
i += 8;
do
{
i++;
}
while (txt[i] != ')');
}
else if (txt[i] == '<' && !memcmp(&txt[i], "</xch_mudtext>", 14))
{
i += 14;
do
{
i++;
}
while (txt[i] != '<'
|| memcmp(&txt[i], "<img xch_mode=text>", 19));
i += 18;
}
else
dest[cnt++] = txt[i];
}
dest[cnt] = NUL;
d_print(to, dest);
free_mem(dest);
return cnt;
}
Do_Fun(do_client_list)
{
chprintlnf(ch, "Type Command Status");
chprintln(ch, "----------------------");
chprintlnf(ch, "{W%-6s {g%-8s %s{x", "MXP", cmd_name(do_mxp),
OnOff(IsMXP(ch->desc)));
chprintlnf(ch, "{W%-6s {g%-8s %s{x", "MSP", cmd_name(do_msp),
OnOff(IsMSP(ch->desc)));
chprintlnf(ch, "{W%-6s {g%-8s %s{x", "PUEBLO", cmd_name(do_pueblo),
OnOff(IsPueblo(ch->desc)));
chprintlnf(ch, "{W%-6s {g%-8s %s{x", "IMP", cmd_name(do_imp),
OnOff(IsFireCl(ch->desc)));
#ifndef DISABLE_MCCP
chprintlnf(ch, "{W%-6s {g%-8s %s{x", "MCCP", cmd_name(do_compress),
OnOff(IsCompressed(ch->desc)));
#endif
chprintlnf(ch, "{W%-6s {g%-8s %s{x", "PORTAL", cmd_name(do_portal),
OnOff(IsPortal(ch->desc)));
chprintlnf(ch, "{W%-6s {g%-8s %s{x", "COLOR", cmd_name(do_color),
OnOff(IsSet(ch->desc->desc_flags, DESC_COLOR)));
chprintln(ch, "------------------------");
chprintlnf(ch,
"Type '%s mxp|msp|pueblo|imp|portal|mccp|color' to change.",
n_fun);
}
Do_Fun(do_client)
{
vinterpret(ch, n_fun, argument, "mxp", do_mxp, "msp", do_msp, "pueblo",
do_pueblo, "imp", do_imp, "portal", do_portal, "mccp",
do_compress, "color", do_color, NULL, do_client_list);
}