/****************************************************************************
* [S]imulated [M]edieval [A]dventure multi[U]ser [G]ame | \\._.// *
* -----------------------------------------------------------| (0...0) *
* SMAUG 1.0 (C) 1994, 1995, 1996 by Derek Snider | ).:.( *
* -----------------------------------------------------------| {o o} *
* SMAUG code team: Thoric, Altrag, Blodkai, Narn, Haus, | / ' ' \ *
* Scryn, Rennard, Swordbearer, Gorog, Grishnakh and Tricops |~'~.VxvxV.~'~*
* ------------------------------------------------------------------------ *
* Merc 2.1 Diku Mud improvments copyright (C) 1992, 1993 by Michael *
* Chastain, Michael Quan, and Mitchell Tse. *
* Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, *
* Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe. *
* ------------------------------------------------------------------------ *
* Online Reset Editing Module *
****************************************************************************/
/*
* This file relies heavily on the fact that your linked lists are correct,
* and that pArea->reset_first is the first reset in pArea. Likewise,
* pArea->reset_last *MUST* be the last reset in pArea. Weird and
* wonderful things will happen if any of your lists are messed up, none
* of them good. The most important are your pRoom->contents,
* pRoom->people, rch->carrying, obj->contains, and pArea->reset_first ..
* pArea->reset_last. -- Altrag
*/
#if defined(macintosh)
#include <types.h>
#else
#include <sys/types.h>
#endif
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include "mud.h"
/* Externals */
extern int top_reset;
char * sprint_reset args( ( CHAR_DATA *ch, RESET_DATA *pReset,
sh_int num, bool rlist ) );
RESET_DATA * parse_reset args( ( AREA_DATA *tarea, char *argument,
CHAR_DATA *ch ) );
int get_wearloc args( ( char *type ) );
int get_trapflag args( ( char *flag ) );
int get_exflag args( ( char *flag ) );
int get_rflag args( ( char *flag ) );
extern char * const wear_locs[];
extern char * const ex_flags[];
bool is_room_reset args( ( RESET_DATA *pReset, ROOM_INDEX_DATA *aRoom,
AREA_DATA *pArea ) );
void add_obj_reset args( ( AREA_DATA *pArea, char cm, OBJ_DATA *obj,
int v2, int v3 ) );
void delete_reset args( ( AREA_DATA *pArea, RESET_DATA *pReset ) );
void instaroom args( ( AREA_DATA *pArea, ROOM_INDEX_DATA *pRoom,
bool dodoors ) );
#define RID ROOM_INDEX_DATA
RID *find_room args( ( CHAR_DATA *ch, char *argument,
ROOM_INDEX_DATA *pRoom ) );
#undef RID
void edit_reset args( ( CHAR_DATA *ch, char *argument, AREA_DATA *pArea,
ROOM_INDEX_DATA *aRoom ) );
#define RD RESET_DATA
RD *find_reset args( ( AREA_DATA *pArea, ROOM_INDEX_DATA *pRoom,
int num ) );
#undef RD
void list_resets args( ( CHAR_DATA *ch, AREA_DATA *pArea,
ROOM_INDEX_DATA *pRoom, int start, int end ) );
RESET_DATA *find_reset(AREA_DATA *pArea, ROOM_INDEX_DATA *pRoom, int numb)
{
RESET_DATA *pReset;
int num = 0;
for ( pReset = pArea->first_reset; pReset; pReset = pReset->next )
if ( is_room_reset(pReset, pRoom, pArea) && ++num >= numb )
return pReset;
return NULL;
}
/* This is one loopy function. Ugh. -- Altrag */
bool is_room_reset( RESET_DATA *pReset, ROOM_INDEX_DATA *aRoom,
AREA_DATA *pArea )
{
ROOM_INDEX_DATA *pRoom;
RESET_DATA *reset;
int pr;
if ( !aRoom )
return TRUE;
switch( pReset->command )
{
case 'M':
case 'O':
pRoom = get_room_index( pReset->arg3 );
if ( !pRoom || pRoom != aRoom )
return FALSE;
return TRUE;
case 'P':
case 'T':
case 'H':
if ( pReset->command == 'H' )
pr = pReset->arg1;
else
pr = pReset->arg3;
for ( reset = pReset->prev; reset; reset = reset->prev )
if ( (reset->command == 'O' || reset->command == 'P' ||
reset->command == 'G' || reset->command == 'E') &&
(!pr || pr == reset->arg1) && get_obj_index(reset->arg1) )
break;
if ( reset && is_room_reset(reset, aRoom, pArea) )
return TRUE;
return FALSE;
case 'B':
switch(pReset->arg2 & BIT_RESET_TYPE_MASK)
{
case BIT_RESET_DOOR:
case BIT_RESET_ROOM:
return (aRoom->vnum == pReset->arg1);
case BIT_RESET_MOBILE:
for ( reset = pReset->prev; reset; reset = reset->prev )
if ( reset->command == 'M' && get_mob_index(reset->arg1) )
break;
if ( reset && is_room_reset(reset, aRoom, pArea) )
return TRUE;
return FALSE;
case BIT_RESET_OBJECT:
for ( reset = pReset->prev; reset; reset = reset->prev )
if ( (reset->command == 'O' || reset->command == 'P' ||
reset->command == 'G' || reset->command == 'E') &&
(!pReset->arg1 || pReset->arg1 == reset->arg1) &&
get_obj_index(reset->arg1) )
break;
if ( reset && is_room_reset(reset, aRoom, pArea) )
return TRUE;
return FALSE;
}
return FALSE;
case 'G':
case 'E':
for ( reset = pReset->prev; reset; reset = reset->prev )
if ( reset->command == 'M' && get_mob_index(reset->arg1) )
break;
if ( reset && is_room_reset(reset, aRoom, pArea) )
return TRUE;
return FALSE;
case 'D':
case 'R':
pRoom = get_room_index( pReset->arg1 );
if ( !pRoom || pRoom->area != pArea || (aRoom && pRoom != aRoom) )
return FALSE;
return TRUE;
default:
return FALSE;
}
return FALSE;
}
ROOM_INDEX_DATA *find_room( CHAR_DATA *ch, char *argument,
ROOM_INDEX_DATA *pRoom )
{
char arg[MAX_INPUT_LENGTH];
if ( pRoom )
return pRoom;
one_argument(argument, arg);
if ( !is_number(arg) && arg[0] != '\0' )
{
send_to_char( "Reset to which room?\n\r", ch );
return NULL;
}
if ( arg[0] == '\0' )
pRoom = ch->in_room;
else
pRoom = get_room_index(atoi(arg));
if ( !pRoom )
{
send_to_char( "Room does not exist.\n\r", ch );
return NULL;
}
return pRoom;
}
/* Separate function for recursive purposes */
#define DEL_RESET(area, reset, rprev) \
do { \
rprev = reset->prev; \
delete_reset(area, reset); \
reset = rprev; \
continue; \
} while(0)
void delete_reset( AREA_DATA *pArea, RESET_DATA *pReset )
{
RESET_DATA *reset;
RESET_DATA *reset_prev;
if ( pReset->command == 'M' )
{
for ( reset = pReset->next; reset; reset = reset->next )
{
/* Break when a new mob found */
if ( reset->command == 'M' )
break;
/* Delete anything mob is holding */
if ( reset->command == 'G' || reset->command == 'E' )
DEL_RESET(pArea, reset, reset_prev);
if ( reset->command == 'B' &&
(reset->arg2 & BIT_RESET_TYPE_MASK) == BIT_RESET_MOBILE &&
(!reset->arg1 || reset->arg1 == pReset->arg1) )
DEL_RESET(pArea, reset, reset_prev);
}
}
else if ( pReset->command == 'O' || pReset->command == 'P' ||
pReset->command == 'G' || pReset->command == 'E' )
{
for ( reset = pReset->next; reset; reset = reset->next )
{
if ( reset->command == 'T' &&
(!reset->arg3 || reset->arg3 == pReset->arg1) )
DEL_RESET(pArea, reset, reset_prev);
if ( reset->command == 'H' &&
(!reset->arg1 || reset->arg1 == pReset->arg1) )
DEL_RESET(pArea, reset, reset_prev);
/* Delete nested objects, even if they are the same object. */
if ( reset->command == 'P' && (reset->arg3 > 0 ||
pReset->command != 'P' || reset->extra-1 == pReset->extra) &&
(!reset->arg3 || reset->arg3 == pReset->arg1) )
DEL_RESET(pArea, reset, reset_prev);
if ( reset->command == 'B' &&
(reset->arg2 & BIT_RESET_TYPE_MASK) == BIT_RESET_OBJECT &&
(!reset->arg1 || reset->arg1 == pReset->arg1) )
DEL_RESET(pArea, reset, reset_prev);
/* Break when a new object of same type is found */
if ( (reset->command == 'O' || reset->command == 'P' ||
reset->command == 'G' || reset->command == 'E') &&
reset->arg1 == pReset->arg1 )
break;
}
}
if ( pReset == pArea->last_mob_reset )
pArea->last_mob_reset = NULL;
if ( pReset == pArea->last_obj_reset )
pArea->last_obj_reset = NULL;
UNLINK(pReset, pArea->first_reset, pArea->last_reset, next, prev);
DISPOSE(pReset);
return;
}
#undef DEL_RESET
RESET_DATA *find_oreset(CHAR_DATA *ch, AREA_DATA *pArea,
ROOM_INDEX_DATA *pRoom, char *name)
{
RESET_DATA *reset;
if ( !*name )
{
for ( reset = pArea->last_reset; reset; reset = reset->prev )
{
if ( !is_room_reset(reset, pRoom, pArea) )
continue;
switch(reset->command)
{
default:
continue;
case 'O': case 'E': case 'G': case 'P':
break;
}
break;
}
if ( !reset )
send_to_char( "No object resets in list.\n\r", ch );
return reset;
}
else
{
char arg[MAX_INPUT_LENGTH];
int cnt = 0, num = number_argument(name, arg);
OBJ_INDEX_DATA *pObjTo = NULL;
for ( reset = pArea->first_reset; reset; reset = reset->next )
{
if ( !is_room_reset(reset, pRoom, pArea) )
continue;
switch(reset->command)
{
default:
continue;
case 'O': case 'E': case 'G': case 'P':
break;
}
if ( (pObjTo = get_obj_index(reset->arg1)) &&
is_name(arg, pObjTo->name) && ++cnt == num )
break;
}
if ( !pObjTo || !reset )
{
send_to_char( "To object not in reset list.\n\r", ch );
return NULL;
}
}
return reset;
}
RESET_DATA *find_mreset(CHAR_DATA *ch, AREA_DATA *pArea,
ROOM_INDEX_DATA *pRoom, char *name)
{
RESET_DATA *reset;
if ( !*name )
{
for ( reset = pArea->last_reset; reset; reset = reset->prev )
{
if ( !is_room_reset(reset, pRoom, pArea) )
continue;
switch(reset->command)
{
default:
continue;
case 'M':
break;
}
break;
}
if ( !reset )
send_to_char( "No mobile resets in list.\n\r", ch );
return reset;
}
else
{
char arg[MAX_INPUT_LENGTH];
int cnt = 0, num = number_argument(name, arg);
MOB_INDEX_DATA *pMob = NULL;
for ( reset = pArea->first_reset; reset; reset = reset->next )
{
if ( !is_room_reset(reset, pRoom, pArea) )
continue;
switch(reset->command)
{
default:
continue;
case 'M':
break;
}
if ( (pMob = get_mob_index(reset->arg1)) &&
is_name(arg, pMob->player_name) && ++cnt == num )
break;
}
if ( !pMob || !reset )
{
send_to_char( "Mobile not in reset list.\n\r", ch );
return NULL;
}
}
return reset;
}
void edit_reset( CHAR_DATA *ch, char *argument, AREA_DATA *pArea,
ROOM_INDEX_DATA *aRoom )
{
char arg[MAX_INPUT_LENGTH];
RESET_DATA *pReset = NULL;
RESET_DATA *reset;
MOB_INDEX_DATA *pMob = NULL;
ROOM_INDEX_DATA *pRoom;
OBJ_INDEX_DATA *pObj;
int num = 0;
int vnum;
char *origarg = argument;
argument = one_argument(argument, arg);
if ( !*arg || !str_cmp(arg, "?") )
{
char *nm = (ch->substate == SUB_REPEATCMD ? "" : (aRoom ? "rreset "
: "reset "));
char *rn = (aRoom ? "" : " [room#]");
ch_printf(ch, "Syntax: %s<list|edit|delete|add|insert|place%s>\n\r",
nm, (aRoom ? "" : "|area"));
ch_printf( ch, "Syntax: %sremove <#>\n\r", nm );
ch_printf( ch, "Syntax: %smobile <mob#> [limit]%s\n\r", nm, rn );
ch_printf( ch, "Syntax: %sobject <obj#> [limit [room%s]]\n\r", nm, rn );
ch_printf( ch, "Syntax: %sobject <obj#> give <mob name> [limit]\n\r", nm );
ch_printf( ch, "Syntax: %sobject <obj#> equip <mob name> <location> "
"[limit]\n\r", nm );
ch_printf( ch, "Syntax: %sobject <obj#> put <to_obj name> [limit]\n\r",
nm );
ch_printf( ch, "Syntax: %shide <obj name>\n\r", nm );
ch_printf( ch, "Syntax: %strap <obj name> <type> <charges> <flags>\n\r",
nm );
ch_printf( ch, "Syntax: %strap room <type> <charges> <flags>\n\r", nm );
ch_printf( ch, "Syntax: %sbit <set|toggle|remove> door%s <dir> "
"<exit flags>\n\r", nm, rn );
ch_printf( ch, "Syntax: %sbit <set|toggle|remove> object <obj name> "
"<extra flags>\n\r", nm );
ch_printf( ch, "Syntax: %sbit <set|toggle|remove> mobile <mob name> "
"<affect flags>\n\r", nm );
ch_printf( ch, "Syntax: %sbit <set|toggle|remove> room%s <room flags>"
"\n\r", nm, rn );
ch_printf( ch, "Syntax: %srandom <last dir>%s\n\r", nm, rn );
if ( !aRoom )
{
send_to_char( "\n\r[room#] will default to the room you are in, "
"if unspecified.\n\r", ch );
}
return;
}
if ( !str_cmp(arg, "on") )
{
ch->substate = SUB_REPEATCMD;
ch->dest_buf = (aRoom ? (void *)aRoom : (void *)pArea);
send_to_char( "Reset mode on.\n\r", ch );
return;
}
if ( !aRoom && !str_cmp(arg, "area") )
{
if ( !pArea->first_reset )
{
send_to_char( "You don't have any resets defined.\n\r", ch );
return;
}
num = pArea->nplayer;
pArea->nplayer = 0;
reset_area(pArea);
pArea->nplayer = num;
send_to_char( "Done.\n\r", ch );
return;
}
if ( !str_cmp(arg, "list") )
{
int start, end;
argument = one_argument(argument, arg);
start = is_number(arg) ? atoi(arg) : -1;
argument = one_argument(argument, arg);
end = is_number(arg) ? atoi(arg) : -1;
list_resets(ch, pArea, aRoom, start, end);
return;
}
if ( !str_cmp(arg, "edit") )
{
argument = one_argument(argument, arg);
if ( !*arg || !is_number(arg) )
{
send_to_char( "Usage: reset edit <number> <command>\n\r", ch );
return;
}
if ( !(pReset = find_reset(pArea, aRoom, num)) )
{
send_to_char( "Reset not found.\n\r", ch );
return;
}
if ( !(reset = parse_reset(pArea, argument, ch)) )
{
send_to_char( "Error in reset. Reset not changed.\n\r", ch );
return;
}
reset->prev = pReset->prev;
reset->next = pReset->next;
if ( !pReset->prev )
pArea->first_reset = reset;
else
pReset->prev->next = reset;
if ( !pReset->next )
pArea->last_reset = reset;
else
pReset->next->prev = reset;
DISPOSE(pReset);
send_to_char( "Done.\n\r", ch );
return;
}
if ( !str_cmp(arg, "add") )
{
if ( (pReset = parse_reset(pArea, argument, ch)) == NULL )
{
send_to_char( "Error in reset. Reset not added.\n\r", ch );
return;
}
add_reset(pArea, pReset->command, pReset->extra, pReset->arg1,
pReset->arg2, pReset->arg3);
DISPOSE(pReset);
send_to_char( "Done.\n\r", ch );
return;
}
if ( !str_cmp(arg, "place") )
{
if ( (pReset = parse_reset(pArea, argument, ch)) == NULL )
{
send_to_char( "Error in reset. Reset not added.\n\r", ch );
return;
}
place_reset(pArea, pReset->command, pReset->extra, pReset->arg1,
pReset->arg2, pReset->arg3);
DISPOSE(pReset);
send_to_char( "Done.\n\r", ch );
return;
}
if ( !str_cmp(arg, "insert") )
{
argument = one_argument(argument, arg);
if ( !*arg || !is_number(arg) )
{
send_to_char( "Usage: reset insert <number> <command>\n\r", ch );
return;
}
num = atoi(arg);
if ( (reset = find_reset(pArea, aRoom, num)) == NULL )
{
send_to_char( "Reset not found.\n\r", ch );
return;
}
if ( (pReset = parse_reset(pArea, argument, ch)) == NULL )
{
send_to_char( "Error in reset. Reset not inserted.\n\r", ch );
return;
}
INSERT(pReset, reset, pArea->first_reset, next, prev);
send_to_char( "Done.\n\r", ch );
return;
}
if ( !str_cmp(arg, "delete") )
{
int start, end;
bool found;
if ( !*argument )
{
send_to_char( "Usage: reset delete <start> [end]\n\r", ch );
return;
}
argument = one_argument(argument, arg);
start = is_number(arg) ? atoi(arg) : -1;
end = is_number(arg) ? atoi(arg) : -1;
num = 0; found = FALSE;
for ( pReset = pArea->first_reset; pReset; pReset = reset )
{
reset = pReset->next;
if ( !is_room_reset(pReset, aRoom, pArea) )
continue;
if ( start > ++num )
continue;
if ( (end != -1 && num > end) || (end == -1 && found) )
return;
UNLINK(pReset, pArea->first_reset, pArea->last_reset, next, prev);
if ( pReset == pArea->last_mob_reset )
pArea->last_mob_reset = NULL;
DISPOSE(pReset);
top_reset--;
found = TRUE;
}
if ( !found )
send_to_char( "Reset not found.\n\r", ch );
else
send_to_char( "Done.\n\r", ch );
return;
}
if ( !str_cmp(arg, "remove") )
{
int iarg;
argument = one_argument(argument, arg);
if ( arg[0] == '\0' || !is_number(arg) )
{
send_to_char( "Delete which reset?\n\r", ch );
return;
}
iarg = atoi(arg);
for ( pReset = pArea->first_reset; pReset; pReset = pReset->next )
{
if ( is_room_reset( pReset, aRoom, pArea ) && ++num == iarg )
break;
}
if ( !pReset )
{
send_to_char( "Reset does not exist.\n\r", ch );
return;
}
delete_reset( pArea, pReset );
send_to_char( "Reset deleted.\n\r", ch );
return;
}
if ( !str_prefix( arg, "mobile" ) )
{
argument = one_argument(argument, arg);
if ( arg[0] == '\0' || !is_number(arg) )
{
send_to_char( "Reset which mobile vnum?\n\r", ch );
return;
}
if ( !(pMob = get_mob_index(atoi(arg))) )
{
send_to_char( "Mobile does not exist.\n\r", ch );
return;
}
argument = one_argument(argument, arg);
if ( arg[0] == '\0' )
num = 1;
else if ( !is_number(arg) )
{
send_to_char( "Reset how many mobiles?\n\r", ch );
return;
}
else
num = atoi(arg);
if ( !(pRoom = find_room(ch, argument, aRoom)) )
return;
pReset = make_reset('M', 0, pMob->vnum, num, pRoom->vnum);
LINK(pReset, pArea->first_reset, pArea->last_reset, next, prev);
send_to_char( "Mobile reset added.\n\r", ch );
return;
}
if ( !str_prefix(arg, "object") )
{
argument = one_argument(argument, arg);
if ( arg[0] == '\0' || !is_number(arg) )
{
send_to_char( "Reset which object vnum?\n\r", ch );
return;
}
if ( !(pObj = get_obj_index(atoi(arg))) )
{
send_to_char( "Object does not exist.\n\r", ch );
return;
}
argument = one_argument(argument, arg);
if ( arg[0] == '\0' )
strcpy(arg, "room");
if ( !str_prefix( arg, "put" ) )
{
argument = one_argument(argument, arg);
if ( !(reset = find_oreset(ch, pArea, aRoom, arg)) )
return;
/* Put in_objects after hide and trap resets */
while ( reset->next && (reset->next->command == 'H' ||
reset->next->command == 'T' || reset->next->command == 'B') )
reset = reset->next;
/* pReset = make_reset('P', 1, pObj->vnum, num, reset->arg1);*/
argument = one_argument(argument, arg);
if ( (vnum = atoi(arg)) < 1 )
vnum = 1;
pReset = make_reset('P', reset->extra+1, pObj->vnum, vnum, 0);
/* Grumble.. insert puts pReset before reset, and we need it after,
so we make a hackup and reverse all the list params.. :P.. */
INSERT(pReset, reset, pArea->last_reset, prev, next);
send_to_char( "Object reset in object created.\n\r", ch );
return;
}
if ( !str_prefix( arg, "give" ) )
{
argument = one_argument(argument, arg);
if ( !(reset = find_mreset(ch, pArea, aRoom, arg)) )
return;
while ( reset->next && reset->next->command == 'B' )
reset = reset->next;
argument = one_argument(argument, arg);
if ( (vnum = atoi(arg)) < 1 )
vnum = 1;
pReset = make_reset('G', 1, pObj->vnum, vnum, 0);
INSERT(pReset, reset, pArea->last_reset, prev, next);
send_to_char( "Object reset to mobile created.\n\r", ch );
return;
}
if ( !str_prefix( arg, "equip" ) )
{
argument = one_argument(argument, arg);
if ( !(reset = find_mreset(ch, pArea, aRoom, arg)) )
return;
while ( reset->next && reset->next->command == 'B' )
reset = reset->next;
num = get_wearloc(argument);
if ( num < 0 )
{
send_to_char( "Reset object to which location?\n\r", ch );
return;
}
for ( pReset = reset->next; pReset; pReset = pReset->next )
{
if ( pReset->command == 'M' )
break;
if ( pReset->command == 'E' && pReset->arg3 == num )
{
send_to_char( "Mobile already has an item equipped there.\n\r", ch);
return;
}
}
argument = one_argument(argument, arg);
if ( (vnum = atoi(arg)) < 1 )
vnum = 1;
pReset = make_reset('E', 1, pObj->vnum, vnum, num);
INSERT(pReset, reset, pArea->last_reset, prev, next);
send_to_char( "Object reset equipped by mobile created.\n\r", ch );
return;
}
if ( arg[0] == '\0' || !(num = (int)str_cmp(arg, "room")) ||
is_number(arg) )
{
if ( !(bool)num )
argument = one_argument(argument, arg);
if ( !(pRoom = find_room(ch, argument, aRoom)) )
return;
if ( pRoom->area != pArea )
{
send_to_char( "Cannot reset objects to other areas.\n\r", ch );
return;
}
if ( (vnum = atoi(arg)) < 1 )
vnum = 1;
pReset = make_reset('O', 0, pObj->vnum, vnum, pRoom->vnum);
LINK(pReset, pArea->first_reset, pArea->last_reset, next, prev);
send_to_char( "Object reset added.\n\r", ch );
return;
}
send_to_char( "Reset object to where?\n\r", ch );
return;
}
if ( !str_cmp(arg, "random") )
{
argument = one_argument(argument, arg);
vnum = get_dir( arg );
if ( vnum < 0 || vnum > 9 )
{
send_to_char( "Reset which random doors?\n\r", ch );
return;
}
if ( vnum == 0 )
{
send_to_char( "There is no point in randomizing one door.\n\r", ch );
return;
}
pRoom = find_room(ch, argument, aRoom);
if ( pRoom->area != pArea )
{
send_to_char( "Cannot randomize doors in other areas.\n\r", ch );
return;
}
pReset = make_reset('R', 0, pRoom->vnum, vnum, 0);
LINK(pReset, pArea->first_reset, pArea->last_reset, next, prev);
send_to_char( "Reset random doors created.\n\r", ch );
return;
}
if ( !str_cmp(arg, "trap") )
{
char oname[MAX_INPUT_LENGTH];
int chrg, value, extra = 0;
bool isobj;
argument = one_argument(argument, oname);
argument = one_argument(argument, arg);
num = is_number(arg) ? atoi(arg) : -1;
argument = one_argument(argument, arg);
chrg = is_number(arg) ? atoi(arg) : -1;
isobj = is_name(argument, "obj");
if ( isobj == is_name(argument, "room") )
{
send_to_char( "Reset: TRAP: Must specify ROOM or OBJECT\n\r", ch );
return;
}
if ( !str_cmp(oname, "room") && !isobj )
{
vnum = (aRoom ? aRoom->vnum : ch->in_room->vnum);
extra = TRAP_ROOM;
}
else
{
if ( is_number(oname) && !isobj )
{
vnum = atoi(oname);
if ( !get_room_index(vnum) )
{
send_to_char( "Reset: TRAP: no such room\n\r", ch );
return;
}
reset = NULL;
extra = TRAP_ROOM;
}
else
{
if ( !(reset = find_oreset(ch, pArea, aRoom, oname)) )
return;
/* vnum = reset->arg1;*/
vnum = 0;
extra = TRAP_OBJ;
}
}
if ( num < 1 || num > MAX_TRAPTYPE )
{
send_to_char( "Reset: TRAP: invalid trap type\n\r", ch );
return;
}
if ( chrg < 0 || chrg > 10000 )
{
send_to_char( "Reset: TRAP: invalid trap charges\n\r", ch );
return;
}
while ( *argument )
{
argument = one_argument(argument, arg);
value = get_trapflag(arg);
if ( value < 0 || value > 31 )
{
send_to_char( "Reset: TRAP: bad flag\n\r", ch );
return;
}
SET_BIT(extra, 1 << value);
}
pReset = make_reset('T', extra, num, chrg, vnum);
if ( reset )
INSERT(pReset, reset, pArea->last_reset, prev, next);
else
LINK(pReset, pArea->first_reset, pArea->last_reset, next, prev);
send_to_char( "Trap created.\n\r", ch );
return;
}
if ( !str_cmp(arg, "bit") )
{
int (*flfunc)(char *type);
int flags = 0;
char option[MAX_INPUT_LENGTH];
char *parg;
argument = one_argument(argument, option);
if ( !*option )
{
send_to_char( "You must specify SET, REMOVE, or TOGGLE.\n\r", ch );
return;
}
num = 0;
if ( !str_prefix(option, "set") )
SET_BIT(num, BIT_RESET_SET);
else if ( !str_prefix(option, "toggle") )
SET_BIT(num, BIT_RESET_TOGGLE);
else if ( str_prefix(option, "remove") )
{
send_to_char( "You must specify SET, REMOVE, or TOGGLE.\n\r", ch );
return;
}
argument = one_argument(argument, option);
parg = argument;
argument = one_argument(argument, arg);
if ( !*option )
{
send_to_char( "Must specify OBJECT, MOBILE, ROOM, or DOOR.\n\r", ch );
return;
}
if ( !str_prefix(option, "door") )
{
SET_BIT(num, BIT_RESET_DOOR);
if ( aRoom )
{
pRoom = aRoom;
argument = parg;
}
else if ( !is_number(arg) )
{
pRoom = ch->in_room;
argument = parg;
}
else if ( !(pRoom = find_room(ch, arg, aRoom)) )
return;
argument = one_argument(argument, arg);
if ( !*arg )
{
send_to_char( "Must specify direction.\n\r", ch );
return;
}
vnum = get_dir(arg);
SET_BIT(num, vnum << BIT_RESET_DOOR_THRESHOLD);
vnum = pRoom->vnum;
flfunc = &get_exflag;
reset = NULL;
}
else if ( !str_prefix(option, "object") )
{
SET_BIT(num, BIT_RESET_OBJECT);
vnum = 0;
flfunc = &get_oflag;
if ( !(reset = find_oreset(ch, pArea, aRoom, arg)) )
return;
}
else if ( !str_prefix(option, "mobile") )
{
SET_BIT(num, BIT_RESET_MOBILE);
vnum = 0;
flfunc = &get_aflag;
if ( !(reset = find_mreset(ch, pArea, aRoom, arg)) )
return;
}
else if ( !str_prefix(option, "room") )
{
SET_BIT(num, BIT_RESET_ROOM);
if ( aRoom )
{
pRoom = aRoom;
argument = parg;
}
else if ( !is_number(arg) )
{
pRoom = ch->in_room;
argument = parg;
}
else if ( !(pRoom = find_room(ch, arg, aRoom)) )
return;
vnum = pRoom->vnum;
flfunc = &get_rflag;
reset = NULL;
}
else
{
send_to_char( "Must specify OBJECT, MOBILE, ROOM, or DOOR.\n\r", ch );
return;
}
while ( *argument )
{
int value;
argument = one_argument(argument, arg);
value = (*flfunc)(arg);
if ( value < 0 || value > 31 )
{
send_to_char( "Reset: BIT: bad flag\n\r", ch );
return;
}
SET_BIT(flags, 1 << value);
}
if ( !flags )
{
send_to_char( "Set which flags?\n\r", ch );
return;
}
pReset = make_reset('B', 1, vnum, num, flags);
if ( reset )
INSERT(pReset, reset, pArea->last_reset, prev, next);
else
LINK(pReset, pArea->first_reset, pArea->last_reset, next, prev);
send_to_char( "Bitvector reset created.\n\r", ch );
return;
}
if ( !str_cmp(arg, "hide") )
{
argument = one_argument(argument, arg);
if ( !(reset = find_oreset(ch, pArea, aRoom, arg)) )
return;
/* pReset = make_reset('H', 1, reset->arg1, 0, 0);*/
pReset = make_reset('H', 1, 0, 0, 0);
INSERT(pReset, reset, pArea->last_reset, prev, next);
send_to_char( "Object hide reset created.\n\r", ch );
return;
}
if ( ch->substate == SUB_REPEATCMD )
{
ch->substate = SUB_NONE;
interpret(ch, origarg);
ch->substate = SUB_REPEATCMD;
ch->last_cmd = (aRoom ? do_rreset : do_reset);
}
else
edit_reset(ch, "", pArea, aRoom);
return;
}
void do_reset( CHAR_DATA *ch, char *argument )
{
AREA_DATA *pArea = NULL;
char arg[MAX_INPUT_LENGTH];
char *parg;
parg = one_argument(argument, arg);
if ( ch->substate == SUB_REPEATCMD )
{
pArea = ch->dest_buf;
if ( pArea && pArea != ch->pcdata->area && pArea != ch->in_room->area )
{
AREA_DATA *tmp;
for ( tmp = first_build; tmp; tmp = tmp->next )
if ( tmp == pArea )
break;
if ( !tmp )
for ( tmp = first_area; tmp; tmp = tmp->next )
if ( tmp == pArea )
break;
if ( !tmp )
{
send_to_char("Your area pointer got lost. Reset mode off.\n\r", ch);
bug("do_reset: %s's dest_buf points to invalid area",
(int)ch->name);
ch->substate = SUB_NONE;
ch->dest_buf = NULL;
return;
}
}
if ( !*arg )
{
ch_printf(ch, "Editing resets for area: %s\n\r", pArea->name);
return;
}
if ( !str_cmp(arg, "done") || !str_cmp(arg, "off") )
{
send_to_char( "Reset mode off.\n\r", ch );
ch->substate = SUB_NONE;
ch->dest_buf = NULL;
return;
}
}
if ( !pArea && get_trust(ch) > LEVEL_GOD )
{
char fname[80];
sprintf(fname, "%s.are", capitalize(arg));
for ( pArea = first_build; pArea; pArea = pArea->next )
if ( !str_cmp(fname, pArea->filename) )
{
argument = parg;
break;
}
if ( !pArea )
pArea = ch->pcdata->area;
if ( !pArea )
pArea = ch->in_room->area;
}
else
pArea = ch->pcdata->area;
if ( !pArea )
{
send_to_char( "You do not have an assigned area.\n\r", ch );
return;
}
edit_reset(ch, argument, pArea, NULL);
return;
}
void do_rreset( CHAR_DATA *ch, char *argument )
{
ROOM_INDEX_DATA *pRoom;
if ( ch->substate == SUB_REPEATCMD )
{
pRoom = ch->dest_buf;
if ( !pRoom )
{
send_to_char( "Your room pointer got lost. Reset mode off.\n\r", ch);
bug("do_rreset: %s's dest_buf points to invalid room", (int)ch->name);
}
ch->substate = SUB_NONE;
ch->dest_buf = NULL;
return;
}
else
pRoom = ch->in_room;
if ( !can_rmodify(ch, pRoom) )
return;
edit_reset(ch, argument, pRoom->area, pRoom);
return;
}
void add_obj_reset( AREA_DATA *pArea, char cm, OBJ_DATA *obj, int v2, int v3 )
{
OBJ_DATA *inobj;
static int iNest;
if ( (cm == 'O' || cm == 'P') && obj->pIndexData->vnum == OBJ_VNUM_TRAP )
{
if ( cm == 'O' )
add_reset(pArea, 'T', obj->value[3], obj->value[1], obj->value[0], v3);
return;
}
add_reset( pArea, cm, (cm == 'P' ? iNest : 1), obj->pIndexData->vnum,
v2, v3 );
/* Only add hide for in-room objects that are hidden and cant be moved, as
hide is an update reset, not a load-only reset. */
if ( cm == 'O' && IS_OBJ_STAT(obj, ITEM_HIDDEN) &&
!IS_SET(obj->wear_flags, ITEM_TAKE) )
add_reset(pArea, 'H', 1, 0, 0, 0);
for ( inobj = obj->first_content; inobj; inobj = inobj->next_content )
if ( inobj->pIndexData->vnum == OBJ_VNUM_TRAP )
add_obj_reset(pArea, 'O', inobj, 0, 0);
if ( cm == 'P' )
iNest++;
for ( inobj = obj->first_content; inobj; inobj = inobj->next_content )
add_obj_reset( pArea, 'P', inobj, 1, 0 );
if ( cm == 'P' )
iNest--;
return;
}
void instaroom( AREA_DATA *pArea, ROOM_INDEX_DATA *pRoom, bool dodoors )
{
CHAR_DATA *rch;
OBJ_DATA *obj;
for ( rch = pRoom->first_person; rch; rch = rch->next_in_room )
{
if ( !IS_NPC(rch) )
continue;
add_reset( pArea, 'M', 1, rch->pIndexData->vnum, rch->pIndexData->count,
pRoom->vnum );
for ( obj = rch->first_carrying; obj; obj = obj->next_content )
{
if ( obj->wear_loc == WEAR_NONE )
add_obj_reset( pArea, 'G', obj, 1, 0 );
else
add_obj_reset( pArea, 'E', obj, 1, obj->wear_loc );
}
}
for ( obj = pRoom->first_content; obj; obj = obj->next_content )
{
add_obj_reset( pArea, 'O', obj, 1, pRoom->vnum );
}
if ( dodoors )
{
EXIT_DATA *pexit;
for ( pexit = pRoom->first_exit; pexit; pexit = pexit->next )
{
int state = 0;
if ( !IS_SET( pexit->exit_info, EX_ISDOOR ) )
continue;
if ( IS_SET( pexit->exit_info, EX_CLOSED ) )
{
if ( IS_SET( pexit->exit_info, EX_LOCKED ) )
state = 2;
else
state = 1;
}
add_reset( pArea, 'D', 0, pRoom->vnum, pexit->vdir, state );
}
}
return;
}
void wipe_resets( AREA_DATA *pArea, ROOM_INDEX_DATA *pRoom )
{
RESET_DATA *pReset;
for ( pReset = pArea->first_reset; pReset; )
{
if ( pReset->command != 'R' && is_room_reset( pReset, pRoom, pArea ) )
{
/* Resets always go forward, so we can safely use the previous reset,
providing it exists, or first_reset if it doesnt. -- Altrag */
RESET_DATA *prev = pReset->prev;
delete_reset(pArea, pReset);
pReset = (prev ? prev->next : pArea->first_reset);
}
else
pReset = pReset->next;
}
return;
}
void do_instaroom( CHAR_DATA *ch, char *argument )
{
AREA_DATA *pArea;
ROOM_INDEX_DATA *pRoom;
bool dodoors;
char arg[MAX_INPUT_LENGTH];
if ( IS_NPC(ch) || get_trust(ch) < LEVEL_SAVIOR || !ch->pcdata ||
!ch->pcdata->area )
{
send_to_char( "You don't have an assigned area to create resets for.\n\r",
ch );
return;
}
argument = one_argument(argument, arg);
if ( !str_cmp(argument, "nodoors") )
dodoors = FALSE;
else
dodoors = TRUE;
pArea = ch->pcdata->area;
if ( !(pRoom = find_room(ch, arg, NULL)) )
{
send_to_char( "Room doesn't exist.\n\r", ch );
return;
}
if ( !can_rmodify(ch, pRoom) )
return;
if ( pRoom->area != pArea && get_trust(ch) < LEVEL_GREATER )
{
send_to_char( "You cannot reset that room.\n\r", ch );
return;
}
if ( pArea->first_reset )
wipe_resets(pArea, pRoom);
instaroom(pArea, pRoom, dodoors);
send_to_char( "Room resets installed.\n\r", ch );
}
void do_instazone( CHAR_DATA *ch, char *argument )
{
AREA_DATA *pArea;
int vnum;
ROOM_INDEX_DATA *pRoom;
bool dodoors;
if ( IS_NPC(ch) || get_trust(ch) < LEVEL_SAVIOR || !ch->pcdata ||
!ch->pcdata->area )
{
send_to_char( "You don't have an assigned area to create resets for.\n\r",
ch );
return;
}
if ( !str_cmp(argument, "nodoors") )
dodoors = FALSE;
else
dodoors = TRUE;
pArea = ch->pcdata->area;
if ( pArea->first_reset )
wipe_resets(pArea, NULL);
for ( vnum = pArea->low_r_vnum; vnum <= pArea->hi_r_vnum; vnum++ )
{
if ( !(pRoom = get_room_index(vnum)) || pRoom->area != pArea )
continue;
instaroom( pArea, pRoom, dodoors );
}
send_to_char( "Area resets installed.\n\r", ch );
return;
}
int generate_itemlevel( AREA_DATA *pArea, OBJ_INDEX_DATA *pObjIndex )
{
int olevel;
int min = UMAX(pArea->low_soft_range, 1);
int max = UMIN(pArea->hi_soft_range, min + 15);
if ( pObjIndex->level > 0 )
olevel = UMIN(pObjIndex->level, MAX_LEVEL);
else
switch ( pObjIndex->item_type )
{
default: olevel = 0; break;
case ITEM_PILL: olevel = number_range( min, max ); break;
case ITEM_POTION: olevel = number_range( min, max ); break;
case ITEM_SCROLL: olevel = pObjIndex->value[0]; break;
case ITEM_WAND: olevel = number_range( min+4, max+1 ); break;
case ITEM_STAFF: olevel = number_range( min+9, max+5 ); break;
case ITEM_ARMOR: olevel = number_range( min+4, max+1 ); break;
case ITEM_WEAPON: olevel = number_range( min+4, max+1 ); break;
}
return olevel;
}
/*
* Reset one area.
*/
void reset_area( AREA_DATA *pArea )
{
RESET_DATA *pReset;
CHAR_DATA *mob;
OBJ_DATA *obj;
OBJ_DATA *lastobj;
ROOM_INDEX_DATA *pRoomIndex;
MOB_INDEX_DATA *pMobIndex;
OBJ_INDEX_DATA *pObjIndex;
OBJ_INDEX_DATA *pObjToIndex;
EXIT_DATA *pexit;
OBJ_DATA *to_obj;
int level = 0;
int *plc;
if ( !pArea )
{
bug( "reset_area: NULL pArea", 0 );
return;
}
mob = NULL;
obj = NULL;
lastobj = NULL;
if ( !pArea->first_reset )
{
bug( "%s: reset_area: no resets", (int)pArea->filename );
return;
}
level = 0;
for ( pReset = pArea->first_reset; pReset; pReset = pReset->next )
{
switch( pReset->command )
{
default:
bug( "Reset_area: bad command %c.", pReset->command );
break;
case 'M':
if ( !(pMobIndex = get_mob_index(pReset->arg1)) )
{
bug( "Reset_area: 'M': bad mob vnum %d.", pReset->arg1 );
continue;
}
if ( !(pRoomIndex = get_room_index(pReset->arg3)) )
{
bug( "Reset_area: 'M': bad room vnum %d.", pReset->arg3 );
continue;
}
if ( pMobIndex->count >= pReset->arg2 )
{
mob = NULL;
break;
}
mob = create_mobile(pMobIndex);
{
ROOM_INDEX_DATA *pRoomPrev = get_room_index(pReset->arg3 - 1);
if ( pRoomPrev && IS_SET(pRoomPrev->room_flags, ROOM_PET_SHOP) )
SET_BIT(mob->act, ACT_PET);
}
if ( room_is_dark(pRoomIndex) )
SET_BIT(mob->affected_by, AFF_INFRARED);
char_to_room(mob, pRoomIndex);
economize_mobgold(mob);
level = URANGE(0, mob->level - 2, LEVEL_AVATAR);
break;
case 'G':
case 'E':
if ( !(pObjIndex = get_obj_index(pReset->arg1)) )
{
bug( "Reset_area: 'E' or 'G': bad obj vnum %d.", pReset->arg1 );
continue;
}
if ( !mob )
{
lastobj = NULL;
break;
}
if ( mob->pIndexData->pShop )
{
int olevel = generate_itemlevel( pArea, pObjIndex );
obj = create_object(pObjIndex, olevel);
SET_BIT(obj->extra_flags, ITEM_INVENTORY);
}
else
obj = create_object(pObjIndex, number_fuzzy(level));
obj->level = URANGE(0, obj->level, LEVEL_AVATAR);
obj = obj_to_char(obj, mob);
if ( pReset->command == 'E' )
equip_char(mob, obj, pReset->arg3);
lastobj = obj;
break;
case 'O':
if ( !(pObjIndex = get_obj_index(pReset->arg1)) )
{
bug( "Reset_area: 'O': bad obj vnum %d.", pReset->arg1 );
continue;
}
if ( !(pRoomIndex = get_room_index(pReset->arg3)) )
{
bug( "Reset_area: 'O': bad room vnum %d.", pReset->arg3 );
continue;
}
if ( pArea->nplayer > 0 ||
count_obj_list(pObjIndex, pRoomIndex->first_content) > 0 )
{
obj = NULL;
lastobj = NULL;
break;
}
obj = create_object(pObjIndex, number_fuzzy(generate_itemlevel(pArea, pObjIndex)));
obj->level = UMIN(obj->level, LEVEL_AVATAR);
obj->cost = 0;
obj_to_room(obj, pRoomIndex);
lastobj = obj;
break;
case 'P':
if ( !(pObjIndex = get_obj_index(pReset->arg1)) )
{
bug( "Reset_area: 'P': bad obj vnum %d.", pReset->arg1 );
continue;
}
if ( pReset->arg3 > 0 )
{
if ( !(pObjToIndex = get_obj_index(pReset->arg3)) )
{
bug( "Reset_area: 'P': bad objto vnum %d.", pReset->arg3 );
continue;
}
if ( pArea->nplayer > 0 ||
!(to_obj = get_obj_type(pObjToIndex)) ||
!to_obj->in_room ||
count_obj_list(pObjIndex, to_obj->first_content) > 0 )
{
obj = NULL;
break;
}
lastobj = to_obj;
}
else
{
int iNest;
if ( !lastobj )
break;
to_obj = lastobj;
for ( iNest = 0; iNest < pReset->extra; iNest++ )
if ( !(to_obj = to_obj->last_content) )
{
bug( "Reset_area: 'P': Invalid nesting obj %d.", pReset->arg1 );
iNest = -1;
break;
}
if ( iNest < 0 )
continue;
}
obj = create_object(pObjIndex, number_fuzzy(UMAX(generate_itemlevel(pArea, pObjIndex),to_obj->level)));
obj->level = UMIN(obj->level, LEVEL_AVATAR);
obj_to_obj(obj, to_obj);
break;
case 'T':
if ( IS_SET(pReset->extra, TRAP_OBJ) )
{
/* We need to preserve obj for future 'T' and 'H' checks */
OBJ_DATA *pobj;
if ( pReset->arg3 > 0 )
{
if ( !(pObjToIndex = get_obj_index(pReset->arg3)) )
{
bug( "Reset_area: 'T': bad objto vnum %d.", pReset->arg3 );
continue;
}
if ( pArea->nplayer > 0 ||
!(to_obj = get_obj_type(pObjToIndex)) ||
(to_obj->carried_by && !IS_NPC(to_obj->carried_by)) ||
is_trapped(to_obj) )
break;
}
else
{
if ( !lastobj || !obj )
break;
to_obj = obj;
}
pobj = make_trap( pReset->arg2, pReset->arg1,
number_fuzzy(to_obj->level), pReset->extra );
obj_to_obj(pobj, to_obj);
}
else
{
if ( !(pRoomIndex = get_room_index(pReset->arg3)) )
{
bug( "Reset_area: 'T': bad room %d.", pReset->arg3 );
continue;
}
if ( pArea->nplayer > 0 ||
count_obj_list(get_obj_index(OBJ_VNUM_TRAP),
pRoomIndex->first_content) > 0 )
break;
to_obj = make_trap(pReset->arg1, pReset->arg1, 10, pReset->extra);
obj_to_room(to_obj, pRoomIndex);
}
break;
case 'H':
if ( pReset->arg1 > 0 )
{
if ( !(pObjToIndex = get_obj_index(pReset->arg1)) )
{
bug( "Reset_area: 'H': bad objto vnum %d.", pReset->arg1 );
continue;
}
if ( pArea->nplayer > 0 ||
!(to_obj = get_obj_type(pObjToIndex)) ||
!to_obj->in_room ||
to_obj->in_room->area != pArea ||
IS_OBJ_STAT(to_obj, ITEM_HIDDEN) )
break;
}
else
{
if ( !lastobj || !obj )
break;
to_obj = obj;
}
SET_BIT(to_obj->extra_flags, ITEM_HIDDEN);
break;
case 'B':
switch(pReset->arg2 & BIT_RESET_TYPE_MASK)
{
case BIT_RESET_DOOR:
{
int doornum;
if ( !(pRoomIndex = get_room_index(pReset->arg1)) )
{
bug( "Reset_area: 'B': door: bad room vnum %d.", pReset->arg1 );
continue;
}
doornum = (pReset->arg2 & BIT_RESET_DOOR_MASK)
>> BIT_RESET_DOOR_THRESHOLD;
if ( !(pexit = get_exit(pRoomIndex, doornum)) )
break;
plc = &pexit->exit_info;
}
break;
case BIT_RESET_ROOM:
if ( !(pRoomIndex = get_room_index(pReset->arg1)) )
{
bug( "Reset_area: 'B': room: bad room vnum %d.", pReset->arg1 );
continue;
}
plc = &pRoomIndex->room_flags;
break;
case BIT_RESET_OBJECT:
if ( pReset->arg1 > 0 )
{
if ( !(pObjToIndex = get_obj_index(pReset->arg1)) )
{
bug( "Reset_area: 'B': object: bad objto vnum %d.", pReset->arg1 );
continue;
}
if ( !(to_obj = get_obj_type(pObjToIndex)) ||
!to_obj->in_room ||
to_obj->in_room->area != pArea )
continue;
}
else
{
if ( !lastobj || !obj )
continue;
to_obj = obj;
}
plc = &to_obj->extra_flags;
break;
case BIT_RESET_MOBILE:
if ( !mob )
continue;
plc = &mob->affected_by;
break;
default:
bug( "Reset_area: 'B': bad options %d.", pReset->arg2 );
continue;
}
if ( IS_SET(pReset->arg2, BIT_RESET_SET) )
SET_BIT(*plc, pReset->arg3);
else if ( IS_SET(pReset->arg2, BIT_RESET_TOGGLE) )
TOGGLE_BIT(*plc, pReset->arg3);
else
REMOVE_BIT(*plc, pReset->arg3);
break;
case 'D':
if ( !(pRoomIndex = get_room_index(pReset->arg1)) )
{
bug( "Reset_area: 'D': bad room vnum %d.", pReset->arg1 );
continue;
}
if ( !(pexit = get_exit(pRoomIndex, pReset->arg2)) )
break;
switch( pReset->arg3 )
{
case 0:
REMOVE_BIT(pexit->exit_info, EX_CLOSED);
REMOVE_BIT(pexit->exit_info, EX_LOCKED);
break;
case 1:
SET_BIT( pexit->exit_info, EX_CLOSED);
REMOVE_BIT(pexit->exit_info, EX_LOCKED);
if ( IS_SET(pexit->exit_info, EX_xSEARCHABLE) )
SET_BIT( pexit->exit_info, EX_SECRET);
break;
case 2:
SET_BIT( pexit->exit_info, EX_CLOSED);
SET_BIT( pexit->exit_info, EX_LOCKED);
if ( IS_SET(pexit->exit_info, EX_xSEARCHABLE) )
SET_BIT( pexit->exit_info, EX_SECRET);
break;
}
break;
case 'R':
if ( !(pRoomIndex = get_room_index(pReset->arg1)) )
{
bug( "Reset_area: 'R': bad room vnum %d.", pReset->arg1 );
continue;
}
randomize_exits(pRoomIndex, pReset->arg2-1);
break;
}
}
return;
}
void list_resets( CHAR_DATA *ch, AREA_DATA *pArea, ROOM_INDEX_DATA *pRoom,
int start, int end )
{
RESET_DATA *pReset;
ROOM_INDEX_DATA *room;
MOB_INDEX_DATA *mob;
OBJ_INDEX_DATA *obj, *obj2;
OBJ_INDEX_DATA *lastobj;
RESET_DATA *lo_reset;
bool found;
int num = 0;
const char *rname, *mname, *oname;
char buf[256];
char *pbuf;
if ( !ch || !pArea )
return;
room = NULL;
mob = NULL;
obj = NULL;
lastobj = NULL;
lo_reset = NULL;
found = FALSE;
for ( pReset = pArea->first_reset; pReset; pReset = pReset->next )
{
if ( !is_room_reset(pReset, pRoom, pArea) )
continue;
++num;
sprintf(buf, "%2d) ", num);
pbuf = buf+strlen(buf);
switch( pReset->command )
{
default:
sprintf(pbuf, "*** BAD RESET: %c %d %d %d %d ***\n\r",
pReset->command, pReset->extra, pReset->arg1, pReset->arg2,
pReset->arg3);
break;
case 'M':
if ( !(mob = get_mob_index(pReset->arg1)) )
mname = "Mobile: *BAD VNUM*";
else
mname = mob->player_name;
if ( !(room = get_room_index(pReset->arg3)) )
rname = "Room: *BAD VNUM*";
else
rname = room->name;
sprintf( pbuf, "%s (%d) -> %s (%d) [%d]", mname, pReset->arg1, rname,
pReset->arg3, pReset->arg2 );
if ( !room )
mob = NULL;
if ( (room = get_room_index(pReset->arg3-1)) &&
IS_SET(room->room_flags, ROOM_PET_SHOP) )
strcat( buf, " (pet)\n\r" );
else
strcat( buf, "\n\r" );
break;
case 'G':
case 'E':
if ( !mob )
mname = "* ERROR: NO MOBILE! *";
if ( !(obj = get_obj_index(pReset->arg1)) )
oname = "Object: *BAD VNUM*";
else
oname = obj->name;
sprintf( pbuf, "%s (%d) -> %s (%s) [%d]", oname, pReset->arg1, mname,
(pReset->command == 'G' ? "carry" : wear_locs[pReset->arg3]),
pReset->arg2 );
if ( mob && mob->pShop )
strcat( buf, " (shop)\n\r" );
else
strcat( buf, "\n\r" );
lastobj = obj;
lo_reset = pReset;
break;
case 'O':
if ( !(obj = get_obj_index(pReset->arg1)) )
oname = "Object: *BAD VNUM*";
else
oname = obj->name;
if ( !(room = get_room_index(pReset->arg3)) )
rname = "Room: *BAD VNUM*";
else
rname = room->name;
sprintf( pbuf, "(object) %s (%d) -> %s (%d) [%d]\n\r", oname,
pReset->arg1, rname, pReset->arg3, pReset->arg2 );
if ( !room )
obj = NULL;
lastobj = obj;
lo_reset = pReset;
break;
case 'P':
if ( !(obj = get_obj_index(pReset->arg1)) )
oname = "Object1: *BAD VNUM*";
else
oname = obj->name;
obj2 = NULL;
if ( pReset->arg3 > 0 )
{
obj2 = get_obj_index(pReset->arg3);
rname = (obj2 ? obj2->name : "Object2: *BAD VNUM*");
lastobj = obj2;
}
else if ( !lastobj )
rname = "Object2: *NULL obj*";
else if ( pReset->extra == 0 )
{
rname = lastobj->name;
obj2 = lastobj;
}
else
{
int iNest;
RESET_DATA *reset;
reset = lo_reset->next;
for ( iNest = 0; iNest < pReset->extra; iNest++ )
{
for ( ; reset; reset = reset->next )
if ( reset->command == 'O' || reset->command == 'G' ||
reset->command == 'E' || (reset->command == 'P' &&
!reset->arg3 && reset->extra == iNest) )
break;
if ( !reset || reset->command != 'P' )
break;
}
if ( !reset )
rname = "Object2: *BAD NESTING*";
else if ( !(obj2 = get_obj_index(reset->arg1)) )
rname = "Object2: *NESTED BAD VNUM*";
else
rname = obj2->name;
}
sprintf( pbuf, "(Put) %s (%d) -> %s (%d) [%d] {nest %d}\n\r", oname,
pReset->arg1, rname, (obj2 ? obj2->vnum : pReset->arg3),
pReset->arg2, pReset->extra );
break;
case 'T':
sprintf(pbuf, "TRAP: %d %d %d %d (%s)\n\r", pReset->extra, pReset->arg1,
pReset->arg2, pReset->arg3, flag_string(pReset->extra, trap_flags));
break;
case 'H':
if ( pReset->arg1 > 0 )
if ( !(obj2 = get_obj_index(pReset->arg1)) )
rname = "Object: *BAD VNUM*";
else
rname = obj2->name;
else if ( !obj )
rname = "Object: *NULL obj*";
else
rname = oname;
sprintf(pbuf, "Hide %s (%d)\n\r", rname,
(pReset->arg1 > 0 ? pReset->arg1 : obj ? obj->vnum : 0));
break;
case 'B':
{
char * const *flagarray;
strcpy(pbuf, "BIT: ");
pbuf += 5;
if ( IS_SET(pReset->arg2, BIT_RESET_SET) )
{
strcpy(pbuf, "Set: ");
pbuf += 5;
}
else if ( IS_SET(pReset->arg2, BIT_RESET_TOGGLE) )
{
strcpy(pbuf, "Toggle: ");
pbuf += 8;
}
else
{
strcpy(pbuf, "Remove: ");
pbuf += 8;
}
switch(pReset->arg2 & BIT_RESET_TYPE_MASK)
{
case BIT_RESET_DOOR:
{
int door;
if ( !(room = get_room_index(pReset->arg1)) )
rname = "Room: *BAD VNUM*";
else
rname = room->name;
door = (pReset->arg2 & BIT_RESET_DOOR_MASK)
>> BIT_RESET_DOOR_THRESHOLD;
door = URANGE(0, door, MAX_DIR+1);
sprintf(pbuf, "Exit %s%s (%d), Room %s (%d)", dir_name[door],
(room && get_exit(room, door) ? "" : " (NO EXIT!)"), door,
rname, pReset->arg1);
}
flagarray = ex_flags;
break;
case BIT_RESET_ROOM:
if ( !(room = get_room_index(pReset->arg1)) )
rname = "Room: *BAD VNUM*";
else
rname = room->name;
sprintf(pbuf, "Room %s (%d)", rname, pReset->arg1);
flagarray = r_flags;
break;
case BIT_RESET_OBJECT:
if ( pReset->arg1 > 0 )
if ( !(obj2 = get_obj_index(pReset->arg1)) )
rname = "Object: *BAD VNUM*";
else
rname = obj2->name;
else if ( !obj )
rname = "Object: *NULL obj*";
else
rname = oname;
sprintf(pbuf, "Object %s (%d)", rname,
(pReset->arg1 > 0 ? pReset->arg1 : obj ? obj->vnum : 0));
flagarray = o_flags;
break;
case BIT_RESET_MOBILE:
if ( pReset->arg1 > 0 )
{
MOB_INDEX_DATA *mob2;
if ( !(mob2 = get_mob_index(pReset->arg1)) )
rname = "Mobile: *BAD VNUM*";
else
rname = mob2->player_name;
}
else if ( !mob )
rname = "Mobile: *NULL mob*";
else
rname = mname;
sprintf(pbuf, "Mobile %s (%d)", rname,
(pReset->arg1 > 0 ? pReset->arg1 : mob ? mob->vnum : 0));
flagarray = a_flags;
break;
default:
sprintf(pbuf, "bad type %d", pReset->arg2 & BIT_RESET_TYPE_MASK);
flagarray = NULL;
break;
}
pbuf += strlen(pbuf);
if ( flagarray )
sprintf(pbuf, "; flags: %s [%d]\n\r",
flag_string(pReset->arg3, flagarray), pReset->arg3);
else
sprintf(pbuf, "; flags %d\n\r", pReset->arg3);
}
break;
case 'D':
{
char *ef_name;
pReset->arg2 = URANGE(0, pReset->arg2, MAX_DIR+1);
if ( !(room = get_room_index(pReset->arg1)) )
rname = "Room: *BAD VNUM*";
else
rname = room->name;
switch(pReset->arg3)
{
default: ef_name = "(* ERROR *)"; break;
case 0: ef_name = "Open"; break;
case 1: ef_name = "Close"; break;
case 2: ef_name = "Close and lock"; break;
}
sprintf(pbuf, "%s [%d] the %s%s [%d] door %s (%d)\n\r", ef_name,
pReset->arg3, dir_name[pReset->arg2],
(room && get_exit(room, pReset->arg2) ? "" : " (NO EXIT!)"),
pReset->arg2, rname, pReset->arg1);
}
break;
case 'R':
if ( !(room = get_room_index(pReset->arg1)) )
rname = "Room: *BAD VNUM*";
else
rname = room->name;
sprintf(pbuf, "Randomize exits 0 to %d -> %s (%d)\n\r", pReset->arg2,
rname, pReset->arg1);
break;
}
if ( start == -1 || num >= start )
send_to_char( buf, ch );
if ( end != -1 && num >= end )
break;
}
if ( num == 0 )
send_to_char( "You don't have any resets defined.\n\r", ch );
return;
}
/* Setup put nesting levels, regardless of whether or not the resets will
actually reset, or if they're bugged. */
void renumber_put_resets( AREA_DATA *pArea )
{
RESET_DATA *pReset, *lastobj = NULL;
for ( pReset = pArea->first_reset; pReset; pReset = pReset->next )
{
switch(pReset->command)
{
default:
break;
case 'G': case 'E': case 'O':
lastobj = pReset;
break;
case 'P':
if ( pReset->arg3 == 0 )
{
if ( !lastobj )
pReset->extra = 1000000;
else if ( lastobj->command != 'P' || lastobj->arg3 > 0 )
pReset->extra = 0;
else
pReset->extra = lastobj->extra+1;
lastobj = pReset;
}
}
}
return;
}
/*
* Create a new reset (for online building) -Thoric
*/
RESET_DATA *make_reset( char letter, int extra, int arg1, int arg2, int arg3 )
{
RESET_DATA *pReset;
CREATE( pReset, RESET_DATA, 1 );
pReset->command = letter;
pReset->extra = extra;
pReset->arg1 = arg1;
pReset->arg2 = arg2;
pReset->arg3 = arg3;
top_reset++;
return pReset;
}
/*
* Add a reset to an area -Thoric
*/
RESET_DATA *add_reset( AREA_DATA *tarea, char letter, int extra, int arg1, int arg2, int arg3 )
{
RESET_DATA *pReset;
if ( !tarea )
{
bug( "add_reset: NULL area!", 0 );
return NULL;
}
letter = UPPER(letter);
pReset = make_reset( letter, extra, arg1, arg2, arg3 );
switch( letter )
{
case 'M': tarea->last_mob_reset = pReset; break;
case 'H': if ( arg1 > 0 ) break;
case 'E': case 'G': case 'P':
case 'O': tarea->last_obj_reset = pReset; break;
case 'T':
if ( IS_SET( extra, TRAP_OBJ ) && arg1 == 0)
tarea->last_obj_reset = pReset;
break;
}
LINK( pReset, tarea->first_reset, tarea->last_reset, next, prev );
return pReset;
}
/*
* Place a reset into an area, insert sorting it -Thoric
*/
RESET_DATA *place_reset( AREA_DATA *tarea, char letter, int extra, int arg1, int arg2, int arg3 )
{
RESET_DATA *pReset, *tmp, *tmp2;
if ( !tarea )
{
bug( "place_reset: NULL area!", 0 );
return NULL;
}
letter = UPPER(letter);
pReset = make_reset( letter, extra, arg1, arg2, arg3 );
if ( letter == 'M' )
tarea->last_mob_reset = pReset;
if ( tarea->first_reset )
{
switch( letter )
{
default:
bug( "place_reset: Bad reset type %c", letter );
return NULL;
case 'D': case 'R':
for ( tmp = tarea->last_reset; tmp; tmp = tmp->prev )
if ( tmp->command == letter )
break;
if ( tmp ) /* organize by location */
for ( ; tmp && tmp->command == letter && tmp->arg1 > arg1; tmp = tmp->prev );
if ( tmp ) /* organize by direction */
for ( ; tmp && tmp->command == letter && tmp->arg1 == tmp->arg1 && tmp->arg2 > arg2; tmp = tmp->prev );
if ( tmp )
INSERT( pReset, tmp, tarea->first_reset, next, prev );
else
LINK( pReset, tarea->first_reset, tarea->last_reset, next, prev );
return pReset;
case 'M': case 'O':
/* find last reset of same type */
for ( tmp = tarea->last_reset; tmp; tmp = tmp->prev )
if ( tmp->command == letter )
break;
tmp2 = tmp ? tmp->next : NULL;
/* organize by location */
for ( ; tmp; tmp = tmp->prev )
if ( tmp->command == letter && tmp->arg3 <= arg3 )
{
tmp2 = tmp->next;
/* organize by vnum */
if ( tmp->arg3 == arg3 )
for ( ; tmp; tmp = tmp->prev )
if ( tmp->command == letter
&& tmp->arg3 == tmp->arg3
&& tmp->arg1 <= arg1 )
{
tmp2 = tmp->next;
break;
}
break;
}
/* skip over E or G for that mob */
if ( tmp2 && letter == 'M' )
{
for ( ; tmp2; tmp2 = tmp2->next )
if ( tmp2->command != 'E' && tmp2->command != 'G' )
break;
}
else
/* skip over P, T or H for that obj */
if ( tmp2 && letter == 'O' )
{
for ( ; tmp2; tmp2 = tmp2->next )
if ( tmp2->command != 'P' && tmp2->command != 'T'
&& tmp2->command != 'H' )
break;
}
if ( tmp2 )
INSERT( pReset, tmp2, tarea->first_reset, next, prev );
else
LINK( pReset, tarea->first_reset, tarea->last_reset, next, prev );
return pReset;
case 'G': case 'E':
/* find the last mob */
if ( (tmp=tarea->last_mob_reset) != NULL )
{
/*
* See if there are any resets for this mob yet,
* put E before G and organize by vnum
*/
if ( tmp->next )
{
tmp = tmp->next;
if ( tmp && tmp->command == 'E' )
{
if ( letter == 'E' )
for ( ; tmp && tmp->command == 'E' && tmp->arg1 < arg1; tmp = tmp->next );
else
for ( ; tmp && tmp->command == 'E'; tmp = tmp->next );
}
else
if ( tmp && tmp->command == 'G' && letter == 'G' )
for ( ; tmp && tmp->command == 'G' && tmp->arg1 < arg1; tmp = tmp->next );
if ( tmp )
INSERT( pReset, tmp, tarea->first_reset, next, prev );
else
LINK( pReset, tarea->first_reset, tarea->last_reset, next, prev );
}
else
LINK( pReset, tarea->first_reset, tarea->last_reset, next, prev );
return pReset;
}
break;
case 'P': case 'T': case 'H':
/* find the object in question */
if ( ((letter == 'P' && arg3 == 0)
|| (letter == 'T' && IS_SET(extra, TRAP_OBJ) && arg1 == 0)
|| (letter == 'H' && arg1 == 0))
&& (tmp=tarea->last_obj_reset) != NULL )
{
if ( (tmp=tmp->next) != NULL )
INSERT( pReset, tmp, tarea->first_reset, next, prev );
else
LINK( pReset, tarea->first_reset, tarea->last_reset, next, prev );
return pReset;
}
for ( tmp = tarea->last_reset; tmp; tmp = tmp->prev )
if ( (tmp->command == 'O' || tmp->command == 'G'
|| tmp->command == 'E' || tmp->command == 'P')
&& tmp->arg1 == arg3 )
{
/*
* See if there are any resets for this object yet,
* put P before H before T and organize by vnum
*/
if ( tmp->next )
{
tmp = tmp->next;
if ( tmp && tmp->command == 'P' )
{
if ( letter == 'P' && tmp->arg3 == arg3 )
for ( ; tmp && tmp->command == 'P' && tmp->arg3 == arg3 && tmp->arg1 < arg1; tmp = tmp->next );
else
if ( letter != 'T' )
for ( ; tmp && tmp->command == 'P' && tmp->arg3 == arg3; tmp = tmp->next );
}
else
if ( tmp && tmp->command == 'H' )
{
if ( letter == 'H' && tmp->arg3 == arg3 )
for ( ; tmp && tmp->command == 'H' && tmp->arg3 == arg3 && tmp->arg1 < arg1; tmp = tmp->next );
else
if ( letter != 'H' )
for ( ; tmp && tmp->command == 'H' && tmp->arg3 == arg3; tmp = tmp->next );
}
else
if ( tmp && tmp->command == 'T' && letter == 'T' )
for ( ; tmp && tmp->command == 'T' && tmp->arg3 == arg3 && tmp->arg1 < arg1; tmp = tmp->next );
if ( tmp )
INSERT( pReset, tmp, tarea->first_reset, next, prev );
else
LINK( pReset, tarea->first_reset, tarea->last_reset, next, prev );
}
else
LINK( pReset, tarea->first_reset, tarea->last_reset, next, prev );
return pReset;
}
break;
}
/* likely a bad reset if we get here... add it anyways */
}
LINK( pReset, tarea->first_reset, tarea->last_reset, next, prev );
return pReset;
}