/*************************************************************************** * 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; }