/* ************************************************* * file: redit.cc * * authors: Andrew Hynek, Nick Robertson, Jon Lin, * * Phrodo, Demise, Terra, Washu * * purpose: Room Editor for AwakeOLC, a * * component of AwakeMUD * * (c) 1997-1999 Andrew Hynek, (c) 2001 * * The AwakeMUD Consortium * ************************************************* */ #include <string.h> #include <stdio.h> #include <stdlib.h> #include "structs.h" #include "awake.h" #include "interpreter.h" #include "comm.h" #include "spells.h" #include "utils.h" #include "db.h" #include "boards.h" #include "screen.h" #include "olc.h" #include "memory.h" extern class memoryClass *Mem; /* change this depending on the number of flags you have defined */ #define NUM_ROOM_SECTORS 15 #define NUM_ROOM_FLAGS 26 #define NUM_ROOM_FUNCS 6 #define ROOM d->edit_room extern int top_of_world; extern int top_of_world_array; extern struct room_data *world; extern struct obj_data *obj_proto; extern struct char_data *mob_proto; extern const char *room_bits[]; extern const char *sector_types[]; extern const char *exit_bits[]; extern const char *dirs[]; extern struct zone_data *zone_table; extern struct char_data *character_list; extern sh_int r_mortal_start_room; extern sh_int r_immort_start_room; extern sh_int r_frozen_start_room; extern sh_int r_newbie_start_room; extern int olc_state; extern char *material_names[]; extern char *barrier_names[]; extern const char *room_functions[]; extern int material_ratings[]; extern int barrier_ratings[]; extern int rev_dir[]; extern void char_to_room(struct char_data * ch, int room); // extern funcs extern char *cleanup(char *dest, const char *src); extern char *remove_CRs(char *string); extern bool resize_world_array(); extern int real_zone(int); /* function protos */ void redit_disp_extradesc_menu(struct descriptor_data * d); void redit_disp_exit_menu(struct descriptor_data * d); void redit_disp_exit_flag_menu(struct descriptor_data * d); void redit_disp_flag_menu(struct descriptor_data * d); void redit_disp_sector_menu(struct descriptor_data * d); void redit_disp_menu(struct descriptor_data * d); void redit_parse(struct descriptor_data * d, char *arg); void write_world_to_disk(int vnum); /************************************************************************** Menu functions **************************************************************************/ void redit_disp_barrier_menu(struct descriptor_data *d) { CLS(CH); for (register int counter = 0; counter < NUM_BARRIERS; ++counter) send_to_char(CH, "%2d) %s\r\n", counter + 1, barrier_names[counter]); send_to_char("Enter construction category, 0 to return: ", CH); } void redit_disp_material_menu(struct descriptor_data *d) { CLS(CH); for (register int counter = 0; counter < NUM_MATERIALS; ++counter) send_to_char(CH, "%2d) %s\r\n", counter + 1, material_names[counter]); send_to_char("Enter material type, 0 to return: ", CH); } /* For extra descriptions */ void redit_disp_extradesc_menu(struct descriptor_data * d) { struct extra_descr_data *extra_desc = (struct extra_descr_data *) * d->misc_data; send_to_char(CH, "Extra descript menu\r\n" "0) Quit\r\n" "1) Keyword: %s%s%s\r\n" "2) Description:\r\n%s\r\n", CCCYN(CH, C_CMP), extra_desc->keyword, CCNRM(CH, C_CMP), (extra_desc->description ? extra_desc->description : "(none)")); send_to_char(CH, "3) %s\r\n" "Enter Choice:\r\n", (extra_desc->next ? "Another description set. (not viewed)" : "Another description")); d->edit_mode = REDIT_EXTRADESC_MENU; } /* For exits */ void redit_disp_exit_menu(struct descriptor_data * d) { CLS(CH); #define DOOR d->edit_room->dir_option[d->edit_number2] /* if exit doesn't exist, alloc/create it and clear it*/ if(!DOOR) { DOOR = new room_direction_data; memset((char *) DOOR, 0, sizeof (struct room_direction_data)); DOOR->barrier = 4; DOOR->condition = DOOR->barrier; DOOR->material = 5; } send_to_char(CH, "1) Exit to: %s%d%s\r\n" "2) Description: %s\r\n", CCCYN(CH, C_CMP), DOOR->to_room_vnum, CCNRM(CH, C_CMP), (DOOR->general_description ? DOOR->general_description : "(None)")); send_to_char(CH, "3) Door names: %s%s%s\r\n" "4) Key vnum: %s%d%s\r\n" "5) Door flag: %s%s%s\r\n", CCCYN(CH, C_CMP), (DOOR->keyword ? DOOR->keyword : "(none)"), CCNRM(CH, C_CMP), CCCYN(CH, C_CMP), DOOR->key, CCNRM(CH, C_CMP), CCCYN(CH, C_CMP), (IS_SET(DOOR->exit_info, EX_ISDOOR) ? (IS_SET(DOOR->exit_info, EX_PICKPROOF) ? "Pickproof" : "Regular door") : "No door"), CCNRM(CH, C_CMP)); send_to_char(CH, "6) Lock level: %s%d%s\r\n" "7) Material Type: %s%s%s\r\n" "8) Barrier Rating: %s%d%s\r\n", CCCYN(CH, C_CMP), DOOR->key_level, CCNRM(CH, C_CMP), CCCYN(CH, C_CMP), material_names[DOOR->material], CCNRM(CH, C_CMP), CCCYN(CH, C_CMP), DOOR->barrier, CCNRM(CH, C_CMP)); send_to_char(CH, "9) Hidden Rating: %s%d%s\r\n" "a) Purge exit.\r\n" "Enter choice, 0 to quit:", CCCYN(CH, C_CMP), DOOR->hidden, CCNRM(CH, C_CMP)); d->edit_mode = REDIT_EXIT_MENU; } /* For exit flags */ void redit_disp_exit_flag_menu(struct descriptor_data * d) { send_to_char( "0) No door\r\n" "1) Closeable door\r\n" "2) Pickproof\r\n" "Enter choice:", CH); } /* For room flags */ void redit_disp_flag_menu(struct descriptor_data * d) { int counter; CLS(CH); for (counter = 0; counter < NUM_ROOM_FLAGS; counter += 2) { send_to_char(CH, "%2d) %-10s %2d) %-10s\r\n", counter + 1, room_bits[counter], counter + 2, counter + 1 < NUM_ROOM_FLAGS ? room_bits[counter + 1] : ""); } sprintbit(d->edit_room->room_flags, room_bits, buf1); send_to_char(CH, "Room flags: %s%s%s\r\n" "Enter room flags, 0 to quit:", CCCYN(CH, C_CMP), buf1, CCNRM(CH, C_CMP)); d->edit_mode = REDIT_FLAGS; } /* for sector type */ void redit_disp_sector_menu(struct descriptor_data * d) { int counter; CLS(CH); for (counter = 0; counter < NUM_ROOM_SECTORS; counter += 2) { sprintf(buf, "%2d) %-10s %2d) %-10s\r\n", counter, sector_types[counter], counter + 1, counter + 1 < NUM_ROOM_SECTORS ? sector_types[counter + 1] : ""); send_to_char(buf, d->character); } send_to_char("Enter sector type:", d->character); d->edit_mode = REDIT_SECTOR; } void redit_disp_func_menu(struct descriptor_data *d) { int i; CLS(CH); d->edit_mode = REDIT_ROOM_FUNCTION; for (i = 0; i <= NUM_ROOM_FUNCS; i++) send_to_char(CH, " %d) %s\r\n", i, room_functions[i]); send_to_char("Enter room function: ", CH); } /* the main menu */ void redit_disp_menu(struct descriptor_data * d) { CLS(CH); d->edit_mode = REDIT_MAIN_MENU; send_to_char(CH, "Room number: %s%d%s\r\n" "1) Room name: %s%s%s\r\n", CCCYN(CH, C_CMP), d->edit_number, CCNRM(CH, C_CMP), CCCYN(CH, C_CMP), d->edit_room->name, CCNRM(CH, C_CMP)); send_to_char(CH, "2) Room Desc:\r\n%s\r\n", d->edit_room->description); send_to_char(CH, "Room zone: %s%d%s\r\n", CCCYN(CH, C_CMP), zone_table[d->edit_room->zone].number, CCNRM(CH, C_CMP)); sprintbit((long) d->edit_room->room_flags, room_bits, buf2); send_to_char(CH, "3) Room flags: %s%s%s\r\n", CCCYN(CH, C_CMP), buf2, CCNRM(CH, C_CMP)); sprinttype(d->edit_room->sector_type, sector_types, buf2); send_to_char(CH, "4) Sector type: %s%s%s\r\n",CCCYN(CH, C_CMP), buf2, CCNRM(CH, C_CMP)); if (d->edit_room->dir_option[NORTH]) send_to_char(CH, "5) Exit north to: %s%d%s\r\n", CCCYN(CH, C_CMP), d->edit_room->dir_option[NORTH]->to_room_vnum, CCNRM(CH, C_CMP)); else send_to_char( "5) Exit north to: (none)\r\n", CH); if (d->edit_room->dir_option[NORTHEAST]) send_to_char(CH, "6) Exit northeast to: %s%d%s\r\n", CCCYN(CH, C_CMP), d->edit_room->dir_option[NORTHEAST]->to_room_vnum, CCNRM(CH, C_CMP)); else send_to_char( "6) Exit northeast to: (none)\r\n", CH); if (d->edit_room->dir_option[EAST]) send_to_char(CH, "7) Exit east to: %s%d%s\r\n", CCCYN(CH, C_CMP), d->edit_room->dir_option[EAST]->to_room_vnum, CCNRM(CH, C_CMP)); else send_to_char( "7) Exit east to: (none)\r\n", CH); if (d->edit_room->dir_option[SOUTHEAST]) send_to_char(CH, "8) Exit southeast to: %s%d%s\r\n", CCCYN(CH, C_CMP), d->edit_room->dir_option[SOUTHEAST]->to_room_vnum, CCNRM(CH, C_CMP)); else send_to_char( "8) Exit southeast to: (none)\r\n", CH); if (d->edit_room->dir_option[SOUTH]) send_to_char(CH, "9) Exit south to: %s%d%s\r\n", CCCYN(CH, C_CMP), d->edit_room->dir_option[SOUTH]->to_room_vnum, CCNRM(CH, C_CMP)); else send_to_char( "9) Exit south to: (none)\r\n", CH); if (d->edit_room->dir_option[SOUTHWEST]) send_to_char(CH, "a) Exit southwest to: %s%d%s\r\n", CCCYN(CH, C_CMP), d->edit_room->dir_option[SOUTHWEST]->to_room_vnum, CCNRM(CH, C_CMP)); else send_to_char( "a) Exit southwest to: (none)\r\n", CH); if (d->edit_room->dir_option[WEST]) send_to_char(CH, "b) Exit west to: %s%d%s\r\n", CCCYN(CH, C_CMP), d->edit_room->dir_option[WEST]->to_room_vnum, CCNRM(CH, C_CMP)); else send_to_char( "b) Exit west to: (none)\r\n", CH); if (d->edit_room->dir_option[NORTHWEST]) send_to_char(CH, "c) Exit northwest to: %s%d%s\r\n", CCCYN(CH, C_CMP), d->edit_room->dir_option[NORTHWEST]->to_room_vnum, CCNRM(CH, C_CMP)); else send_to_char( "c) Exit northwest to: (none)\r\n", CH); if (d->edit_room->dir_option[UP]) send_to_char(CH, "d) Exit up to: %s%d%s\r\n", CCCYN(CH, C_CMP), d->edit_room->dir_option[UP]->to_room_vnum, CCNRM(CH, C_CMP)); else send_to_char( "d) Exit up to: (none)\r\n", CH); if (d->edit_room->dir_option[DOWN]) send_to_char(CH, "e) Exit down to: %s%d%s\r\n", CCCYN(CH, C_CMP), d->edit_room->dir_option[DOWN]->to_room_vnum, CCNRM(CH, C_CMP)); else send_to_char( "e) Exit down to: (none)\r\n", CH); if (d->edit_room->dir_option[MATRIX]) send_to_char(CH, "f) Exit matrix to: %s%d%s\r\n", CCCYN(CH, C_CMP), d->edit_room->dir_option[MATRIX]->to_room_vnum, CCNRM(CH, C_CMP)); else send_to_char( "f) Exit matrix to: (none)\r\n", CH); send_to_char("g) Extra descriptions\r\n", d->character); // send this option if they make the room a library if (ROOM->sector_type == SECT_WATER_SWIM) send_to_char(CH, "h) Current rating: %s%d%s\r\n", CCCYN(CH, C_CMP), ROOM->rating, CCNRM(CH, C_CMP)); else if (IS_SET(ROOM->room_flags, ROOM_HERMETIC_LIBRARY) || IS_SET(ROOM->room_flags, ROOM_MEDICINE_LODGE) || IS_SET(ROOM->room_flags, ROOM_FALL)) send_to_char(CH, "h) Library or Climb Rating: %s%d%s\r\n", CCCYN(CH, C_CMP), ROOM->rating, CCNRM(CH, C_CMP)); else if (IS_SET(ROOM->room_flags, ROOM_MATRIX)) { send_to_char(CH, "h) Node rating: %s%d%s\r\n", CCCYN(CH, C_CMP), ROOM->rating, CCNRM(CH, C_CMP)); if (ROOM->sector_type >= SECT_BLUE) send_to_char(CH, "i) Node function: %s%s%s\r\n", CCCYN(CH, C_CMP), room_functions[ROOM->spec], CCNRM(CH, C_CMP)); } if (access_level(CH, LVL_PRESIDENT)) send_to_char(CH, "s) MSP trigger: %s%s%s\r\n", CCCYN(CH, C_CMP), ROOM->msp_trigger ? ROOM->msp_trigger : "(none)", CCNRM(CH, C_CMP)); send_to_char("q) Quit and save\r\n", d->character); send_to_char("x) Exit and abort\r\n", d->character); send_to_char("Enter your choice:\r\n", d->character); } /************************************************************************** The main loop **************************************************************************/ void redit_parse(struct descriptor_data * d, char *arg) { extern struct room_data *world; SPECIAL(cpu); SPECIAL(datastore); SPECIAL(input_output); SPECIAL(spu); SPECIAL(system_access); SPECIAL(slave); int number; int room_num; int min, max; switch (d->edit_mode) { case REDIT_CONFIRM_EDIT: switch (*arg) { case 'y': case 'Y': // put the allocation over here! redit_disp_menu(d); break; case 'n': case 'N': /* player doesn't want to edit, free entire temp room */ STATE(d) = CON_PLAYING; if (d->edit_room) Mem->DeleteRoom(d->edit_room); d->edit_room = NULL; REMOVE_BIT(PLR_FLAGS(d->character), PLR_EDITING); char_to_room(CH, GET_WAS_IN(CH)); GET_WAS_IN(CH) = NOWHERE; break; default: send_to_char("That's not a valid choice!\r\n", d->character); send_to_char("Do you wish to edit it?\r\n", d->character); break; } break; /* end of REDIT_CONFIRM_EDIT */ case REDIT_CONFIRM_SAVESTRING: switch (*arg) { case 'y': case 'Y': { int counter, counter2; struct extra_descr_data *This, *next_one; room_num = real_room(d->edit_number); if (room_num > 0) { /* copy people/object pointers over to the temp room as a temporary measure */ d->edit_room->contents = world[room_num].contents; d->edit_room->people = world[room_num].people; // we use free_room here because we aren't ready to turn it over // to the stack just yet as we're gonna use it immediately free_room(world + room_num); /* now copy everything over! */ world[room_num] = *d->edit_room; } else { /* hm, we can't just copy.. gotta insert a new room */ int counter; int counter2; int found = 0; // check first if you need to resize it if ((top_of_world + 1) >= top_of_world_array) // if it can't resize, free the edit_room and return if (!resize_world_array()) { send_to_char("Unable to save, OLC temporarily unavailable.\r\n" ,CH); Mem->DeleteRoom(d->edit_room); olc_state = 0; d->edit_room = NULL; REMOVE_BIT(PLR_FLAGS(d->character), PLR_EDITING); STATE(d) = CON_PLAYING; char_to_room(CH, GET_WAS_IN(CH)); GET_WAS_IN(CH) = NOWHERE; return; } /* count thru world tables */ for (counter = 0; counter < top_of_world + 1; counter++) { if (!found) { /* check if current virtual is bigger than our virtual */ if (world[counter].number > d->edit_number) { // now, zoom backwards through the list copying over for (counter2 = top_of_world + 1; counter2 > counter; counter2--) { world[counter2] = world[counter2 - 1]; } world[counter] = *(d->edit_room); world[counter].number = d->edit_number; world[counter].func = NULL; found = TRUE; } } else { // okay, it's been found and inserted // anything in a room after the one inserted needs their // real numbers increased struct char_data *temp_ch; struct obj_data *temp_obj; for (temp_ch = world[counter].people; temp_ch; temp_ch = temp_ch->next_in_room) { if (temp_ch->in_room != NOWHERE) temp_ch->in_room++; } /* move objects */ for (temp_obj = world[counter].contents; temp_obj; temp_obj = temp_obj->next_content) if (temp_obj->in_room != -1) temp_obj->in_room++; } // end else } // end 'insert' for-loop /* if place not found, insert at end */ if (!found) { world[top_of_world + 1] = *d->edit_room; world[top_of_world + 1].number = d->edit_number; world[top_of_world + 1].func = NULL; } top_of_world++; /* now this is the *real* room_num */ room_num = real_room(d->edit_number); /* now zoom through the character list and update anyone in limbo */ struct char_data * temp_ch; for (temp_ch = character_list; temp_ch; temp_ch = temp_ch->next) { if (GET_WAS_IN(temp_ch) >= room_num) GET_WAS_IN(temp_ch)++; } /* update zone tables */ { extern int top_of_zone_table; int zone, cmd_no; for (zone = 0; zone <= top_of_zone_table; zone++) for (cmd_no = 0; cmd_no < zone_table[zone].num_cmds; cmd_no++) { switch (ZCMD.command) { case 'M': ZCMD.arg3 = (ZCMD.arg3 >= room_num ? ZCMD.arg3 + 1 : ZCMD.arg3); break; case 'O': if (ZCMD.arg3 != NOWHERE) ZCMD.arg3 = (ZCMD.arg3 >= room_num ? ZCMD.arg3 + 1 : ZCMD.arg3); break; case 'D': ZCMD.arg1 = (ZCMD.arg1 >= room_num ? ZCMD.arg1 + 1 : ZCMD.arg1); break; case 'R': /* rem obj from room */ ZCMD.arg1 = (ZCMD.arg1 >= room_num ? ZCMD.arg1 + 1 : ZCMD.arg1); break; } } } /* update load rooms, to fix creeping load room problem */ if (room_num <= r_mortal_start_room) r_mortal_start_room++; if (room_num <= r_immort_start_room) r_immort_start_room++; if (room_num <= r_frozen_start_room) r_frozen_start_room++; if (room_num <= r_newbie_start_room) r_newbie_start_room++; /* go through the world. if any of the old rooms indicated an exit * to our new room, we have to change it */ for (counter = 0; counter < top_of_world + 1; counter++) { for (counter2 = 0; counter2 < NUM_OF_DIRS; counter2++) { /* if exit exists */ if (world[counter].dir_option[counter2]) { /* increment r_nums for rooms bigger than or equal to new one * because we inserted room */ if (world[counter].dir_option[counter2]->to_room >= room_num) world[counter].dir_option[counter2]->to_room += 1; /* if an exit to the new room is indicated, change to_room */ if (world[counter].dir_option[counter2]->to_room_vnum == d->edit_number) world[counter].dir_option[counter2]->to_room = room_num; } } } } // end 'insert' else /* resolve all vnum doors to rnum doors in the newly edited room */ int opposite; for (counter2 = 0; counter2 < NUM_OF_DIRS; counter2++) { if (world[room_num].dir_option[counter2]) { world[room_num].dir_option[counter2]->to_room = real_room(world[room_num].dir_option[counter2]->to_room_vnum); if (counter2 < MATRIX) { opposite = world[room_num].dir_option[counter2]->to_room; if (opposite != NOWHERE && world[opposite].dir_option[rev_dir[counter2]] && world[opposite].dir_option[rev_dir[counter2]]->to_room == room_num) { world[opposite].dir_option[rev_dir[counter2]]->material = world[room_num].dir_option[counter2]->material; world[opposite].dir_option[rev_dir[counter2]]->barrier = world[room_num].dir_option[counter2]->barrier; world[opposite].dir_option[rev_dir[counter2]]->condition = world[room_num].dir_option[counter2]->condition; } } } } send_to_char("Writing room to disk.\r\n", d->character); write_world_to_disk(d->character->player_specials->saved.zonenum); send_to_char("Saved.\r\n", CH); /* do NOT free strings! just the room structure */ Mem->ClearRoom(d->edit_room); d->edit_room = NULL; REMOVE_BIT(PLR_FLAGS(d->character), PLR_EDITING); STATE(d) = CON_PLAYING; char_to_room(CH, GET_WAS_IN(CH)); GET_WAS_IN(CH) = NOWHERE; send_to_char("Done.\r\n", d->character); break; } case 'n': case 'N': send_to_char("Room not saved, aborting.\r\n", d->character); STATE(d) = CON_PLAYING; REMOVE_BIT(PLR_FLAGS(d->character), PLR_EDITING); /* free everything up, including strings etc */ if (d->edit_room) Mem->DeleteRoom(d->edit_room); d->edit_room = NULL; d->edit_number = 0; char_to_room(CH, GET_WAS_IN(CH)); GET_WAS_IN(CH) = NOWHERE; break; default: send_to_char("Invalid choice!\r\n", d->character); send_to_char("Do you wish to save this room internally?", d->character); break; } break; /* end of REDIT_CONFIRM_SAVESTRING */ case REDIT_MAIN_MENU: switch (LOWER(*arg)) { case 'q': d->edit_mode = REDIT_CONFIRM_SAVESTRING; #if CONFIRM_SAVE send_to_char("Do you wish to save this room internally?\r\n", d->character); #else redit_parse(d, "y"); #endif break; case 'x': d->edit_mode = REDIT_CONFIRM_SAVESTRING; #if CONFIRM_SAVE send_to_char("Do you wish to save this room internally?\r\n", d->character); #else redit_parse(d, "n"); #endif break; case '1': send_to_char("Enter room name:", d->character); d->edit_mode = REDIT_NAME; break; case '2': send_to_char("Enter room description:\r\n", d->character); d->edit_mode = REDIT_DESC; //d->str = (char **) xmalloc(sizeof(char *)); d->str = new (char *); if (!d->str) { mudlog("Malloc failed!", NULL, LOG_SYSLOG, TRUE); exit(1); } *(d->str) = NULL; d->max_str = MAX_MESSAGE_LENGTH; d->mail_to = 0; break; case '3': redit_disp_flag_menu(d); break; case '4': redit_disp_sector_menu(d); break; case '5': d->edit_number2 = NORTH; redit_disp_exit_menu(d); break; case '6': d->edit_number2 = NORTHEAST; redit_disp_exit_menu(d); break; case '7': d->edit_number2 = EAST; redit_disp_exit_menu(d); break; case '8': d->edit_number2 = SOUTHEAST; redit_disp_exit_menu(d); break; case '9': d->edit_number2 = SOUTH; redit_disp_exit_menu(d); break; case 'a': d->edit_number2 = SOUTHWEST; redit_disp_exit_menu(d); break; case 'b': d->edit_number2 = WEST; redit_disp_exit_menu(d); break; case 'c': d->edit_number2 = NORTHWEST; redit_disp_exit_menu(d); break; case 'd': d->edit_number2 = UP; redit_disp_exit_menu(d); break; case 'e': d->edit_number2 = DOWN; redit_disp_exit_menu(d); break; case 'f': d->edit_number2 = MATRIX; redit_disp_exit_menu(d); break; case 'g': /* if extra desc doesn't exist . */ if (!d->edit_room->ex_description) { d->edit_room->ex_description = new extra_descr_data; memset((char *) d->edit_room->ex_description, 0, sizeof(struct extra_descr_data)); } d->misc_data = (void **) &(d->edit_room->ex_description); redit_disp_extradesc_menu(d); break; case 'h': if (ROOM->sector_type == SECT_WATER_SWIM) { send_to_char("Enter current rating (1 to 20): ", CH); d->edit_mode = REDIT_LIBRARY_RATING; } else if (IS_SET(ROOM->room_flags, ROOM_HERMETIC_LIBRARY) || IS_SET(ROOM->room_flags, ROOM_MEDICINE_LODGE) || IS_SET(ROOM->room_flags, ROOM_FALL)) { send_to_char("Enter library (or climb) rating (1 to 20): ", CH); d->edit_mode = REDIT_LIBRARY_RATING; } else if (IS_SET(ROOM->room_flags, ROOM_MATRIX)) { send_to_char("Enter node rating: ", CH); d->edit_mode = REDIT_LIBRARY_RATING; } else { redit_disp_menu(d); return; } break; case 'i': if (IS_SET(ROOM->room_flags, ROOM_MATRIX) && ROOM->sector_type >= SECT_BLUE) redit_disp_func_menu(d); else redit_disp_menu(d); break; case 's': if (access_level(CH, LVL_PRESIDENT)) { send_to_char("Enter room MSP trigger (or \"clear\"): ", CH); d->edit_mode = REDIT_MSP_TRIGGER; } else redit_disp_menu(d); break; default: send_to_char("Invalid choice!", d->character); redit_disp_menu(d); break; } break; case REDIT_NAME: if (d->edit_room->name) delete [] d->edit_room->name; d->edit_room->name = str_dup(arg); redit_disp_menu(d); break; case REDIT_DESC: /* we will NEVER get here */ break; case REDIT_FLAGS: number = atoi(arg); if ((number < 0) || (number > NUM_ROOM_FLAGS)) { send_to_char("That's not a valid choice!\r\n", d->character); redit_disp_flag_menu(d); } else { if (number == 0) /* back out */ redit_disp_menu(d); else { /* toggle bits */ if (IS_SET(d->edit_room->room_flags, 1 << (number - 1))) { REMOVE_BIT(d->edit_room->room_flags, 1 << (number - 1)); if ((1 << (number - 1)) == ROOM_MATRIX && ROOM->spec) { ROOM->func = NULL; ROOM->spec = 0; } } else SET_BIT(d->edit_room->room_flags, 1 << (number - 1)); redit_disp_flag_menu(d); } } break; case REDIT_SECTOR: number = atoi(arg); if (number < 0 || number >= NUM_ROOM_SECTORS) { send_to_char("Invalid choice!", d->character); redit_disp_sector_menu(d); } else { d->edit_room->sector_type = number; if (number < SECT_BLUE && ROOM->spec) { ROOM->func = NULL; ROOM->spec = 0; } redit_disp_menu(d); } break; case REDIT_EXIT_MENU: switch (*arg) { case '0': redit_disp_menu(d); break; case '1': d->edit_mode = REDIT_EXIT_NUMBER; send_to_char("Exit to room number:", d->character); break; case '2': d->edit_mode = REDIT_EXIT_DESCRIPTION; //d->str = (char **) xmalloc(sizeof(char *)); d->str = new (char *); if (!d->str) { mudlog("Malloc failed!", NULL, LOG_SYSLOG, TRUE); exit(1); } *(d->str) = NULL; d->max_str = MAX_MESSAGE_LENGTH; d->mail_to = 0; send_to_char("Enter exit description:\r\n", d->character); break; case '3': d->edit_mode = REDIT_EXIT_KEYWORD; send_to_char("Enter keywords:", d->character); break; case '4': d->edit_mode = REDIT_EXIT_KEY; send_to_char("Enter key number:", d->character); break; case '5': redit_disp_exit_flag_menu(d); d->edit_mode = REDIT_EXIT_DOORFLAGS; break; case '6': d->edit_mode = REDIT_EXIT_KEY_LEV; send_to_char("Enter lock level:", CH); break; case '7': d->edit_mode = REDIT_EXIT_MATERIAL; redit_disp_material_menu(d); break; case '8': d->edit_mode = REDIT_EXIT_BARRIER; redit_disp_barrier_menu(d); break; case '9': d->edit_mode = REDIT_EXIT_HIDDEN; send_to_char("Enter hidden rating of the exit: ", CH); break; case 'a': /* delete exit */ if (d->edit_room->dir_option[d->edit_number2]->keyword) delete [] d->edit_room->dir_option[d->edit_number2]->keyword; if (d->edit_room->dir_option[d->edit_number2]->general_description) delete [] d->edit_room->dir_option[d->edit_number2]->general_description; delete d->edit_room->dir_option[d->edit_number2]; d->edit_room->dir_option[d->edit_number2] = NULL; redit_disp_menu(d); break; default: send_to_char("Invalid choice!\r\n", d->character); break; } break; case REDIT_EXIT_NUMBER: number = atoi(arg); if (number < 0) send_to_char("Invalid choice!\r\nExit to room number:", d->character); else { d->edit_room->dir_option[d->edit_number2]->to_room_vnum = number; redit_disp_exit_menu(d); } break; case REDIT_EXIT_DESCRIPTION: /* we should NEVER get here */ break; case REDIT_EXIT_KEYWORD: if (d->edit_room->dir_option[d->edit_number2]->keyword) delete [] d->edit_room->dir_option[d->edit_number2]->keyword; d->edit_room->dir_option[d->edit_number2]->keyword = str_dup(arg); redit_disp_exit_menu(d); break; case REDIT_EXIT_KEY: number = atoi(arg); d->edit_room->dir_option[d->edit_number2]->key = number; redit_disp_exit_menu(d); break; case REDIT_EXIT_KEY_LEV: number = atoi(arg); DOOR->key_level = MAX(0, MIN(50, number)); redit_disp_exit_menu(d); break; case REDIT_EXIT_HIDDEN: number = atoi(arg); DOOR->hidden = MAX(0, MIN(50, number)); redit_disp_exit_menu(d); break; case REDIT_EXIT_MATERIAL: number = atoi(arg); if (number == 0) redit_disp_exit_menu(d); else if (number > 0 && number <= NUM_MATERIALS) { DOOR->material = number - 1; redit_disp_exit_menu(d); } else redit_disp_material_menu(d); break; case REDIT_EXIT_BARRIER: number = atoi(arg); if (number == 0) redit_disp_exit_menu(d); else if (number > 0 && number <= NUM_BARRIERS) { DOOR->condition = DOOR->barrier = barrier_ratings[number - 1]; redit_disp_exit_menu(d); } else redit_disp_barrier_menu(d); break; case REDIT_LIBRARY_RATING: number = atoi(arg); if (IS_SET(ROOM->room_flags, ROOM_HERMETIC_LIBRARY) || IS_SET(ROOM->room_flags, ROOM_MEDICINE_LODGE) || IS_SET(ROOM->room_flags, ROOM_FALL) || ROOM->sector_type == SECT_WATER_SWIM) { if ((number < 0) || (number > 20)) { send_to_char("Value must be between 1 and 20.\r\n", CH); if (ROOM->sector_type == SECT_WATER_SWIM) send_to_char("Enter current rating: ", CH); else send_to_char("Enter library (or climb) rating: ", CH); } else { ROOM->rating = number; redit_disp_menu(d); } } else if (IS_SET(ROOM->room_flags, ROOM_MATRIX)) { switch (ROOM->sector_type) { case SECT_BLUE: if (number < 1 || number > 6) { send_to_char("Rating must be between 1 and 6.\r\n", CH); return; } break; case SECT_GREEN: if (number < 2 || number > 7) { send_to_char("Rating must be between 2 and 7.\r\n", CH); return; } break; case SECT_ORANGE: if (number < 3 || number > 8) { send_to_char("Rating must be between 3 and 8.\r\n", CH); return; } break; case SECT_RED: if (number < 2 || number > 12) { send_to_char("Rating must be between 2 and 12.\r\n", CH); return; } break; case SECT_BLACK: if (number < 3 || number > 13) { send_to_char("Rating must be between 3 and 13.\r\n", CH); return; } break; default: if (number < 1 || number > 12) { send_to_char("Rating must be between 1 and 6.\r\n", CH); return; } break; } ROOM->rating = number; redit_disp_menu(d); } break; case REDIT_EXIT_DOORFLAGS: number = atoi(arg); if ((number < 0) || (number > 2)) { send_to_char("That's not a valid choice!\r\n", d->character); redit_disp_exit_flag_menu(d); } else { /* doors are a bit idiotic, don't you think? :) */ if (number == 0) d->edit_room->dir_option[d->edit_number2]->exit_info = 0; else if (number == 1) d->edit_room->dir_option[d->edit_number2]->exit_info = EX_ISDOOR; else if (number == 2) d->edit_room->dir_option[d->edit_number2]->exit_info = EX_ISDOOR | EX_PICKPROOF; /* jump out to menu */ redit_disp_exit_menu(d); } break; case REDIT_ROOM_FUNCTION: number = atoi(arg); if (number < 0 || number > NUM_ROOM_FUNCS) redit_disp_func_menu(d); else { ROOM->spec = number; switch (number) { case 1 : ROOM->func = cpu; break; case 2 : ROOM->func = datastore; break; case 3 : ROOM->func = input_output; break; case 4 : ROOM->func = spu; break; case 5 : ROOM->func = system_access; break; case 6 : ROOM->func = slave; break; default: if (ROOM->func == cpu || ROOM->func == datastore || ROOM->func == spu || ROOM->func == input_output || ROOM->func == system_access || ROOM->func == slave) ROOM->func = NULL; break; } redit_disp_menu(d); } break; case REDIT_EXTRADESC_KEY: if (((struct extra_descr_data *) *d->misc_data)->keyword) delete [] (((struct extra_descr_data *) *d->misc_data)->keyword); ((struct extra_descr_data *) * d->misc_data)->keyword = str_dup(arg); redit_disp_extradesc_menu(d); break; case REDIT_EXTRADESC_MENU: number = atoi(arg); switch (number) { case 0: { /* if something got left out, delete the extra desc when backing out to menu */ if (!((struct extra_descr_data *) * d->misc_data)->keyword || !((struct extra_descr_data *) * d->misc_data)->description) { if (((struct extra_descr_data *) * d->misc_data)->keyword) delete [] ((struct extra_descr_data *) * d->misc_data)->keyword; if (((struct extra_descr_data *) * d->misc_data)->description) delete [] ((struct extra_descr_data *) * d->misc_data)->description; delete *d->misc_data; *d->misc_data = NULL; } /* else, we don't need to do anything.. jump to menu */ redit_disp_menu(d); } break; case 1: d->edit_mode = REDIT_EXTRADESC_KEY; send_to_char("Enter keywords, separated by spaces:", d->character); break; case 2: d->edit_mode = REDIT_EXTRADESC_DESCRIPTION; send_to_char("Enter extra description:\r\n", d->character); /* send out to modify.c */ //d->str = (char **) xmalloc(sizeof(char *)); d->str = new (char *); if (!d->str) { mudlog("Malloc failed!", NULL, LOG_SYSLOG, TRUE); exit(1); } *(d->str) = NULL; d->max_str = MAX_MESSAGE_LENGTH; d->mail_to = 0; break; case 3: if (!((struct extra_descr_data *) *d->misc_data)->keyword || !((struct extra_descr_data *) *d->misc_data)->description) { send_to_char("You can't edit the next extra desc without completing this one.\r\n", d->character); redit_disp_extradesc_menu(d); } else { struct extra_descr_data *new_extra; if (((struct extra_descr_data *) * d->misc_data)->next) d->misc_data = (void **) &((struct extra_descr_data *) * d->misc_data)->next; else { /* make new extra, attach at end */ new_extra = new extra_descr_data; memset((char *) new_extra, 0, sizeof(extra_descr_data)); ((struct extra_descr_data *) * d->misc_data)->next = new_extra; d->misc_data = (void **) &((struct extra_descr_data *) * d->misc_data)->next; } redit_disp_extradesc_menu(d); } } break; case REDIT_MSP_TRIGGER: if (!str_cmp(arg, "clear")) { if (ROOM->msp_trigger) delete [] ROOM->msp_trigger; ROOM->msp_trigger = NULL; redit_disp_menu(d); return; } else if (strstr(arg, "MUSIC(") != arg && strstr(arg, "SOUND(") != arg) { send_to_char("Invalid MSP trigger!\r\nEnter room MSP trigger (or \"clear\"): ", CH); return; } if (ROOM->msp_trigger) delete [] ROOM->msp_trigger; ROOM->msp_trigger = str_dup(arg); redit_disp_menu(d); break; default: /* we should never get here */ break; } } // world saving routine #define RM world[realcounter] void write_world_to_disk(int vnum) { int counter, counter2, realcounter; int znum = real_zone(vnum); FILE *fp; struct room_data *room; struct extra_descr_data *ex_desc; sprintf(buf, "%s/%d.wld", WLD_PREFIX, zone_table[znum].number); fp = fopen(buf, "w+"); for (counter = zone_table[znum].number * 100; counter <= zone_table[znum].top; counter++) { realcounter = real_room(counter); if (realcounter >= 0) { fprintf(fp, "#%d\n", counter); fprintf(fp, "%s~\n", RM.name ? RM.name : "An unnamed room"); fprintf(fp, "%s~\n", cleanup(buf2, RM.description ? RM.description : "You see an empty room")); fprintf(fp, "%d %d %d %d\n", RM.spec, RM.room_flags, RM.sector_type, RM.rating); for (counter2 = 0; counter2 < NUM_OF_DIRS; counter2++) { if (RM.dir_option[counter2]) { int temp_door_flag; fprintf(fp, "D%d\n", counter2); fprintf(fp, "%s~\n", RM.dir_option[counter2]->general_description ? cleanup(buf2, RM.dir_option[counter2]->general_description) : ""); fprintf(fp, "%s~\n", RM.dir_option[counter2]->keyword ? RM.dir_option[counter2]->keyword : ""); /* door flags need special handling, unfortunately. argh! */ if (IS_SET(RM.dir_option[counter2]->exit_info, EX_ISDOOR)) { if (IS_SET(RM.dir_option[counter2]->exit_info, EX_PICKPROOF)) temp_door_flag = 2; else temp_door_flag = 1; } else temp_door_flag = 0; fprintf(fp, "%d %d %d %d %d %d %d\n", temp_door_flag, RM.dir_option[counter2]->key, RM.dir_option[counter2]->to_room_vnum, RM.dir_option[counter2]->key_level, RM.dir_option[counter2]->material, RM.dir_option[counter2]->barrier, RM.dir_option[counter2]->hidden); } } if (RM.ex_description) { for (ex_desc = RM.ex_description; ex_desc; ex_desc = ex_desc->next) { fprintf(fp, "E\n"); fprintf(fp, "%s~\n", ex_desc->keyword); fprintf(fp, "%s~\n", cleanup(buf2, ex_desc->description)); } } if (RM.msp_trigger) { fprintf(fp, "M\n"); fprintf(fp, "%s~\n", RM.msp_trigger); } fprintf(fp, "S\n"); } } /* write final line and close */ fprintf(fp, "$~\n"); fclose(fp); write_index_file("wld"); /* do NOT free strings! just the room structure */ } #undef RM