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