#ifdef REALITY_LVLS
/*
* levels.cpp - Reality levels stuff
*/
#include "copyright.h"
#include "autoconf.h"
#include "config.h"
#include "externs.h"
#include "db.h"
#include "attrs.h"
#include "mudconf.h"
#include "command.h"
#include "powers.h"
#include "alloc.h"
#include "match.h"
#include "levels.h"
#include "stringutil.h"
extern void cf_log_notfound(dbref, char *, const char *, char *);
RLEVEL RxLevel(dbref thing)
{
const char *buff = atr_get_raw(thing, A_RLEVEL);
if ( NULL == buff
|| strlen(buff) != 17)
{
switch(Typeof(thing))
{
case TYPE_ROOM:
return(mudconf.def_room_rx);
case TYPE_PLAYER:
return(mudconf.def_player_rx);
case TYPE_EXIT:
return(mudconf.def_exit_rx);
default:
return(mudconf.def_thing_rx);
}
}
int i;
RLEVEL rx = 0;
for (i = 0; mux_ishex(buff[i]); i++)
{
rx = 16 * rx + mux_hex2dec(buff[i]);
}
return rx;
}
RLEVEL TxLevel(dbref thing)
{
const char *buff = atr_get_raw(thing, A_RLEVEL);
if ( NULL == buff
|| strlen(buff) != 17)
{
switch(Typeof(thing))
{
case TYPE_ROOM:
return(mudconf.def_room_tx);
case TYPE_PLAYER:
return(mudconf.def_player_tx);
case TYPE_EXIT:
return(mudconf.def_exit_tx);
default:
return(mudconf.def_thing_tx);
}
}
// Skip the first field.
//
int i;
for (i = 0; buff[i] && !mux_isspace(buff[i]); i++)
{
; // Nothing.
}
RLEVEL tx = 0;
if (buff[i])
{
// Skip space found above.
//
i++;
// Decode second field.
//
for ( ; mux_ishex(buff[i]); i++)
{
tx = 16 * tx + mux_hex2dec(buff[i]);
}
}
return tx;
}
void notify_except_rlevel
(
dbref loc,
dbref player,
dbref exception,
const char *msg,
int xflags
)
{
if ( loc != exception
&& IsReal(loc, player))
{
notify_check(loc, player, msg,
(MSG_ME_ALL | MSG_F_UP | MSG_S_INSIDE | MSG_NBR_EXITS_A| xflags));
}
dbref first;
DOLIST(first, Contents(loc))
{
if ( first != exception
&& IsReal(first, player))
{
notify_check(first, player, msg,
(MSG_ME | MSG_F_DOWN | MSG_S_OUTSIDE | xflags));
}
}
}
void notify_except2_rlevel
(
dbref loc,
dbref player,
dbref exc1,
dbref exc2,
const char *msg
)
{
if ( loc != exc1
&& loc != exc2
&& IsReal(loc, player))
{
notify_check(loc, player, msg,
(MSG_ME_ALL | MSG_F_UP | MSG_S_INSIDE | MSG_NBR_EXITS_A));
}
dbref first;
DOLIST(first, Contents(loc))
{
if ( first != exc1
&& first != exc2
&& IsReal(first, player))
{
notify_check(first, player, msg,
(MSG_ME | MSG_F_DOWN | MSG_S_OUTSIDE));
}
}
}
void notify_except2_rlevel2
(
dbref loc,
dbref player,
dbref exc1,
dbref exc2,
const char *msg
)
{
if ( loc != exc1
&& loc != exc2
&& IsReal(loc, player))
{
notify_check(loc, player, msg,
(MSG_ME_ALL | MSG_F_UP | MSG_S_INSIDE | MSG_NBR_EXITS_A));
}
dbref first;
DOLIST(first, Contents(loc))
{
if ( first != exc1
&& first != exc2
&& IsReal(first, player)
&& IsReal(first, exc2))
{
notify_check(first, player, msg,
(MSG_ME | MSG_F_DOWN | MSG_S_OUTSIDE));
}
}
}
/*
* ---------------------------------------------------------------------------
* * rxlevel_description: Return an mbuf containing the RxLevels of the thing.
*/
char *rxlevel_description(dbref player, dbref target)
{
// Allocate the return buffer.
//
int otype = Typeof(target);
char *buff = alloc_mbuf("rxlevel_description");
char *bp = buff;
// Store the header strings and object type.
//
safe_mb_str("RxLevel:", buff, &bp);
int i;
RLEVEL rl = RxLevel(target);
for (i = 0; i < mudconf.no_levels; ++i)
{
if ( (rl & mudconf.reality_level[i].value)
== mudconf.reality_level[i].value)
{
safe_mb_chr(' ', buff, &bp);
safe_mb_str(mudconf.reality_level[i].name, buff, &bp);
}
}
// Terminate the string, and return the buffer to the caller.
//
*bp = '\0';
return buff;
}
/*
* ---------------------------------------------------------------------------
* * txlevel_description: Return an mbuf containing the TxLevels of the thing.
*/
char *txlevel_description(dbref player, dbref target)
{
// Allocate the return buffer.
//
int otype = Typeof(target);
char *buff = alloc_mbuf("txlevel_description");
char *bp = buff;
// Store the header strings and object type.
//
safe_mb_str((char *)"TxLevel:", buff, &bp);
int i;
RLEVEL tl = TxLevel(target);
for (i = 0; i < mudconf.no_levels; ++i)
{
if ( (tl & mudconf.reality_level[i].value)
== mudconf.reality_level[i].value)
{
safe_mb_chr(' ', buff, &bp);
safe_mb_str(mudconf.reality_level[i].name, buff, &bp);
}
}
// Terminate the string, and return the buffer to the caller.
//
*bp = '\0';
return buff;
}
RLEVEL find_rlevel(char *name)
{
for (int i = 0; i < mudconf.no_levels; i++)
{
if (mux_stricmp(name, mudconf.reality_level[i].name) == 0)
{
return mudconf.reality_level[i].value;
}
}
return 0;
}
void do_rxlevel
(
dbref player,
dbref cause,
dbref enactor,
int nargs,
int key,
char *object,
char *arg
)
{
if (!arg || !*arg)
{
notify_quiet(player, "I don't know what you want to set!");
return;
}
// Find thing.
//
dbref thing = match_controlled(player, object);
if (NOTHING == thing)
{
return;
}
char lname[9];
RLEVEL ormask = 0;
RLEVEL andmask = ~ormask;
while (*arg)
{
int negate = 0;
while ( *arg != '\0'
&& mux_isspace(*arg))
{
arg++;
}
if (*arg == '!')
{
negate = 1;
++arg;
}
int i;
for (i = 0; *arg && !mux_isspace(*arg); arg++)
{
if (i < 8)
{
lname[i++] = *arg;
}
}
lname[i] = '\0';
if (!lname[0])
{
if (negate)
{
notify(player, "You must specify a reality level to clear.");
}
else
{
notify(player, "You must specify a reality level to set.");
}
return;
}
RLEVEL result = find_rlevel(lname);
if (!result)
{
notify(player, "No such reality level.");
continue;
}
if (negate)
{
andmask &= ~result;
notify(player, "Cleared.");
}
else
{
ormask |= result;
notify(player, "Set.");
}
}
// Set the Rx Level.
//
char *buff = alloc_lbuf("do_rxlevel");
sprintf(buff, "%08X %08X", RxLevel(thing) & andmask | ormask, TxLevel(thing));
atr_add_raw(thing, A_RLEVEL, buff);
free_lbuf(buff);
}
void do_txlevel
(
dbref player,
dbref cause,
dbref enactor,
int nargs,
int key,
char *object,
char *arg
)
{
if (!arg || !*arg)
{
notify_quiet(player, "I don't know what you want to set!");
return;
}
// Find thing.
//
dbref thing = match_controlled(player, object);
if (NOTHING == thing)
{
return;
}
char lname[9];
RLEVEL ormask = 0;
RLEVEL andmask = ~ormask;
while (*arg)
{
int negate = 0;
while ( *arg
&& mux_isspace(*arg))
{
arg++;
}
if (*arg == '!')
{
negate = 1;
++arg;
}
int i;
for (i = 0; *arg && !mux_isspace(*arg); arg++)
{
if (i < 8)
{
lname[i++] = *arg;
}
}
lname[i] = '\0';
if (!lname[0])
{
if (negate)
{
notify(player, "You must specify a reality level to clear.");
}
else
{
notify(player, "You must specify a reality level to set.");
}
return;
}
RLEVEL result = find_rlevel(lname);
if (!result)
{
notify(player, "No such reality level.");
continue;
}
if (negate)
{
andmask &= ~result;
notify(player, "Cleared.");
}
else
{
ormask |= result;
notify(player, "Set.");
}
}
// Set the Tx Level.
//
char *buff = alloc_lbuf("do_rxlevel");
sprintf(buff, "%08X %08X", RxLevel(thing), TxLevel(thing) & andmask | ormask);
atr_add_raw(thing, A_RLEVEL, buff);
free_lbuf(buff);
}
/*
* ---------------------------------------------------------------------------
* * decompile_rlevels: Produce commands to set reality levels on target.
*/
void decompile_rlevels(dbref player,dbref thing,char *thingname)
{
char *buf = rxlevel_description(player, thing);
notify(player, tprintf("@rxlevel %s=%s", strip_ansi(thingname), buf));
free_mbuf(buf);
buf = txlevel_description(player, thing);
notify(player, tprintf("@txlevel %s=%s", strip_ansi(thingname), buf));
free_mbuf(buf);
}
int *desclist_match(dbref player, dbref thing)
{
static int descbuffer[33];
descbuffer[0] = 1;
RLEVEL match = RxLevel(player) & TxLevel(thing);
for (int i = 0; i < mudconf.no_levels; i++)
{
if ( (match & mudconf.reality_level[i].value)
== mudconf.reality_level[i].value)
{
ATTR *at = atr_str(mudconf.reality_level[i].attr);
if (at)
{
int j;
for (j = 1; j < descbuffer[0]; j++)
{
if (at->number == descbuffer[j])
{
break;
}
}
if (j == descbuffer[0])
{
descbuffer[descbuffer[0]++] = at->number;
}
}
}
}
return descbuffer;
}
/* ---------------------------------------------------------------------------
* did_it_rlevel: Have player do something to/with thing, watching the
* attributes. 'what' is actually ignored, the desclist match being used
* instead.
*/
void did_it_rlevel
(
dbref player,
dbref thing,
int what,
const char *def,
int owhat,
const char *odef,
int awhat,
char *args[],
int nargs
)
{
char *d, *buff, *act, *charges, *bp, *str;
dbref loc, aowner;
int num, aflags;
int i, *desclist, found_a_desc;
char *preserve[MAX_GLOBAL_REGS];
int preserve_len[MAX_GLOBAL_REGS];
bool need_pres = false;
// Message to player.
//
if (what > 0)
{
// Get description list.
//
desclist = desclist_match(player, thing);
found_a_desc = 0;
for (i = 1; i < desclist[0]; i++)
{
// Ok, if it's A_DESC, we need to check against A_IDESC.
//
if ( A_IDESC == what
&& desclist[i] == A_DESC)
{
d = atr_pget(thing, A_IDESC, &aowner, &aflags);
}
else
{
d = atr_pget(thing, desclist[i], &aowner, &aflags);
}
if (*d)
{
// No need for the 'def' message.
//
found_a_desc = 1;
if (!need_pres)
{
need_pres = true;
save_global_regs("did_it_save", preserve, preserve_len);
}
buff = bp = alloc_lbuf("did_it.1");
str = d;
mux_exec(buff, &bp, 0, thing, player,
EV_EVAL | EV_FIGNORE | EV_TOP, &str, args, nargs);
*bp = '\0';
if ( A_HTDESC == desclist[i]
&& Html(player))
{
safe_str("\r\n", buff, &bp);
*bp = '\0';
notify_html(player, buff);
}
else
{
notify(player, buff);
}
free_lbuf(buff);
}
free_lbuf(d);
}
if (!found_a_desc)
{
// No desc found... try the default desc (again).
// A_DESC or A_HTDESC... the worst case we look for it twice.
//
d = atr_pget(thing, what, &aowner, &aflags);
if (*d)
{
// No need for the 'def' message
//
found_a_desc = 1;
if (!need_pres)
{
need_pres = true;
save_global_regs("did_it_save", preserve, preserve_len);
}
buff = bp = alloc_lbuf("did_it.1");
str = d;
mux_exec(buff, &bp, 0, thing, player,
EV_EVAL | EV_FIGNORE | EV_TOP, &str, args, nargs);
*bp = '\0';
if ( A_HTDESC == what
&& Html(player))
{
safe_str("\r\n", buff, &bp);
*bp = '\0';
notify_html(player, buff);
}
else
{
notify(player, buff);
}
free_lbuf(buff);
}
else if (def)
{
notify(player, def);
}
free_lbuf(d);
}
}
else if ( what < 0
&& def)
{
notify(player, def);
}
if (isPlayer(thing))
{
d = atr_pget(mudconf.master_room, get_atr("ASSET_DESC"), &aowner, &aflags);
if (*d)
{
if (!need_pres)
{
need_pres = true;
save_global_regs("did_it_save", preserve, preserve_len);
}
buff = bp = alloc_lbuf("did_it.1");
str = d;
mux_exec(buff, &bp, 0, thing, player, EV_EVAL | EV_FIGNORE |EV_TOP, &str, args, nargs);
*bp = '\0';
notify(player, buff);
free_lbuf(buff);
}
free_lbuf(d);
}
// Message to neighbors.
//
if ( owhat > 0
&& Has_location(player)
&& Good_obj(loc = Location(player)))
{
d = atr_pget(thing, owhat, &aowner, &aflags);
if (*d)
{
if (!need_pres)
{
need_pres = true;
save_global_regs("did_it_save", preserve, preserve_len);
}
buff = bp = alloc_lbuf("did_it.2");
str = d;
mux_exec(buff, &bp, 0, thing, player, EV_EVAL | EV_FIGNORE | EV_TOP, &str, args, nargs);
*bp = '\0';
if (*buff)
{
notify_except2_rlevel2(loc, player, player, thing,
tprintf("%s %s", Name(player), buff));
}
free_lbuf(buff);
}
else if (odef)
{
notify_except2_rlevel2(loc, player, player, thing,
tprintf("%s %s", Name(player), odef));
}
free_lbuf(d);
}
else if ( owhat < 0
&& odef
&& Has_location(player)
&& Good_obj(loc = Location(player)))
{
notify_except2_rlevel2(loc, player, player, thing,
tprintf("%s %s", Name(player), odef));
}
// If we preserved the state of the global registers, restore them.
//
if (need_pres)
{
restore_global_regs("did_it_restore", preserve, preserve_len);
}
// Do the action attribute.
//
if ( awhat > 0
&& IsReal(thing, player))
{
act = atr_pget(thing, awhat, &aowner, &aflags);
if (*act != '\0')
{
charges = atr_pget(thing, A_CHARGES, &aowner, &aflags);
if (*charges)
{
num = mux_atol(charges);
if (num > 0)
{
buff = alloc_sbuf("did_it.charges");
mux_ltoa(num-1, buff);
atr_add_raw(thing, A_CHARGES, buff);
free_sbuf(buff);
}
else
{
buff = atr_pget(thing, A_RUNOUT, &aowner, &aflags);
if (*buff != '\0')
{
free_lbuf(act);
act = buff;
}
else
{
free_lbuf(act);
free_lbuf(buff);
free_lbuf(charges);
return;
}
}
}
free_lbuf(charges);
CLinearTimeAbsolute lta;
wait_que(thing, player, player, 0, lta, NOTHING, 0, act, args,
nargs, mudstate.global_regs);
}
free_lbuf(act);
}
}
#endif /* REALITY_LVLS */