/***************************************************************************
* Mud20 1.0 by Todd H. Johnson (Kregor) a derivative of the Open Gaming *
* License by Wizards of the Coast. All comments referring to D20, OGL, *
* and SRD refer to the System Reference Document for the Open Gaming *
* system. Any inclusion of these derivatives must include credit to the *
* Mud20 system, the full and complete Open Gaming LIcense, and credit to *
* the respective authors. See ../doc/srd.txt for more information. *
* *
* Emud 2.2 by Igor van den Hoven, Michiel Lange, and Martin Bethlehem. *
* *
* MrMud 1.4 by David Bills, Dug Michael and Martin Gallwey *
* *
* 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{rfeld, Tom Madsen, and Katje Nyboe. *
***************************************************************************/
/***************************************************************************
* reset.c: Server resets and repops *
***************************************************************************/
#include "mud.h"
/*
Externals
*/
void list_resets args( ( CHAR_DATA *ch, ROOM_INDEX_DATA *pRoom ) );
RESET_DATA * find_reset args( ( ROOM_INDEX_DATA *room, int num ) );
RESET_DATA * parse_reset args( ( ROOM_INDEX_DATA *room, int type, char *argument, CHAR_DATA *ch ) );
/*
* Added flags and bitvectors for real-engligh
* flags in reset edits and displays - Kregor
*/
typedef enum
{
RESET_MOBILE = 0,
RESET_CARRY,
RESET_EQUIP,
RESET_OBJECT,
RESET_CONTENT,
RESET_TRAP,
RESET_DOOR,
RESET_RANDOM
} reset_cmd_flags;
char * const reset_flags [] =
{
"mobile",
"carry",
"equip",
"object",
"content",
"trap",
"door",
"random",
"*"
};
void do_rredit( CHAR_DATA *ch, char *argument )
{
ROOM_INDEX_DATA *room;
RESET_DATA *reset1, *reset2;
char arg[MAX_INPUT_LENGTH];
char buf[MAX_INPUT_LENGTH];
char *origarg = argument;
char colg[10], colw[10], colW[10], colM[10];
sh_int type;
push_call("do_rredit(%p,%p)",ch,argument);
CHECK_EDITMODE( ch );
strcpy(colw, ansi_translate_text(ch, "{078}"));
strcpy(colg, ansi_translate_text(ch, "{028}"));
strcpy(colW, ansi_translate_text(ch, "{178}"));
strcpy(colM, ansi_translate_text(ch, "{158}"));
if (!ch->desc)
{
send_to_char( "You have no descriptor.\n\r", ch );
pop_call();
return;
}
smash_tilde(argument);
if (ch->pcdata->editmode == MODE_REPEATCMD)
{
room = ch->pcdata->edit_ptr;
if (argument[0] == '?')
{
/*
Show rredit status
*/
ch_printf_color(ch, "Syntax: <command> <argument>\n\r\n\r");
ch_printf_color(ch, "Command being one of:\n\r");
ch_printf_color(ch, " del set ? stat done < >\n\r");
pop_call();
return;
}
if (!strcasecmp(argument, "done"))
{
send_to_char( "RRedit mode off.\n\r", ch );
stop_olc_editing(ch, room->area);
pop_call();
return;
}
if (!strcmp(argument, ">"))
{
if (get_room_index(room->vnum + 1) && can_olc_modify(ch, room->vnum + 1))
{
stop_olc_editing(ch, room->area);
sprintf(buf, "%d", room->vnum + 1);
do_rredit(ch, buf);
}
else
{
ch_printf_color(ch, "Next index not found.\n\r");
}
pop_call();
return;
}
if (!strcmp(argument, "<"))
{
if (get_room_index(room->vnum - 1) && can_olc_modify(ch, room->vnum - 1))
{
stop_olc_editing(ch, room->area);
sprintf(buf, "%d", room->vnum - 1);
do_rredit(ch, buf);
}
else
{
ch_printf_color(ch, "Prev index not found.\n\r");
}
pop_call();
return;
}
if (!strcasecmp(argument, "list") || !strcasecmp(argument, "stat") || argument[0] == ' ')
{
list_resets(ch, room);
pop_call();
return;
}
}
else if (argument[0] == '\0')
{
if (!can_olc_modify(ch, ch->in_room->vnum))
{
send_to_char("This room is not in your allocated range.\n\r", ch);
pop_call();
return;
}
room = ch->in_room;
}
else if ((room = get_room_index(atoi(argument))) == NULL)
{
send_to_char("Syntax: edit reset [room vnum]\n\r", ch);
pop_call();
return;
}
else if (!can_olc_modify(ch, room->vnum))
{
send_to_char("That vnum is not in your allocated range.\n\r", ch);
pop_call();
return;
}
argument = one_argument(argument, arg);
if (!strcasecmp(arg, "del") || !strcasecmp(arg, "delete"))
{
if (!is_number(argument))
{
ch_printf_color(ch, "Syntax: delete <index>");
}
else if ((reset1 = find_reset(room, atoi(argument))) == NULL)
{
ch_printf_color(ch, "Index %s not found.\n\r", argument);
}
else
{
delete_reset(room->area, reset1);
}
}
else if (!strcasecmp(arg, "set"))
{
argument = one_argument(argument, arg);
if ((type = get_flag(arg, reset_flags)) == -1)
{
send_to_char("Invalid reset type.\n\r", ch);
pop_call();
return;
}
argument = one_argument(argument, arg);
if ((reset1 = find_reset(room, atoi(arg))) == NULL)
{
switch (type)
{
default:
case RESET_TRAP:
ch_printf_color(ch, "That reset type must target an existing door or object reset.\n\r");
break;
case RESET_CONTENT:
ch_printf_color(ch, "That reset type must target an existing container object reset.\n\r");
break;
case RESET_EQUIP:
case RESET_CARRY:
ch_printf_color(ch, "That reset type must target an existing mobile reset.\n\r");
break;
case RESET_MOBILE:
case RESET_OBJECT:
case RESET_DOOR:
case RESET_RANDOM:
if ((reset1 = parse_reset(room, type, argument, ch)) != NULL)
{
LINK(reset1, room->area->first_reset, room->area->last_reset, next, prev);
}
break;
}
}
else if (reset1->command == 'M')
{
switch (type)
{
case RESET_CARRY:
case RESET_EQUIP:
if ((reset2 = parse_reset(room, type, argument, ch)) != NULL)
{
reset2->container = reset1;
INSERT_RIGHT(reset2, reset1, room->area->last_reset, next, prev);
}
break;
case RESET_CONTENT:
ch_printf_color(ch, "You can only set contents into other object resets.\n\r");
break;
case RESET_TRAP:
ch_printf_color(ch, "You can only set traps on object or door resets.\n\r");
break;
default:
if ((reset2 = parse_reset(room, type, argument, ch)) != NULL)
{
INSERT_LEFT(reset2, reset1, room->area->first_reset, next, prev);
}
break;
}
}
else if (reset1->command == 'O')
{
switch (type)
{
case RESET_CONTENT:
case RESET_TRAP:
if ((reset2 = parse_reset(room, type, argument, ch)) != NULL)
{
reset2->container = reset1;
reset2->arg3 = reset1->arg1;
INSERT_RIGHT(reset2, reset1, room->area->last_reset, next, prev);
}
break;
case RESET_CARRY:
case RESET_EQUIP:
ch_printf_color(ch, "You must target a mobile reset to give it an object.\n\r");
break;
default:
if ((reset2 = parse_reset(room, type, argument, ch)) != NULL)
{
INSERT_LEFT(reset2, reset1, room->area->first_reset, next, prev);
}
break;
}
}
else if (reset1->command == 'D')
{
if (type == RESET_TRAP)
{
if ((reset2 = parse_reset(room, type, argument, ch)) != NULL)
{
reset2->container = reset1;
reset2->arg2 = reset1->arg1;
INSERT_RIGHT(reset2, reset1, room->area->last_reset, next, prev);
}
}
else
{
ch_printf_color(ch, "You can only set traps on door resets.\n\r");
}
}
else if (reset1->command == 'G' || reset1->command == 'E')
{
switch (type)
{
case RESET_CONTENT:
case RESET_TRAP:
if ((reset2 = parse_reset(room, type, argument, ch)) != NULL)
{
reset2->container = reset1;
reset2->arg3 = reset1->arg1;
INSERT_RIGHT(reset2, reset1, room->area->last_reset, next, prev);
}
break;
case RESET_CARRY:
case RESET_EQUIP:
ch_printf_color(ch, "You must target the mobile carrying the object.\n\r");
break;
default:
ch_printf_color(ch, "You can only set contents or traps into other objects.\n\r");
break;
}
}
else
{
switch (type)
{
case RESET_CARRY:
case RESET_EQUIP:
ch_printf_color(ch, "You can only put carry or equip resets onto mobile resets.\n\r");
break;
case RESET_CONTENT:
ch_printf_color(ch, "You can only put contents into other object resets.\n\r");
break;
case RESET_TRAP:
ch_printf_color(ch, "You can only set traps on object and door resets.\n\r");
break;
default:
if ((reset2 = parse_reset(room, type, argument, ch)) != NULL)
{
INSERT_LEFT(reset2, reset1, room->area->first_reset, next, prev);
}
break;
}
}
}
else if (ch->pcdata->editmode != MODE_REPEATCMD)
{
ch->pcdata->edit_ptr = room;
ch->pcdata->edittype = EDIT_TYPE_RESET;
ch_printf_color(ch, "Editing Room Reset: %d\n\r", room->vnum);
ch->pcdata->editmode = MODE_REPEATCMD;
if (ch->pcdata)
{
if (ch->pcdata->subprompt)
{
STRFREE(ch->pcdata->subprompt);
}
sprintf(arg, "Editing Room Reset: %d", room->vnum);
ch->pcdata->subprompt = STRALLOC( arg );
}
do_rredit(ch, "stat");
pop_call();
return;
}
else if (ch->pcdata->editmode == MODE_REPEATCMD)
{
ch->pcdata->editmode = MODE_RESTRICTED;
interpret(ch, origarg);
ch->pcdata->editmode = MODE_REPEATCMD;
ch->pcdata->last_cmd = do_edit;
pop_call();
return;
}
do_rredit(ch, "stat");
pop_call();
return;
}
RESET_DATA *find_reset(ROOM_INDEX_DATA *room, int numb)
{
RESET_DATA *reset;
int num = 0;
push_call("find_reset(%p,%p)",room,numb);
for (reset = room->area->first_reset ; reset ; reset = reset->next)
{
if (is_room_reset(reset, room) && ++num == numb)
{
pop_call();
return reset;
}
}
pop_call();
return NULL;
}
bool is_room_reset(RESET_DATA *reset, ROOM_INDEX_DATA *room)
{
push_call("is_room_reset(%p,%p)",reset,room);
switch (reset->command)
{
case 'M':
case 'O':
if (room->vnum == reset->arg3)
{
pop_call();
return TRUE;
}
break;
case 'P':
pop_call();
return is_room_reset(reset->container, room);
case 'G':
case 'E':
if (room->vnum == reset->container->arg3)
{
pop_call();
return TRUE;
}
break;
case 'D':
case 'R':
if (room->vnum == reset->arg1)
{
pop_call();
return TRUE;
}
break;
}
pop_call();
return FALSE;
}
bool is_obj_reset(RESET_DATA *reset, OBJ_INDEX_DATA *obj)
{
push_call("is_obj_reset(%p,%p)",reset,obj);
switch (reset->command)
{
case 'O':
case 'P':
case 'G':
case 'E':
if (obj->vnum == reset->arg1)
{
pop_call();
return TRUE;
}
break;
}
pop_call();
return FALSE;
}
bool is_mob_reset(RESET_DATA *reset, MOB_INDEX_DATA *mob)
{
push_call("is_mob_reset(%p,%p)",reset,mob);
switch (reset->command)
{
case 'M':
if (mob->vnum == reset->arg1)
{
pop_call();
return TRUE;
}
break;
}
pop_call();
return FALSE;
}
bool is_door_reset(RESET_DATA *reset, int door)
{
push_call("is_door_reset(%p,%p)",reset,door);
switch (reset->command)
{
case 'D':
if (door == reset->arg2)
{
pop_call();
return TRUE;
}
break;
}
pop_call();
return FALSE;
}
/*
Doing this my way, it works - Scandum
*/
void delete_reset( AREA_DATA *pArea, RESET_DATA *pReset )
{
RESET_DATA *reset;
push_call("delete_reset(%p,%p)",pArea,pReset);
if (pReset->command == 'M')
{
for (reset = pReset->next ; reset ; )
{
if (reset->command == 'M')
{
break;
}
if (reset->command == 'G' || reset->command == 'E')
{
delete_reset(pArea, reset);
reset = pReset->next;
}
else
{
reset = reset->next;
}
}
}
else if (pReset->command == 'E' || pReset->command == 'G' || pReset->command == 'O')
{
for (reset = pReset->next ; reset ; )
{
if (reset->command != 'P')
{
break;
}
delete_reset(pArea, reset);
reset = pReset->next;
}
}
if (pReset->mob) pReset->mob->reset = NULL;
if (pReset->obj) pReset->obj->reset = NULL;
UNLINK(pReset, pArea->first_reset, pArea->last_reset, next, prev);
FREEMEM(pReset);
pop_call();
return;
}
/*
Reset one area.
*/
void reset_area( AREA_DATA *pArea )
{
ROOM_INDEX_DATA *pRoomIndex;
MOB_INDEX_DATA *pMobIndex;
OBJ_INDEX_DATA *pObjIndex;
RESET_DATA *pReset;
CHAR_DATA *mob;
EXIT_DATA *pExit;
OBJ_DATA *obj, *obj2;
int cnt;
bool d0, d1;
push_call("reset_area(%p)",pArea);
if (IS_SET(mud->flags, MUD_EMUD_BOOTDB))
{
pArea->average_level = 0;
pArea->count = 0;
pArea->tmp = 0;
for (pReset = pArea->first_reset ; pReset ; pReset = pReset->next)
{
switch ( pReset->command )
{
case 'M':
if ((pMobIndex = get_mob_index(pReset->arg1)) == NULL)
{
log_printf("reset_area: 'M': bad mobile vnum %d.", pReset->arg1);
abort();
}
if ((pRoomIndex = get_room_index(pReset->arg3)) == NULL)
{
log_printf("reset_area: 'M': bad room vnum %d.", pReset->arg3);
abort();
}
if (IS_SET(pRoomIndex->room_flags, ROOM_CLANHALL))
{
pMobIndex->creator_pvnum = pRoomIndex->creator_pvnum;
}
if (IS_SET(pMobIndex->act, ACT_MOBINVIS))
{
continue;
}
if (!IS_SET(pMobIndex->act , ACT_AGGRESSIVE))
{
pArea->average_level += pMobIndex->level/3;
}
else
{
pArea->average_level += pMobIndex->level;
}
pArea->tmp++;
break;
case 'O':
if ((pObjIndex = get_obj_index(pReset->arg1)) == NULL)
{
log_printf("reset_area: 'O': bad obj vnum %d.", pReset->arg1);
abort();
}
if ((pRoomIndex = get_room_index(pReset->arg3)) == NULL)
{
log_printf("reset_area: 'O': bad room vnum %d.", pReset->arg3);
abort();
}
if (IS_SET(pRoomIndex->room_flags, ROOM_CLANHALL))
{
pObjIndex->creator_pvnum = pRoomIndex->creator_pvnum;
}
break;
case 'P':
if (get_obj_index(pReset->arg1) == NULL)
{
log_printf( "reset_area: 'P': bad obj vnum %d.", pReset->arg1 );
abort();
}
if (pReset->container == NULL)
{
log_printf( "reset_area: 'P': bad container vnum %d.", pReset->arg3 );
abort();
}
break;
case 'T':
if (get_obj_index(pReset->arg1) == NULL)
{
log_printf( "reset_area: 'T': bad obj vnum %d.", pReset->arg1 );
abort();
}
if (!IS_OBJ_TYPE(get_obj_index(pReset->arg1), ITEM_TRAP))
{
log_printf( "reset_area: 'T': obj vnum %d not a trap.", pReset->arg1 );
abort();
}
if (pReset->container == NULL)
{
log_printf( "reset_area: 'T': bad container vnum %d.", pReset->arg2 );
abort();
}
break;
case 'G':
case 'E':
if (get_obj_index(pReset->arg1) == NULL)
{
log_printf("reset_area: '%c' bad obj vnum %d.", pReset->command, pReset->arg1);
abort();
}
if (pReset->container == NULL)
{
log_printf( "reset_area: '%c': bad container vnum %d.", pReset->command, pReset->arg3 );
abort();
}
break;
case 'D':
if (get_room_index(pReset->arg1) == NULL)
{
log_printf("reset_area: 'D': bad vnum %d.", pReset->arg1);
abort();
}
if (pReset->arg2 < 0 || pReset->arg2 > 5)
{
log_printf("reset_area: 'D': invalid direction: %d.", pReset->arg2);
abort();
}
if (get_room_index(pReset->arg1)->exit[pReset->arg2] == NULL)
{
log_printf("reset_area: 'D': invalid connection: %d %d", pReset->arg1, pReset->arg2);
abort();
}
break;
case 'R':
if (get_room_index(pReset->arg1) == NULL)
{
log_printf("Reset_area: 'R': bad vnum %d.", pReset->arg1);
abort();
}
if (pReset->arg2 < 0 || pReset->arg2 > 5)
{
log_printf("reset_area: 'R': invalid direction: %d", pReset->arg2);
abort();
}
break;
default:
log_printf("reset_area: bad command %c.", pReset->command);
break;
}
}
if (pArea->tmp != 0)
{
pArea->average_level /= pArea->tmp;
}
else
{
pArea->average_level = 100;
}
}
for (pReset = pArea->first_reset ; pReset ; pReset = pReset->next)
{
switch ( pReset->command )
{
default:
break;
case 'M':
if (pReset->mob)
{
if (mud->sunlight == SUN_DARK && IS_ACT(pReset->mob, ACT_DAY)) // Thanks to Rhythmic for the idea - Kregor
extract_char(pReset->mob);
else if (mud->sunlight != SUN_DARK && IS_ACT(pReset->mob, ACT_NIGHT))
extract_char(pReset->mob);
else if (number_percent() > pReset->arg2)
extract_char(pReset->mob);
else if (pArea->nplayer == 0) //restore mob if area cleared. Leave alone if players still here. - Kregor
{
for (cnt = 0 ; cnt < MAX_REAL_SKILL ; cnt++)
pReset->mob->uses[cnt] = 0;
restore_mana(pReset->mob);
pReset->mob->hit = get_max_hit(pReset->mob);
pReset->mob->nonlethal = 0;
pReset->mob->move = get_max_move(pReset->mob);
}
continue;
}
pMobIndex = mob_index[pReset->arg1];
/* changed to make value a % chance of popping */
if (number_percent() > pReset->arg2
|| (mud->sunlight != SUN_DARK && IS_SET(pMobIndex->act, ACT_NIGHT))
|| (mud->sunlight == SUN_DARK && IS_SET(pMobIndex->act, ACT_DAY))) // added Rhythmic's day/night mobs idea
{
continue;
}
mob = create_mobile( pMobIndex );
mob->reset = pReset;
pReset->mob = mob;
char_to_room( mob, pReset->arg3, TRUE );
if (is_string(pMobIndex->reset_msg) && (pArea->nplayer > 0))
act( pMobIndex->reset_msg, mob, NULL, NULL, TO_ROOM);
mprog_repop_trigger(mob);
break;
case 'O':
if (pReset->obj)
{
if (number_percent() > pReset->arg2)
{
extract_obj(pReset->obj);
continue;
}
continue;
}
/* changed to make value a % chance of popping */
if (number_percent() > pReset->arg2)
{
continue;
}
pObjIndex = obj_index[pReset->arg1];
obj = create_object( pObjIndex, 0);
obj->reset = pReset;
pReset->obj = obj;
obj_to_room( obj, pReset->arg3 );
oprog_repop_trigger(obj);
break;
case 'P':
if (pReset->obj)
{
if (number_percent() > pReset->arg2)
{
extract_obj(pReset->obj);
continue;
}
continue;
}
if (pReset->container->obj == NULL)
{
continue;
}
pObjIndex = obj_index[pReset->arg1];
/* changed to make value a % chance of popping */
if (number_percent() > pReset->arg2)
{
continue;
}
obj = create_object(pObjIndex, 0);
obj->reset = pReset;
pReset->obj = obj;
obj_to_obj(obj, pReset->container->obj);
break;
case 'T':
if (pReset->obj)
{
if (pArea->nplayer) // do not reset trap if people in area - Kregor
continue;
if (IS_OBJ_TYPE(pReset->obj, ITEM_TRAP)) //reset traps if coded to reset, purge one-shot traps
{
if (TRAP_RESET(pReset->obj) == TRAP_RESET_AUTO && !TRAP_STATE(pReset->obj))
{
if (!obj->in_room->area->nplayer)
{
TRAP_STATE(pReset->obj) = TRAP_ARMED;
}
}
else if (TRAP_RESET(pReset->obj) == TRAP_RESET_NONE && !TRAP_STATE(pReset->obj))
{
extract_obj(pReset->obj);
continue;
}
pReset->obj->value[2] = pReset->obj->pIndexData->value[2];
}
continue;
}
if (pReset->container->command != 'D' && pReset->container->obj == NULL)
continue;
pObjIndex = obj_index[pReset->arg1];
obj = create_object(pObjIndex, 0);
obj->reset = pReset;
pReset->obj = obj;
if (IS_OBJ_TYPE(obj, ITEM_TRAP))
{
if (!TRAP_STATE(obj))
{
TRAP_STATE(obj) = TRAP_ARMED;
}
}
obj->value[2] = obj->pIndexData->value[2];
if (pReset->container->command == 'D')
obj_to_room(obj, pReset->arg2);
else
obj_to_obj(obj, pReset->container->obj);
break;
case 'G':
case 'E':
if (pReset->obj)
{
if (number_percent() > pReset->arg2)
extract_obj(pReset->obj);
break;
}
if (pReset->container->mob == NULL)
{
continue;
}
mob = pReset->container->mob;
pObjIndex = obj_index[pReset->arg1];
/* changed to make value a % chance of popping */
if (number_percent() > pReset->arg2)
{
continue;
}
obj = create_object(pObjIndex, 0);
obj->reset = pReset;
pReset->obj = obj;
if (mob->pIndexData->pShop)
obj->identified = TRUE;
obj_to_char(obj, mob);
/* remove conflicting obj locations from resets */
if (pReset->command == 'E')
{
/* resize armor for mobile size */
if (IS_OBJ_TYPE(obj, ITEM_ARMOR))
obj->value[3] = mob->size;
if ((obj2 = get_eq_char(mob, pReset->arg3)) != NULL) // junks load_eq obj in favor of reset obj
{
extract_obj(obj2);
}
equip_char(mob, obj, pReset->arg3);
}
break;
case 'D':
pExit = room_index[pReset->arg1]->exit[pReset->arg2];
REMOVE_BIT( pExit->exit_info, EX_BASHED);
REMOVE_BIT( pExit->exit_info, EX_KNOCKED);
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 );
break;
case 2:
SET_BIT( pExit->exit_info, EX_CLOSED );
SET_BIT( pExit->exit_info, EX_LOCKED );
break;
}
break;
case 'R':
pRoomIndex = room_index[pReset->arg1];
for (d0 = 0 ; d0 <= pReset->arg2 ; d0++)
{
d1 = number_range(d0, pReset->arg2);
pExit = pRoomIndex->exit[d0];
pRoomIndex->exit[d0] = pRoomIndex->exit[d1];
pRoomIndex->exit[d1] = pExit;
}
break;
}
}
pArea->count++;
if (pArea->low_r_vnum == ROOM_VNUM_SCHOOL)
{
pArea->age = 39;
}
else
{
pArea->age = number_fuzzy(33 - pArea->average_level/3);
}
pop_call();
return;
}
/*
No checks here, debugging is done elsewhere - Scandum
*/
void list_resets(CHAR_DATA *ch, ROOM_INDEX_DATA *room)
{
RESET_DATA *reset;
MOB_INDEX_DATA *mob;
OBJ_INDEX_DATA *obj;
OBJ_INDEX_DATA *cont;
int num = 0;
char buf[MAX_STRING_LENGTH];
char colg[10], colw[10], colW[10], colM[10];
push_call("list_resets(%p,%p)",ch,room);
mob = NULL;
buf[0] = '\0';
strcpy(colw, get_color_string(ch, COLOR_TEXT, VT102_DIM));
strcpy(colg, get_color_string(ch, COLOR_ACCENT, VT102_DIM));
strcpy(colW, get_color_string(ch, COLOR_TEXT, VT102_BOLD));
strcpy(colM, ansi_translate_text(ch, "{158}"));
for (reset = room->area->first_reset ; reset ; reset = reset->next)
{
if (!is_room_reset(reset, room))
{
continue;
}
cont = NULL;
cat_sprintf(buf, "%s%2d%s] ", colW, ++num, colw);
switch (reset->command)
{
default:
cat_sprintf(buf, "%s*** BAD RESET: %c %d %d %d ***\n\r", colW, reset->command, reset->arg1, reset->arg2, reset->arg3);
break;
case 'M':
mob = get_mob_index(reset->arg1);
cat_sprintf(buf, "%s Mobile %s%06d %03d %06d", colg, colW, reset->arg1, reset->arg2, reset->arg3);
if (get_room_index(reset->arg3) == NULL)
{
strcat(buf, "**WARNING NO ROOM INDEX**\n\r");
}
else if (mob == NULL)
{
strcat(buf, "**WARNING NO MOBILE INDEX**\n\r");
}
else
{
cat_sprintf(buf, " %s(%s%s %s%d%% in room)\n\r", colw, colW, mob->player_name, colw, reset->arg2);
}
break;
case 'G':
case 'E':
if (reset->command == 'E')
{
cat_sprintf(buf, "%s Equip %s%06d %03d ", colg, colW, reset->arg1, reset->arg2);
cat_sprintf(buf, "%s", capitalize_all(type_string(reset->arg3, wear_locs)));
}
else
{
cat_sprintf(buf, "%s Carry %s%06d %03d ", colg, colW, reset->arg1, reset->arg2);
}
if (mob == NULL)
{
strcat(buf, "**WARNING NO MOBILE REFERENCE**");
}
else if ((obj = get_obj_index(reset->arg1)) == NULL)
{
strcat(buf, "**WARNING NO OBJECT INDEX**");
}
else
{
cat_sprintf(buf, " %s(%s%s %s%d%%)", colw, colW, obj->name, colw, reset->arg2);
}
if (mob->pShop)
{
cat_sprintf(buf, " %s(Shop)", colw);
}
strcat(buf, "\n\r");
break;
case 'O':
cont = get_obj_index(reset->arg1);
cat_sprintf(buf, "%s Object %s%06d %03d ", colg, colW, reset->arg1, reset->arg2);
if (get_room_index(reset->arg3) == NULL)
{
strcat(buf, "**WARNING NO ROOM INDEX**\n\r");
}
else if (cont == NULL)
{
strcat(buf, "**WARNING NO OBJECT INDEX**\n\r");
}
else
{
cat_sprintf(buf, " %s(%s%s %s%d%% in room)\n\r", colw, colW, cont->name, colw, reset->arg2);
}
break;
case 'P':
cat_sprintf(buf, "%sContent %s%06d %03d ", colg, colW, reset->arg1, reset->arg2);
if ((cont = get_obj_index(reset->arg3)) == NULL)
{
strcat(buf, "**WARNING NO CONTAINER OBJ INDEX**\n\r");
}
else if ((obj = get_obj_index(reset->arg1)) == NULL)
{
strcat(buf, "**WARNING NO OBJECT INDEX**\n\r");
}
else
{
cat_sprintf(buf, " %s(%s%s %s%d%% into %s%s)\n\r", colw, colW, obj->name, colw, reset->arg2, colW, cont->name);
}
break;
case 'T':
cat_sprintf(buf, "%s Trap %s%06d %03d %s ", colg, colW, reset->arg1, reset->arg2, flag_string(reset->arg3, trap_triggers));
if ((obj = get_obj_index(reset->arg1)) == NULL)
{
strcat(buf, "**WARNING NO OBJECT INDEX**\n\r");
}
else if (reset->container->command != 'D' && reset->container->obj == NULL)
{
strcat(buf, "**WARNING NO CONTAINER OBJ INDEX**\n\r");
}
else if (reset->container->command == 'D')
{
cat_sprintf(buf, " %s(%s%s %son door)\n\r", colw, colW, obj->name, colw);
}
else
{
cat_sprintf(buf, " %s(%s%s %sset on %s%s)\n\r", colw, colW, obj->name, colw, colW, reset->container->obj->name);
}
break;
case 'D':
cat_sprintf(buf, "%s Door", colg);
cat_sprintf(buf, " %s%-5s ", colW, capitalize_all(dir_name[reset->arg2]));
cat_sprintf(buf, "%s%s\n\r", colw, capitalize_all(type_string(reset->arg3, reset_exit_types)));
break;
case 'R':
cat_sprintf(buf, "%s Random", colg);
cat_sprintf(buf, " %s%s\n\r", colW, capitalize_all(type_string(reset->arg2, reset_rand_types)));
break;
}
}
if (strlen(buf) > 0)
{
send_to_char_color(buf, ch);
}
else
{
send_to_char( "This room does not have any resets defined.\n\r", ch);
}
pop_call();
return;
}
/*
Setup put nesting levels, regardless of whether or not the resets will
actually reset, or if they're bugged.
*/
RESET_DATA *make_reset( char letter, int arg1, int arg2, int arg3 )
{
RESET_DATA *reset;
push_call("make_reset(%p,%p,%p,%p)",letter,arg1,arg2,arg3);
ALLOCMEM( reset, RESET_DATA, 1 );
reset->command = letter;
reset->arg1 = arg1;
reset->arg2 = arg2;
reset->arg3 = arg3;
mud->top_reset++;
pop_call();
return reset;
}
/*
Parse a reset command string into a reset_data structure
*/
RESET_DATA *parse_reset(ROOM_INDEX_DATA *room, int type, char *argument, CHAR_DATA *ch)
{
char arg2[MAX_INPUT_LENGTH];
char arg3[MAX_INPUT_LENGTH];
char arg4[MAX_INPUT_LENGTH];
int val1, val2, val3;
push_call("parce_reset(%p,%p,%p)",room,argument,ch);
argument = one_argument( argument, arg2 );
argument = one_argument( argument, arg3 );
argument = one_argument( argument, arg4 );
val1 = atoi( arg2 );
val2 = atoi( arg3 );
val3 = atoi( arg4 );
if (arg2[0] == '\0')
{
switch (type)
{
default:
ch_printf_color(ch, "Syntax: set <reset type> <index> <argument>\n\r");
break;
case RESET_MOBILE:
ch_printf_color(ch, "Syntax: set mobile <index> <mob vnum> <percent>\n\r");
break;
case RESET_CARRY:
ch_printf_color(ch, "Syntax: set carry <mob reset index> <obj vnum> <percent>\n\r");
break;
case RESET_EQUIP:
ch_printf_color(ch, "Syntax: set equip <mob reset index> <obj vnum> <percent> <wear location>\n\r");
break;
case RESET_TRAP:
ch_printf_color(ch, "Syntax: set trap <obj or door reset index> <trap vnum>\n\r");
break;
case RESET_OBJECT:
ch_printf_color(ch, "Syntax: set object <index> <obj vnum> <percent>\n\r");
break;
case RESET_CONTENT:
ch_printf_color(ch, "Syntax: set content <obj reset index> <obj vnum> <percent>\n\r");
break;
case RESET_DOOR:
ch_printf_color(ch, "Syntax: set door <index> <dir> <door reset flag>\n\r");
break;
case RESET_RANDOM:
ch_printf_color(ch, "Syntax: set random <index> <randomize flags>\n\r");
break;
}
pop_call();
return NULL;
}
switch (type)
{
default:
parse_reset(room, 0, "", ch);
break;
case RESET_MOBILE:
if (!get_mob_index(val1))
{
ch_printf_color(ch, "<%d> No such mobile.\n\r", val1);
break;
}
if (!can_olc_modify(ch, val1))
{
ch_printf_color(ch, "vnum %d is not in your allocated range.\n\r", val1);
break;
}
if (val2 == 0)
{
val2 = 100;
}
pop_call();
return make_reset('M', val1, URANGE(1, val2, 100), room->vnum);
case RESET_OBJECT:
if (!get_obj_index(val1))
{
ch_printf_color(ch, "<%d> no such object.\n\r", val1);
break;
}
if (!can_olc_modify(ch, val1))
{
ch_printf_color(ch, "vnum %d is not in your allocated range.\n\r", val1);
break;
}
if (val2 == 0)
{
val2 = 100;
}
pop_call();
return make_reset('O', val1, URANGE(1, val2, 100), room->vnum);
case RESET_CARRY:
if (!get_obj_index(val1))
{
ch_printf_color(ch, "<%d> no such object.\n\r", val1);
break;
}
if (!can_olc_modify(ch, val1))
{
ch_printf_color(ch, "vnum %d is not in your allocated range.\n\r", val1);
break;
}
if (val2 == 0)
{
val2 = 100;
}
pop_call();
return make_reset('G', val1, URANGE(1, val2, 100), 0);
case RESET_EQUIP:
if (!get_obj_index(val1))
{
ch_printf_color(ch, "<%d> no such object.\n\r", val1);
break;
}
if (!can_olc_modify(ch, val1))
{
ch_printf_color(ch, "vnum %d is not in your allocated range.\n\r", val1);
break;
}
if ((val3 = get_flag(arg4, wear_locs)) == -1)
{
ch_printf_color(ch, "Wear Flags: <%s>\n\r", give_flags(wear_locs));
break;
}
pop_call();
return make_reset('E', val1, URANGE(1, val2, 100), val3);
case RESET_CONTENT:
if (!get_obj_index(val1))
{
ch_printf_color(ch, "<%d> no such object.\n\r", val1);
break;
}
if (!can_olc_modify(ch, val1))
{
ch_printf_color(ch, "vnum %d is not in your allocated range.\n\r", val1);
break;
}
if (val2 == 0)
{
val2 = 100;
}
pop_call();
return make_reset('P', val1, URANGE(1, val2, 100), 0);
case RESET_TRAP:
if (!get_obj_index(val1))
{
ch_printf_color(ch, "<%d> no such object.\n\r", val1);
break;
}
if (!can_olc_modify(ch, val1))
{
ch_printf_color(ch, "vnum %d is not in your allocated range.\n\r", val1);
break;
}
// if ((val3 = get_flag(arg2, trap_triggers)) == -1)
// {
// ch_printf_color(ch, "Syntax: set <index> t <%s>\n\r", give_flags(trap_triggers));
// break;
// }
pop_call();
return make_reset('T', val1, 0, obj_index[val1]->value[2]);
case RESET_DOOR:
if ((val2 = direction_door(arg2)) == -1)
{
ch_printf_color(ch, "<%s> not a valid direction.\n\r", arg2);
break;
}
if (room->exit[val2] == NULL)
{
ch_printf_color(ch, "There is no exit to the %s.\n\r", dir_name[val2]);
break;
}
if ((val3 = get_flag(arg3, reset_exit_types)) == -1)
{
ch_printf_color(ch, "Exit Reset Flags <%s>\n\r", give_flags(reset_exit_types));
break;
}
pop_call();
return make_reset('D', room->vnum, val2, val3);
case RESET_RANDOM:
if ((val2 = get_flag(arg2, reset_rand_types)) == -1)
{
ch_printf_color(ch, "Syntax: set <random> [index] <%s>\n\r", give_flags(reset_rand_types));
break;
}
pop_call();
return make_reset('R', room->vnum, val2, 0);
}
pop_call();
return NULL;
}
/*
* Add a reset to an area -Martin
*/
RESET_DATA *add_reset( AREA_DATA *tarea, char letter, 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, arg1, arg2, arg3 );
LINK( pReset, tarea->first_reset, tarea->last_reset, next, prev );
return pReset;
}
void add_obj_reset( AREA_DATA *pArea, char cm, OBJ_DATA *obj, int v2, int v3 )
{
OBJ_DATA *inobj;
static int iNest;
add_reset( pArea, cm, 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 == 'P')
iNest++;
for (inobj = obj->first_content; inobj; inobj = inobj->next_content)
{
if (is_trap_armed(inobj))
add_obj_reset( pArea, 'T', inobj, obj->pIndexData->vnum, inobj->value[2] );
else
add_obj_reset( pArea, 'P', inobj, 100, 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', rch->pIndexData->vnum, 100, pRoom->vnum );
for ( obj = rch->first_carrying; obj; obj = obj->next_content )
{
if ( obj->wear_loc == WEAR_NONE )
add_obj_reset( pArea, 'G', obj, 100, 0 );
else if (!rch->pIndexData->load_eq[obj->wear_loc])
add_obj_reset( pArea, 'E', obj, 100, obj->wear_loc );
}
}
for ( obj = pRoom->first_content; obj; obj = obj->next_content )
{
add_obj_reset( pArea, 'O', obj, 100, pRoom->vnum );
}
if ( dodoors )
{
EXIT_DATA *pExit;
int door;
for ( door = 0 ; door<6; door++)
{
int state = 0;
if ((pExit = pRoom->exit[door] ) == NULL)
continue;
if (!IS_SET(pExit->exit_info, EX_ISDOOR)
&& (obj = get_room_trap(pRoom, trap_dir[door]|trap_door[door])) == NULL)
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', pRoom->vnum, door, state );
if (obj != NULL)
add_obj_reset( pArea, 'T', obj, pRoom->vnum, obj->value[2] );
}
}
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))
{
/* 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 *pAreaIndex;
ROOM_INDEX_DATA *pRoomIndex;
bool dodoors;
char arg[MAX_INPUT_LENGTH];
if ( IS_NPC(ch) || !ch->pcdata )
{
return;
}
argument = one_argument(argument, arg);
if ( !strcasecmp(argument, "nodoors") )
dodoors = FALSE;
else
dodoors = TRUE;
if ((pRoomIndex = room_index[atoi(arg)]) == NULL)
{
send_to_char( "Room doesn't exist.\n\r", ch );
return;
}
pAreaIndex = pRoomIndex->area;
if (!can_olc_modify(ch, pRoomIndex->vnum))
{
send_to_char("That vnum is not in your allocated range.\n\r", ch);
return;
}
if ( pAreaIndex->first_reset )
wipe_resets(pAreaIndex, pRoomIndex);
instaroom(pAreaIndex, pRoomIndex, dodoors);
send_to_char( "Room resets installed.\n\r", ch );
}
void do_instazone( CHAR_DATA *ch, char *argument )
{
AREA_DATA *pAreaIndex;
int vnum;
ROOM_INDEX_DATA *pRoomIndex;
bool dodoors;
if ( IS_NPC(ch) || !ch->pcdata )
{
return;
}
if ( !strcasecmp(argument, "nodoors") )
dodoors = FALSE;
else
dodoors = TRUE;
if (!can_olc_modify(ch, ch->in_room->vnum))
{
send_to_char("This area is not in your allocated range.\n\r", ch);
return;
}
pAreaIndex = ch->in_room->area;
if ( pAreaIndex->first_reset )
wipe_resets(pAreaIndex, NULL);
for ( vnum = pAreaIndex->low_r_vnum; vnum <= pAreaIndex->hi_r_vnum; vnum++ )
{
if ((pRoomIndex = room_index[vnum]) == NULL || pRoomIndex->area != pAreaIndex )
continue;
instaroom( pAreaIndex, pRoomIndex, dodoors );
}
send_to_char( "Area resets installed.\n\r", ch );
return;
}