Mud20/accounts/
Mud20/accounts/c/
Mud20/accounts/f/
Mud20/accounts/k/
Mud20/accounts/s/
Mud20/accounts/t/
Mud20/area_current/
Mud20/area_current/newareas/
Mud20/bin/
Mud20/clans/
Mud20/gods/
Mud20/old-sources/
Mud20/player/
Mud20/player/a/del/
Mud20/player/b/
Mud20/player/b/bak/
Mud20/player/b/del/
Mud20/player/f/
Mud20/player/f/bak/
Mud20/player/f/del/
Mud20/player/k/
Mud20/player/k/bak/
Mud20/player/k/del/
Mud20/player/k/dmp/
Mud20/player/m/
Mud20/player/m/bak/
Mud20/player/o/
Mud20/player/o/bak/
Mud20/player/p/
Mud20/player/s/
Mud20/player/s/bak/
Mud20/player/s/del/
Mud20/player/t/
Mud20/player/t/del/
Mud20/player/v/
Mud20/public_html/
Mud20/races/
Mud20/skilltables/
__MACOSX/Mud20/accounts/
__MACOSX/Mud20/accounts/c/
__MACOSX/Mud20/accounts/f/
__MACOSX/Mud20/accounts/k/
__MACOSX/Mud20/accounts/s/
__MACOSX/Mud20/area_current/
__MACOSX/Mud20/area_current/core_areas/
__MACOSX/Mud20/area_current/helps/
__MACOSX/Mud20/area_current/newareas/
__MACOSX/Mud20/backups/
__MACOSX/Mud20/bin/
__MACOSX/Mud20/clans/
__MACOSX/Mud20/gods/
__MACOSX/Mud20/log/
__MACOSX/Mud20/old-sources/
__MACOSX/Mud20/player/
__MACOSX/Mud20/player/a/del/
__MACOSX/Mud20/player/b/
__MACOSX/Mud20/player/b/bak/
__MACOSX/Mud20/player/f/
__MACOSX/Mud20/player/f/bak/
__MACOSX/Mud20/player/f/del/
__MACOSX/Mud20/player/k/
__MACOSX/Mud20/player/k/bak/
__MACOSX/Mud20/player/k/del/
__MACOSX/Mud20/player/k/dmp/
__MACOSX/Mud20/player/m/
__MACOSX/Mud20/player/m/bak/
__MACOSX/Mud20/player/o/
__MACOSX/Mud20/player/o/bak/
__MACOSX/Mud20/player/p/
__MACOSX/Mud20/player/s/
__MACOSX/Mud20/player/s/bak/
__MACOSX/Mud20/player/t/del/
__MACOSX/Mud20/player/v/
__MACOSX/Mud20/public_html/
__MACOSX/Mud20/races/
__MACOSX/Mud20/skilltables/
/***************************************************************************
 * 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;
}