AwakeMUD-0.51Beta/area/
AwakeMUD-0.51Beta/doc/
AwakeMUD-0.51Beta/lib/
AwakeMUD-0.51Beta/lib/etc/
AwakeMUD-0.51Beta/lib/fixer_data/
AwakeMUD-0.51Beta/lib/misc/
AwakeMUD-0.51Beta/lib/plrobjs/
AwakeMUD-0.51Beta/lib/plrobjs/A-E/
AwakeMUD-0.51Beta/lib/plrobjs/K-O/
AwakeMUD-0.51Beta/lib/plrobjs/U-Z/
AwakeMUD-0.51Beta/lib/plrspells/A-E/
AwakeMUD-0.51Beta/lib/plrtext/A-E/
AwakeMUD-0.51Beta/lib/world/
AwakeMUD-0.51Beta/lib/world/mob/
AwakeMUD-0.51Beta/lib/world/obj/
AwakeMUD-0.51Beta/lib/world/qst/
AwakeMUD-0.51Beta/lib/world/shp/
AwakeMUD-0.51Beta/lib/world/wld/
AwakeMUD-0.51Beta/lib/world/zon/
/* *******************************************
*                                            *
*                  iedit.cc                  *
*              Part of AwakeOLC,             *
*          a component of AwakeMUD           *
*                                            *
*       (c)2001 Andrew Hynek, and the        *
*             AwakeMUD Consortium            *
*                                            *
******************************************* */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "structs.h"
#include "awake.h"
#include "interpreter.h"
#include "comm.h"
#include "spells.h"
#include "utils.h"
#include "db.h"
#include "dblist.h"
#include "boards.h"
#include "screen.h"
#include "olc.h"
#include "memory.h"
#include "newmagic.h"

#define OBJ     d->edit_obj

extern class memoryClass *Mem;
extern class objList ObjList;

void write_objs_to_disk(int zone);

/* external variables */
extern struct obj_data *obj_proto;
extern int      top_of_objt;
extern struct index_data *obj_index;
extern struct zone_data *zone_table;

// extern funcs
extern char *cleanup(char *dest, const char *src);
extern int real_zone(int vnum);

/* for objects */
extern const char    *item_types[];
extern const char    *wear_bits[];
extern const char    *extra_bits[];
extern const char    *drinks[];
extern const char    *apply_types[];
extern const char    *container_bits[];
extern const char *material_names[];
extern const char *barrier_names[];
extern const char *affected_bits[];
extern const char *patch_names[];
extern const char *cyberware_names[];
extern const char *bioware_names[];
extern const char *program_types[];
extern const char *file_types[];
extern const char *file_ratings[];
extern const char *composition_names[];
extern const char *spirits[];
extern const char *spell_categories[];
extern int material_ratings[];
extern int barrier_ratings[];
extern struct board_info_type board_info[NUM_OF_BOARDS];
extern spell_a grimoire[];

/* for spell list */
extern const char    *spells[];

#define NUM_WEAR_FLAGS          17
#define NUM_EXTRA_FLAGS         13
#define NUM_APPLY_FLAGS         25
#define NUM_SPELLS              49
#define NUM_WEAPON_TYPES        27
#define NUM_SKILL_TYPES         19
#define NUM_DRINK_TYPES         18
#define NUM_PATCHES             4
#define NUM_CYBERWARE_TYPES     32
#define NUM_BIOWARE_TYPES        11
#define NUM_PROGRAMS         15
#define NUM_FILES          7
#define NUM_FILE_RATINGS   8
#define NUM_SPIRITS       17
void iedit_disp_container_flags_menu(struct descriptor_data * d);
void iedit_disp_extradesc_menu(struct descriptor_data * d);
void iedit_disp_weapon_menu(struct descriptor_data * d);
void iedit_disp_val1_menu(struct descriptor_data * d);
void iedit_disp_val2_menu(struct descriptor_data * d);
void iedit_disp_val3_menu(struct descriptor_data * d);
void iedit_disp_val4_menu(struct descriptor_data * d);
void iedit_disp_val5_menu(struct descriptor_data * d);
void iedit_disp_val6_menu(struct descriptor_data * d);
void iedit_disp_val7_menu(struct descriptor_data * d);
void iedit_disp_val8_menu(struct descriptor_data * d);
void iedit_disp_val9_menu(struct descriptor_data * d);
void iedit_disp_val10_menu(struct descriptor_data * d);


void iedit_disp_type_menu(struct descriptor_data * d);
void iedit_disp_extra_menu(struct descriptor_data * d);
void iedit_disp_wear_menu(struct descriptor_data * d);
void iedit_disp_menu(struct descriptor_data * d);
void iedit_disp_drinktype_menu(struct descriptor_data *d);

void iedit_disp_patch_menu(struct descriptor_data *d);
void iedit_parse(struct descriptor_data * d, char *arg);
void iedit_disp_spells_menu(struct descriptor_data * d);
void iedit_disp_cybertype_menu(struct descriptor_data * d);
void iedit_program_types_menu(struct descriptor_data *d);
void iedit_disp_biotype_menu(struct descriptor_data * d);


/**************************************************************************
 Menu functions
 **************************************************************************/
/* For container flags */
void iedit_disp_container_flags_menu(struct descriptor_data * d)
{
  sprintbit(GET_OBJ_VAL(d->edit_obj, 1), container_bits, buf1);
  send_to_char(CH, "1) Closeable\r\n"
                   "2) Pickproof\r\n"
                   "3) Closed\r\n"
                   "4) Locked\r\n"
                   "Container flags: %s%s%s\r\n"
                   "Enter flag, 0 to quit:", CCCYN(CH, C_CMP), buf1,
                   CCNRM(CH, C_CMP));
}

/* For extra descriptions */
void iedit_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 desc menu\r\n"
                   "0) Quit\r\n"
                   "1) Keyword: %s%s%s\r\n"
                   "2) Description:\r\n%s\r\n"
                   "3) %s%s%s\r\n",
    CCCYN(CH, C_CMP), (extra_desc->keyword ?  extra_desc->keyword : "(none)"),
    CCNRM(CH, C_CMP), (extra_desc->description ? extra_desc->description : "(none)"),
    CCCYN(CH, C_CMP), (!extra_desc->next ? "(not set)" : "Set (not viewed)."),
    CCNRM(CH, C_CMP));
  d->edit_mode = IEDIT_EXTRADESC_MENU;
}

/* Ask for *which* apply to edit */
void iedit_disp_prompt_apply_menu(struct descriptor_data * d)
{
  int             counter;

  CLS(CH);
  for (counter = 0; counter < MAX_OBJ_AFFECT; counter++) {
    if (d->edit_obj->affected[counter].modifier) {
      sprinttype(d->edit_obj->affected[counter].location, apply_types, buf2);
      send_to_char(CH, " %d) %+d to %s%s%s\r\n", counter + 1,
              d->edit_obj->affected[counter].modifier, CCCYN(CH, C_CMP), buf2,
              CCNRM(CH, C_CMP));
    } else
      send_to_char(CH, " %d) None.\r\n", counter + 1);
  }
  send_to_char("Enter affection to modify (0 to quit):", d->character);
  d->edit_mode = IEDIT_PROMPT_APPLY;
}

/* The actual apply to set */
void iedit_disp_apply_menu(struct descriptor_data * d)
{
  int             counter;

  for (counter = 0; counter < NUM_APPLY_FLAGS; counter += 2)
    send_to_char(CH, "%2d) %-18s    %2d) %-18s\r\n",
            counter, apply_types[counter],
            counter + 1, counter + 1 < NUM_APPLY_FLAGS ?
            apply_types[counter + 1] : "");

  send_to_char("Enter apply type (0 is no apply):", d->character);
  d->edit_mode = IEDIT_APPLY;
}

/* skill needed in weapon */
void iedit_disp_skill_menu(struct descriptor_data *d)
{
  CLS(CH);
  send_to_char( " 1) Edged Weapons\r\n"
                " 2) Pole Arms\r\n"
                " 3) Whips and flails\r\n"
                " 4) Clubs\r\n"
                " 5) Pistols\r\n"
                " 6) Rifles\r\n"
                " 7) Shotguns\r\n"
                " 8) Assault Rifles\r\n"
                " 9) Submachine Guns\r\n"
                "10) Grenade Launchers\r\n"
                "11) Tasers\r\n"
                "12) Machine Guns\r\n"
                "13) Missile Launchers\r\n"
                "14) Assault Cannons\r\n"
                "15) Artillery\r\n"
                "16) Bows\r\n"
                "17) Crossbows\r\n"
                "18) Non-aerodynamic throwing weapons\r\n"
                "19) Aerodynamic throwing weapons\r\n"
              "Enter skill needed for weapon:\r\n", CH);
}

/* weapon type */
void iedit_disp_weapon_menu(struct descriptor_data * d)
{
  CLS(CH);
  send_to_char(" 1) sting              2) whip\r\n"
               " 3) slash              4) bite\r\n"
               " 5) bludgeon           6) crush\r\n"
               " 7) pound              8) claw\r\n"
               " 9) maul              10) thrash\r\n"
               "11) pierce            12) punch\r\n"
               "13) stab              14) taser\r\n"
               "15) shuriken          16) throwing knife\r\n"
               "17) arrow/bolt        18) hand grenade\r\n"
               "19) grenade launcher  20) rocket\r\n"
               "21) pistol            22) blast\r\n"
               "23) rifle             24) shotgun\r\n"
               "25) machine gun       26) cannon\r\n"
               "Enter weapon type:\r\n", CH);
}

/* spell type */
void iedit_disp_spells_menu(struct descriptor_data * d)
{
  int             counter;

  CLS(CH);
  for (counter = 1; counter <= NUM_SPELLS; counter += 3)
    send_to_char(CH, "%2d) %-18s %2d) %-18s %2d) %-18s\r\n",
            counter, spells[counter],
            counter + 1, counter + 1 <= NUM_SPELLS ? spells[counter + 1] : "",
          counter + 2, counter + 2 <= NUM_SPELLS ? spells[counter + 2] : "");

  send_to_char("Enter spell:\r\n", CH);
}

/* object value 1 */
void iedit_disp_val1_menu(struct descriptor_data * d)
{
  d->edit_mode = IEDIT_VALUE_1;
  switch (GET_OBJ_TYPE(d->edit_obj)) {
  case ITEM_LIGHT:
    /* values 0 and 1 are unused.. jump to 2 */
    iedit_disp_val3_menu(d);
    break;
  case ITEM_SCROLL:
  case ITEM_WAND:
  case ITEM_STAFF:
  case ITEM_POTION:
    send_to_char("Spell force:", d->character);
    break;
  case ITEM_WEAPON:
  case ITEM_FIREWEAPON:
    send_to_char("Power (0 for melee weapon or bow):", d->character);
    break;
  case ITEM_MISSILE:
    send_to_char("\r\n  0) Arrow     1) Bolt\r\nMissile type: ", CH);
    break;
  case ITEM_ARMOR:
    send_to_char("Ballistic:", d->character);
    break;
  case ITEM_QUIVER:
    send_to_char("Max projectiles to contain: ", CH);
    break;
  case ITEM_CONTAINER:
    send_to_char("Max weight to contain:", d->character);
    break;
  case ITEM_DRINKCON:
  case ITEM_FOUNTAIN:
    send_to_char("Max drink units:", d->character);
    break;
  case ITEM_FOOD:
    send_to_char("Hours to fill stomach:", d->character);
    break;
  case ITEM_MONEY:
    send_to_char("Number of nuyen: ", d->character);
    break;
  case ITEM_CYBERWARE:
  case ITEM_BIOWARE:
    send_to_char("Rating:", CH);
    break;
  case ITEM_CYBERDECK:
    send_to_char("MPCP Rating: ", CH);
    break;
  case ITEM_PROGRAM:
    iedit_program_types_menu(d);
    break;
  case ITEM_GUN_CLIP:
    send_to_char("Number of bullets clip contains (must match max load of weapon):", CH);
    break;
  case ITEM_DOCWAGON:
    send_to_char("  1) Basic contract\r\n  2) Gold contract\r\n  3) Platinum contract\r\nDocWagon type: ", CH);
    break;
  case ITEM_WORKING_GEAR:
    CLS(CH);
    send_to_char("  1) Medical\r\n"
                 "  2) Electronic\r\n"
                 "  3) Cyberdeck\r\n"
                 "Enter type of kit: ", CH);
    break;
  case ITEM_PATCH:
    iedit_disp_patch_menu(d);
    break;
  case ITEM_SPELL_FORMULA:
    iedit_disp_val3_menu(d);
    break;
  case ITEM_DECK_ACCESSORY:
    send_to_char("  0) Data file\r\n  1) Upgrade\r\n"
                 "Accessory type: ", CH);
    break;
  case ITEM_GUN_ACCESSORY:
    send_to_char("  0) Top\r\n  1) Barrel\r\n 2) Under\r\nLocation to mount accessory: ", CH);
    break;
  case ITEM_FOCUS:
    send_to_char("  0) Specific spell\r\n  1) Spell category\r\n  2) Spirit\r\n  3) Power\r\n"
                 "  4) Spell lock\r\n  5) Weapon\r\nFocus type: ", CH);
    break;
  case ITEM_CLIMBING:
    send_to_char("Enter rating (1-3): ", CH);
    break;
  case ITEM_RADIO:
    iedit_disp_val2_menu(d);
    break;
  default:
    iedit_disp_menu(d);
  }
}

/* object value 2 */
void iedit_disp_val2_menu(struct descriptor_data * d)
{
  d->edit_mode = IEDIT_VALUE_2;
  switch (GET_OBJ_TYPE(d->edit_obj)) {
  case ITEM_WAND:
  case ITEM_STAFF:
    send_to_char("Max number of charges:", d->character);
    break;
  case ITEM_WEAPON:
  case ITEM_FIREWEAPON:
    send_to_char("Base Damage (1 - Light, 2 - Moderate, 3 - Serious, 4 - Deadly):", d->character);
    break;
  case ITEM_DRINKCON:
  case ITEM_FOUNTAIN:
    send_to_char("Drink units left:", CH);
    break;
  case ITEM_ARMOR:
    send_to_char("Impact:", CH);
    break;
  case ITEM_FOOD:
    /* values 2 and 3 are unused, jump to 4. how odd */
    iedit_disp_val4_menu(d);
    break;
  case ITEM_CONTAINER:
    /* these are flags, needs a bit of special handling */
    iedit_disp_container_flags_menu(d);
    break;
  case ITEM_QUIVER:
    send_to_char("  0) Arrows\r\n  1) Bolts\r\n  2) Shurikens\r\n  3) Throwing knives\r\n"
                 "Quiver type: ", CH);
    break;
  case ITEM_CYBERWARE:
    send_to_char("Essence cost (x 100): ", CH);
    break;
  case ITEM_BIOWARE:
    send_to_char("Body index cost (x 100): ", CH);
    break;
  case ITEM_CYBERDECK:
    send_to_char("Hardening: ", CH);
    break;
  case ITEM_PROGRAM:
    send_to_char("Program Rating: ", CH);
    break;
  case ITEM_PATCH:
    send_to_char("Rating: ", CH);
    break;
  case ITEM_DECK_ACCESSORY:
    switch (GET_OBJ_VAL(OBJ, 0)) {
      case TYPE_FILE:
        send_to_char("File size: ", CH);
        break;
      case TYPE_UPGRADE:
        send_to_char("  0) MPCP (replacement)\r\n  1) Active memory\r\n"
                     "  2) Storage memory\r\n  3) Load speed\r\n  4) IO speed\r\n"
                     "  5) Reaction increase\r\nUpgrade type: ", CH);
        break;
    }
    break;
  case ITEM_GUN_ACCESSORY:
    send_to_char("  1) Smartlink\r\n  2) Scope\r\n  3) Gas vent\r\n  4) Shock pad\r\nAccessory type: ", CH);
    break;
  case  ITEM_FOCUS:
    if (GET_OBJ_VAL(OBJ, 0) != FOCI_LOCK)
      send_to_char("Focus rating: ", CH);
    else iedit_disp_menu(d);
    break;
  case ITEM_GUN_CLIP:
    send_to_char("  1) Pistol               2) Blast\r\n"
                 "  3) Rifle                4) Shotgun\r\n"
                 "  5) Machine gun          6) Cannon\r\n"
                 "  7) Grenade launcher     8) Rocket\r\nClip type: ", CH);
    break;
  case ITEM_RADIO:
    send_to_char("Enter radio's range (0-5): ", CH);
    break;
  case ITEM_MONEY:
    send_to_char("Type (1 - cash, 2 - credstick): ", d->character);
    break;
  default:
    iedit_disp_menu(d);
  }
}

/* object value 3 */
void iedit_disp_val3_menu(struct descriptor_data * d)
{
  int i;

  d->edit_mode = IEDIT_VALUE_3;
  switch (GET_OBJ_TYPE(d->edit_obj)) {
  case ITEM_LIGHT:
    send_to_char("Number of hours (0 = burnt, -1 is infinite):", d->character);
    break;
  case ITEM_WAND:
  case ITEM_STAFF:
    send_to_char("Number of charges remaining:", d->character);
    break;
  case ITEM_WEAPON:
  case ITEM_FIREWEAPON:
    send_to_char("Strength bonus for melee (0 for non-melee weapons):", CH);
    break;
  case ITEM_CONTAINER:
    send_to_char("Vnum of key to open container (-1 for no key):", d->character);
    break;
  case ITEM_DRINKCON:
  case ITEM_FOUNTAIN:
    iedit_disp_drinktype_menu(d);
    break;
  case ITEM_CYBERWARE:
    iedit_disp_cybertype_menu(d);
    break;
  case ITEM_BIOWARE:
    iedit_disp_biotype_menu(d);
    break;
  case ITEM_CYBERDECK:
    send_to_char("Active: ", CH);
    break;
  case ITEM_PROGRAM:
    send_to_char("Program size: ", CH);
    break;
  case ITEM_SPELL_FORMULA:
    send_to_char("Force: ", CH);
    break;
  case ITEM_DECK_ACCESSORY:
    switch (GET_OBJ_VAL(OBJ, 0)) {
      case TYPE_FILE:
        for (i = 1; i <= NUM_FILES; i++) {
          sprintf(buf, " %2d) %s\r\n", i, file_types[i]);
          send_to_char(buf, CH);
        }
        send_to_char("Enter file type: ", CH);
        break;
      case TYPE_UPGRADE:
        switch (GET_OBJ_VAL(OBJ, 1)) {
          case 0:
            send_to_char("MPCP Rating: ", CH);
            break;
          case 1:
            send_to_char("Active memory increase: ", CH);
            break;
          case 2:
            send_to_char("Storage memory increase: ", CH);
            break;
          case 3:
            send_to_char("Load speed increase: ", CH);
            break;
          case 4:
            send_to_char("I/O speed increase: ", CH);
            break;
          case 5:
            send_to_char("Reaction increase level: ", CH);
            break;
        }
        break;
    }
    break;
  case ITEM_GUN_ACCESSORY:
    if (GET_OBJ_VAL(OBJ, 1) == 3)
      send_to_char("Recoil modifier: ", CH);
    else iedit_disp_menu(d);
    break;
  case ITEM_FOCUS:
    if (GET_OBJ_VAL(OBJ, 0) == FOCI_SPIRIT) {
      CLS(CH);
      for (i = 1; *spirits[i] != '\n'; i++)
        send_to_char(CH, "%2d) %20s", i, spirits[i]);
      send_to_char("Enter spirit type: ", CH);
    } else if (GET_OBJ_VAL(OBJ, 0) == FOCI_SPELL)
      iedit_disp_spells_menu(d);
    else if (GET_OBJ_VAL(OBJ, 0) == FOCI_SPELL_CAT) {
      CLS(CH);
      for (i = 0; *spell_categories[i] != '\n'; i++)
        send_to_char(CH, "%2d %s\r\n", i + 1, spell_categories[i]);
      send_to_char("Enter spell category: ", CH);
    } else iedit_disp_menu(d);
    break;
  case ITEM_RADIO:
    send_to_char("Enter encryption/decryption rating (1-6): ", CH);
    break;
  case ITEM_MONEY:
    if (GET_OBJ_VAL(OBJ, 1))
      send_to_char("  1) 6-digit code\r\n  2) thumbprint\r\n  3) retinal scan\r\n"
                   "Enter credstick security: ", d->character);
    else iedit_disp_menu(d);
    break;
  default:
    iedit_disp_menu(d);
  }
}

/* object value 4 */
void iedit_disp_val4_menu(struct descriptor_data * d)
{
  int i;

  d->edit_mode = IEDIT_VALUE_4;
  switch (GET_OBJ_TYPE(d->edit_obj)) {
  case ITEM_SCROLL:
  case ITEM_POTION:
  case ITEM_WAND:
  case ITEM_STAFF:
    iedit_disp_spells_menu(d);
    break;
  case ITEM_WEAPON:
  case ITEM_FIREWEAPON:
    iedit_disp_weapon_menu(d);
    break;
  case ITEM_CONTAINER:
    send_to_char("Lock level on container:", d->character);
    break;
  case ITEM_DRINKCON:
  case ITEM_FOUNTAIN:
  case ITEM_FOOD:
    send_to_char("Poison Rating (0 = not poison): ", d->character);
    break;
  case ITEM_CYBERWARE:
    iedit_disp_val5_menu(d);
    break;
  case ITEM_CYBERDECK:
    send_to_char("Storage: ", CH);
    break;
  case ITEM_PROGRAM:
    if (GET_OBJ_VAL(OBJ, 2) != PROG_ATTACK) {
      GET_OBJ_VAL(OBJ, 3) = 300;
      iedit_disp_menu(d);
      return;
    }
    send_to_char("Program attack type:\r\n\r\n"
                 "   1) Hit                2) Sting\r\n"
                 "   3) Whip               4) Slash\r\n"
                 "   5) Bite               6) Bludgeon\r\n"
                 "   7) Crush              8) Pound\r\n"
                 "   9) Claw              10) Maul\r\n"
                 "  11) Thrash            12) Pierce\r\n"
                 "  13) Punch             14) Stab\r\n"
                 "  15) Taser             16) Shuriken\r\n"
                 "  17) Throwing knife    18) Arrow/bolt\r\n"
                 "  19) Hand grenade      20) Grenade launcher\r\n"
                 "  21) Rocket            22) Pistol\r\n"
                 "  23) Blast             24) Rifle\r\n"
                 "  25) Shotgun           26) Machine gun\r\n"
                 "  27) Cannon\r\n"
                 "Program attack type: ", CH);
    break;
  case ITEM_SPELL_FORMULA:
    iedit_disp_spells_menu(d);
    d->edit_mode = IEDIT_VALUE_7;
    break;
  case ITEM_DECK_ACCESSORY:
    switch (GET_OBJ_VAL(OBJ, 0)) {
      case TYPE_FILE:
        for (i = 0; i < NUM_FILE_RATINGS; i++) {
          sprintf(buf, " %2d) %s\r\n", i + 1, file_ratings[i]);
          send_to_char(buf, CH);
        }
        send_to_char("Enter file rating: ", CH);
        break;
      case TYPE_UPGRADE:
        if (GET_OBJ_VAL(OBJ, 1) == 5)
          send_to_char("MPCP to enhance: ", CH);
        else iedit_disp_menu(d);
        break;
    }
    break;
  default:
    iedit_disp_menu(d);
  }
}

/* object value 5 */
void iedit_disp_val5_menu(struct descriptor_data * d)
{
  d->edit_mode = IEDIT_VALUE_5;
  switch (GET_OBJ_TYPE(d->edit_obj)) {
    case ITEM_WEAPON:
    case ITEM_FIREWEAPON:
      iedit_disp_skill_menu(d);
      break;
    case ITEM_CYBERDECK:
      send_to_char("Load: ", CH);
      break;
    case ITEM_CYBERWARE:
      if (GET_OBJ_VAL(OBJ, 2) == 2 || GET_OBJ_VAL(OBJ, 2) == 3)
        send_to_char("Enter radio's range (0-5): ", CH);
      else iedit_disp_menu(d);
      break;
    default:
      iedit_disp_menu(d);
  }
}

/* object value 6 */
void iedit_disp_val6_menu(struct descriptor_data * d)
{
  d->edit_mode = IEDIT_VALUE_6;
  switch (GET_OBJ_TYPE(d->edit_obj)) {
    case ITEM_WEAPON:
      send_to_char("Max Ammo (-1 if doesn't use ammo): ", CH);
      break;
    case ITEM_FIREWEAPON:
      send_to_char("  0) Bow\r\n  1) Crossbow\r\nType: ", CH);
      break;
    case ITEM_CYBERWARE:
      send_to_char("Enter encryption/decryption rating (1-6): ", CH);
      break;
    default:
      iedit_disp_menu(d);
  }
}

/* object value 7 */
void iedit_disp_val7_menu(struct descriptor_data * d)
{
  d->edit_mode = IEDIT_VALUE_7;
  switch (GET_OBJ_TYPE(d->edit_obj)) {
  case ITEM_WEAPON:
    send_to_char("Current Ammo: ", CH);
    break;
  case ITEM_FIREWEAPON:
    send_to_char("Enter strength minimum: ", CH);
    break;
  case ITEM_SPELL_FORMULA:
    iedit_disp_spells_menu(d);
    break;
  default:
    iedit_disp_menu(d);
  }
}

/* object value 8 */
void iedit_disp_val8_menu(struct descriptor_data * d)
{
  d->edit_mode = IEDIT_VALUE_8;
  switch (GET_OBJ_TYPE(d->edit_obj)) {
    case ITEM_SPELL_FORMULA:
      send_to_char("0 for mage spell, 1 for shaman spell: ", CH);
      break;
    case ITEM_WEAPON:
      if (access_level(CH, LVL_PRESIDENT)) {
        if (GET_OBJ_VAL(OBJ, 7) > -1)
          send_to_char("Enter vnum of object to attach on top: ", CH);
        else iedit_disp_val9_menu(d);
      } else iedit_disp_menu(d);
      break;
    default:
      iedit_disp_menu(d);
  }
}

/* object value 9 */
void iedit_disp_val9_menu(struct descriptor_data * d)
{
  d->edit_mode = IEDIT_VALUE_9;
  switch (GET_OBJ_TYPE(d->edit_obj)) {
    case ITEM_WEAPON:
      if (access_level(CH, LVL_PRESIDENT)) {
        if (GET_OBJ_VAL(OBJ, 8) > -1)
          send_to_char("Enter vnum of object to attach on barrel: ", CH);
        else iedit_disp_val10_menu(d);
      } else iedit_disp_menu(d);
      break;
    default:
      iedit_disp_menu(d);
  }
}

/* object value 10 */
void iedit_disp_val10_menu(struct descriptor_data * d)
{
  d->edit_mode = IEDIT_VALUE_10;
  switch (GET_OBJ_TYPE(d->edit_obj)) {
    case ITEM_WEAPON:
      if (access_level(CH, LVL_PRESIDENT) && GET_OBJ_VAL(OBJ, 9) > -1)
        send_to_char("Enter vnum of object to attach under: ", CH);
      else iedit_disp_menu(d);
      break;
    default:
      iedit_disp_menu(d);
  }
}

/* object type */
void iedit_disp_type_menu(struct descriptor_data * d)
{
  int counter;

  CLS(CH);
  for (counter = 1; counter <= NUM_ITEM_TYPES; counter += 2) {
    send_to_char(CH, "%2d) %-20s %2d) %-20s\r\n",
            counter, item_types[counter],
            counter + 1, counter + 1 <= NUM_ITEM_TYPES ?
            item_types[counter + 1] : "");
  }
  send_to_char("Enter object type (0 to quit):", d->character);
}

void iedit_disp_drinktype_menu(struct descriptor_data *d)
{
  int counter;

  CLS(CH);
  for (counter = 0; counter < NUM_DRINK_TYPES; ++counter)
    send_to_char(CH, "%2d) %s\r\n", counter + 1, drinks[counter]);
  send_to_char("Enter drink type: ", CH);
}

void iedit_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);
}

void iedit_disp_patch_menu(struct descriptor_data *d)
{
  CLS(CH);

  for (register int counter = 0; counter < NUM_PATCHES; ++counter)
    send_to_char(CH, "%2d) %s\r\n", counter + 1, patch_names[counter]);
  send_to_char("Enter patch type, 0 to return: ", CH);
}

void iedit_disp_spell_type(struct descriptor_data *d)
{
  CLS(CH);
  for (register int counter = 0; counter <= NUM_SPELLS; counter += 2) {
    send_to_char(CH, "%2d) %-20s %2d) %-20s\r\n",
            counter + 1, spells[counter],
            counter + 2, counter + 1 <= NUM_SPELLS ?
            spells[counter + 1] : "");
  }
  send_to_char("Enter spell, 0 to return: ", CH);
}

void iedit_disp_cybertype_menu(struct descriptor_data *d)
{
  CLS(CH);
  for (register int counter = 0; counter <= NUM_CYBERWARE_TYPES; counter += 2)
  {
    send_to_char(CH, "%2d) %-20s %2d) %-20s\r\n",
            counter + 1, cyberware_names[counter],
            counter + 2, counter + 1 < NUM_CYBERWARE_TYPES ?
            cyberware_names[counter + 1] : "");
  }
  send_to_char("Enter cyberware type, 0 to return: ", CH);
}

void iedit_disp_biotype_menu(struct descriptor_data *d)
{
  CLS(CH);
  for (int counter = 0; counter <= NUM_BIOWARE_TYPES; counter += 2) {
    send_to_char(CH, "%2d) %-20s %2d) %-20s\r\n",
            counter + 1, bioware_names[counter],
            counter + 2, counter + 1 < NUM_BIOWARE_TYPES ?
            bioware_names[counter + 1] : "");
  }
  send_to_char("Enter bioware type, 0 to return: ", CH);
}

void iedit_program_types_menu(struct descriptor_data *d)
{
  int counter;

  CLS(CH);
  for (counter = 1; counter < NUM_PROGRAMS; counter += 3) {
    send_to_char(CH, "  %2d) %-15s %2d) %-15s %2d) %-15s\r\n",
            counter, program_types[counter],
            counter + 1, counter + 1 < NUM_PROGRAMS ?
            program_types[counter + 1] : "", counter + 2, counter + 2 < NUM_PROGRAMS ?
            program_types[counter + 2] : "");
  }
  send_to_char("Program type: ", d->character);
}

void iedit_disp_rating_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);
}

/* object extra flags */
void iedit_disp_extra_menu(struct descriptor_data * d)
{
  int             counter;

  CLS(CH);
  for (counter = 0; counter < NUM_EXTRA_FLAGS; counter += 2)
    send_to_char(CH, "%2d) %-20s %2d) %-20s\r\n",
            counter + 1, extra_bits[counter],
            counter + 2, counter + 1 < NUM_EXTRA_FLAGS ?
            extra_bits[counter + 1] : "");

  sprintbit(GET_OBJ_EXTRA(d->edit_obj), extra_bits, buf1);
  send_to_char(CH, "Object flags: %s%s%s\r\n"
                   "Enter object extra flag, 0 to quit:",
               CCCYN(CH, C_CMP), buf1, CCNRM(CH, C_CMP));
}

void iedit_disp_aff_menu(struct descriptor_data *d)
{
  CLS(CH);
  for (register int counter = 0; counter < NUM_AFF_FLAGS; counter += 2)
    send_to_char(CH, "%2d) %-20s %2d) %-20s\r\n", counter + 1,
            affected_bits[counter], counter + 2, counter + 1 < NUM_AFF_FLAGS ?
            affected_bits[counter + 1] : "");

  sprintbit(OBJ->obj_flags.bitvector, affected_bits, buf1);
  send_to_char(CH, "Object flags: %s%s%s\r\n"
                   "Enter affected flags, 0 to quit:", CCCYN(CH, C_CMP),
                   buf1, CCNRM(CH, C_CMP));
}

/* object wear flags */
void iedit_disp_wear_menu(struct descriptor_data * d)
{
  int             counter;

  CLS(CH);
  for (counter = 0; counter < NUM_WEAR_FLAGS; counter += 2) {
    send_to_char(CH, "%2d) %-20s %2d) %-20s\r\n",
            counter + 1, wear_bits[counter],
            counter + 2, counter + 1 < NUM_WEAR_FLAGS ?
            wear_bits[counter + 1] : "");
  }
  sprintbit(GET_OBJ_WEAR(d->edit_obj), wear_bits, buf1);
  send_to_char(CH, "Wear flags: %s%s%s\r\n"
                   "Enter wear flag, 0 to quit:", CCCYN(CH, C_CMP),
               buf1, CCNRM(CH, C_CMP));
}

/* display main menu */
void iedit_disp_menu(struct descriptor_data * d)
{
  CLS(CH);
  send_to_char(CH, "Item number: %s%d%s\r\n", CCCYN(CH, C_CMP), d->edit_number,
               CCNRM(CH, C_CMP));
  send_to_char(CH, "1) Item namelist: %s%s%s\r\n", CCCYN(CH, C_CMP), d->edit_obj->name,
               CCNRM(CH, C_CMP));
  send_to_char(CH, "2) Item shortdesc: %s%s%s\r\n", CCCYN(CH, C_CMP), d->edit_obj->short_description,
               CCNRM(CH, C_CMP));
  send_to_char(CH, "3) Item descript: %s%s%s\r\n", CCCYN(CH, C_CMP), d->edit_obj->description,
               CCNRM(CH, C_CMP));
  send_to_char(CH, "4) Item longdesc: \r\n%s\r\n",
          d->edit_obj->long_description ? d->edit_obj->long_description :
          "(not set)");
  sprinttype(GET_OBJ_TYPE(d->edit_obj), item_types, buf1);
  send_to_char(CH, "5) Item type: %s%s%s\r\n", CCCYN(CH, C_CMP), buf1,
               CCNRM(CH, C_CMP));
  sprintbit(GET_OBJ_EXTRA(d->edit_obj), extra_bits, buf1);
  send_to_char(CH, "6) Item extra flags: %s%s%s\r\n", CCCYN(CH, C_CMP), buf1,
               CCNRM(CH, C_CMP));
  sprintbit(OBJ->obj_flags.bitvector, affected_bits, buf1);
  send_to_char(CH, "7) Item affected bits: %s%s%s\r\n", CCCYN(CH, C_CMP), buf1,
               CCNRM(CH, C_CMP));
  sprintbit(GET_OBJ_WEAR(d->edit_obj), wear_bits, buf1);
  send_to_char(CH, "8) Item wear flags: %s%s%s\r\n", CCCYN(CH, C_CMP), buf1,
               CCNRM(CH, C_CMP));
  send_to_char(CH, "9) Item weight: %s%d%s\r\n", CCCYN(CH, C_CMP),
               GET_OBJ_WEIGHT(d->edit_obj), CCNRM(CH, C_CMP));
  send_to_char(CH, "a) Item cost: %s%d%s\r\n", CCCYN(CH, C_CMP),
               GET_OBJ_COST(d->edit_obj), CCNRM(CH, C_CMP));
  if (GET_OBJ_TYPE(OBJ) == ITEM_CYBERDECK)
    send_to_char(CH, "b) I/O Speed: %s%d%s\r\n", CCCYN(CH, C_CMP), GET_OBJ_RENT(d->edit_obj), CCNRM(CH, C_CMP));
  else send_to_char(CH, "b) Item composition: %s%s%s\r\n", CCCYN(CH, C_CMP), (GET_OBJ_RENT(OBJ) >= 0 &&
      GET_OBJ_RENT(OBJ) <= ITEM_SILVER ? composition_names[GET_OBJ_RENT(OBJ)] : "UNDEFINED"), CCNRM(CH, C_CMP));
  send_to_char(CH, "c) Item timer: %s%d%s\r\n", CCCYN(CH, C_CMP),
               GET_OBJ_TIMER(d->edit_obj), CCNRM(CH, C_CMP));
  send_to_char(CH, "d) Item Material: %s%s%s\r\n", CCCYN(CH, C_CMP),
               material_names[GET_OBJ_MATERIAL(d->edit_obj)], CCNRM(CH, C_CMP));
  send_to_char(CH, "e) Item Barrier Rating: %s%d%s\r\n", CCCYN(CH, C_CMP),
               GET_OBJ_BARRIER(d->edit_obj), CCNRM(CH, C_CMP));
  send_to_char(CH, "f) Item values: ^c%d %d %d %d %d %d %d %d %d %d^n\r\n",
          GET_OBJ_VAL(d->edit_obj, 0), GET_OBJ_VAL(d->edit_obj, 1),
          GET_OBJ_VAL(d->edit_obj, 2), GET_OBJ_VAL(d->edit_obj, 3),
          GET_OBJ_VAL(d->edit_obj, 4), GET_OBJ_VAL(d->edit_obj, 5),
          GET_OBJ_VAL(d->edit_obj, 6), GET_OBJ_VAL(d->edit_obj, 7),
          GET_OBJ_VAL(d->edit_obj, 8), GET_OBJ_VAL(d->edit_obj, 9));
  send_to_char("g) Item applies:\r\n"
               "h) Item extra descriptions:\r\n"
               "q) Quit and save\r\n"
               "x) Exit and abort\r\n"
               "Enter your choice:\r\n", CH);
  d->edit_mode = IEDIT_MAIN_MENU;
}

/***************************************************************************
 main loop (of sorts).. basically interpreter throws all input to here
 ***************************************************************************/


void iedit_parse(struct descriptor_data * d, char *arg)
{
  int             number, j;
  int             obj_number;   /* the RNUM */
  bool modified = FALSE;
  switch (d->edit_mode) {

  case IEDIT_CONFIRM_EDIT:
    /* if player hits 'Y' then edit obj */
    switch (*arg) {
    case 'y':
    case 'Y':
      iedit_disp_menu(d);
      break;
    case 'n':
    case 'N':
      STATE(d) = CON_PLAYING;
      /* free up the editing object */
      if (d->edit_obj)
        Mem->DeleteObject(d->edit_obj);
      d->edit_obj = NULL;
      d->edit_number = 0;
      REMOVE_BIT(PLR_FLAGS(d->character), PLR_EDITING);
      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 IEDIT_CONFIRM_EDIT */

  case IEDIT_CONFIRM_SAVESTRING:
    switch (*arg) {
    case 'y':
    case 'Y':
      {
        /* write to internal tables */
        obj_number = real_object(d->edit_number);
        if (obj_number > 0) {
          /* we need to run through each and every object currently in the
           * game to see which ones are pointing to this prototype */
          struct obj_data *i;
          struct extra_descr_data *This, *next_one;
          struct use_descr_data *This2, *next_one2;
          struct obj_data *temp;

          /* if object is pointing to this prototype, then we need to replace
           * with the new one */
          // this function updates pointers to the active list of objects
          // in the mud
          ObjList.UpdateObjs(d->edit_obj, obj_number);
          /* now safe to free old proto and write over */
          if (obj_proto[obj_number].name)
            delete [] obj_proto[obj_number].name;
          if (obj_proto[obj_number].description)
            delete [] obj_proto[obj_number].description;
          if (obj_proto[obj_number].short_description)
            delete [] obj_proto[obj_number].short_description;
          if (obj_proto[obj_number].long_description)
            delete [] obj_proto[obj_number].long_description;
          if (obj_proto[obj_number].use_description)
            for (This2 = obj_proto[obj_number].use_description;
                 This2; This2 = next_one2)
            {
              next_one2 = This2->next;
              if (This2->keyword)
                delete [] This2->keyword;
              if (This2->description1)
                delete [] This2->description1;
              if (This2->description2)
                delete [] This2->description2;
              delete This2;
            }
          if (obj_proto[obj_number].ex_description)
            for (This = obj_proto[obj_number].ex_description;
                 This; This = next_one) {
              next_one = This->next;
              if (This->keyword)
                delete [] This->keyword;
              if (This->description)
                delete [] This->description;
              delete This;
            }
          obj_proto[obj_number] = *d->edit_obj;
          obj_proto[obj_number].item_number = obj_number;
        } else {
          /* uhoh.. need to make a new place in the object prototype table */
          int realcounter;
          int             counter;
          int             found = FALSE;

          struct obj_data *new_obj_proto;
          struct index_data *new_obj_index;
          struct obj_data *temp_obj;

          /* + 2.. strange but true */
          new_obj_index = new struct index_data[top_of_objt + 2];
          new_obj_proto = new struct obj_data[top_of_objt + 2];
          /* start counting through both tables */
          for (counter = 0; counter < top_of_objt + 1; counter++) {
            /* if we haven't found it */
            if (!found) {
              /* check if current virtual is bigger than our virtual */
              if (obj_index[counter].virt > d->edit_number) {
                /* eureka. insert now */
                /*---------*/
                new_obj_index[counter].virt = d->edit_number;
                new_obj_index[counter].number = 0;
                new_obj_index[counter].func = NULL;
                /*---------*/
                new_obj_proto[counter] = *(d->edit_obj);
                new_obj_proto[counter].in_room = NOWHERE;
                /* it is now safe (and necessary!) to assign real number to
                 * the edit_obj, which has been -1 all this time */
                d->edit_obj->item_number = counter;
                /* and assign to prototype as well */
                new_obj_proto[counter].item_number = counter;
                found = TRUE;
                /* insert the other proto at this point */
                new_obj_index[counter + 1] = obj_index[counter];
                new_obj_proto[counter + 1] = obj_proto[counter];
                new_obj_proto[counter + 1].item_number = counter + 1;
              } else {
                /* just copy from old to new, no num change */
                new_obj_proto[counter] = obj_proto[counter];
                new_obj_index[counter] = obj_index[counter];
              }
            } else {
              /* we HAVE already found it.. therefore copy to object + 1 */
              new_obj_index[counter + 1] = obj_index[counter];
              new_obj_proto[counter + 1] = obj_proto[counter];
              new_obj_proto[counter + 1].item_number = counter + 1;
            }
          }
          /* if we STILL haven't found it, means the object was > than all
           * the other objects.. so insert at end */
          if (!found) {
            new_obj_index[top_of_objt + 1].virt = d->edit_number;
            new_obj_index[top_of_objt + 1].number = 0;
            new_obj_index[top_of_objt + 1].func = NULL;

            clear_object(new_obj_proto + top_of_objt + 1);
            new_obj_proto[top_of_objt + 1] = *(d->edit_obj);
            new_obj_proto[top_of_objt + 1].in_room = NOWHERE;
            new_obj_proto[top_of_objt + 1].item_number = top_of_objt + 1;
            /* it is now safe (and necessary!) to assign real number to
             * the edit_obj, which has been -1 all this time */
            d->edit_obj->item_number = top_of_objt + 1;
          }
          top_of_objt++;

        
          /* we also have to renumber all the objects currently
             existing in the world. This is because when I start
             extracting objects, bad things will happen! */

          ObjList.UpdateNums(d->edit_obj->item_number);

          //for (temp_obj = object_list; temp_obj; temp_obj = temp_obj->next)
          //  if (GET_OBJ_RNUM (temp_obj) >= d->edit_obj->item_number)
          //    GET_OBJ_RNUM (temp_obj)++;

          /* free and replace old tables */
          delete [] obj_proto;
          delete [] obj_index;
          obj_proto = new_obj_proto;
          obj_index = new_obj_index;

          /* RENUMBER ZONE TABLES HERE, only
             because I ADDED an object!
             This code shamelessly ripped off from db.c */
          {
            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 'O':
                        ZCMD.arg1 =
                          (ZCMD.arg1 >= d->edit_obj->item_number ?
                           ZCMD.arg1 + 1 : ZCMD.arg1);
                        break;
                      case 'G':
                        ZCMD.arg1 =
                          (ZCMD.arg1 >= d->edit_obj->item_number ?
                           ZCMD.arg1 + 1 : ZCMD.arg1);
                        break;
                      case 'E':
                        ZCMD.arg1 =
                          (ZCMD.arg1 >= d->edit_obj->item_number ?
                           ZCMD.arg1 + 1 : ZCMD.arg1);
                        break;
                      case 'P':
                        ZCMD.arg1 =
                          (ZCMD.arg1 >= d->edit_obj->item_number ?
                           ZCMD.arg1 + 1 : ZCMD.arg1);
                        ZCMD.arg3 =
                          (ZCMD.arg3 >= d->edit_obj->item_number ?
                           ZCMD.arg3 + 1 : ZCMD.arg3);
                        break;
                      case 'R': /* rem obj from room */
                        ZCMD.arg2 =
                          (ZCMD.arg2 >= d->edit_obj->item_number ?
                           ZCMD.arg2 + 1 : ZCMD.arg2);
                        break;
                    }
                }
          }
          /* this fixes the creeping board problems */
        // not needed since real nums aren't used with boards anymore
/*        realcounter = real_object (d->edit_number);
          for (counter = 0; counter < NUM_OF_BOARDS; counter++)
            {
              if (BOARD_RNUM (counter) >= realcounter)
                BOARD_RNUM (counter) = BOARD_RNUM (counter) + 1;
            } */
        }  /* end of obj insertion */

        send_to_char("Writing object to disk..", d->character);
      write_objs_to_disk(d->character->player_specials->saved.zonenum);
        // don't wanna nuke the strings, so we use ClearObject
        if (d->edit_obj)
          Mem->ClearObject(d->edit_obj);
        d->edit_obj = NULL;
        STATE(d) = CON_PLAYING;
        REMOVE_BIT(PLR_FLAGS(d->character), PLR_EDITING);
        send_to_char("Done.\r\n", d->character);
      }
      break;
    case 'n':
    case 'N':
      send_to_char("Object not saved, aborting.\r\n", d->character);
      STATE(d) = CON_PLAYING;
      /* free up the editing object. free_obj *is* safe since
       it checks against prototype table */
      if (d->edit_obj)
        Mem->DeleteObject(d->edit_obj);
      d->edit_obj = NULL;
      d->edit_number = 0;
      REMOVE_BIT(PLR_FLAGS(d->character), PLR_EDITING);
      break;
    default:
      send_to_char("Invalid choice!\r\n", d->character);
      send_to_char("Do you wish to save this object internally?\r\n", d->character);
      break;
    }
    break;                      /* end of IEDIT_CONFIRM_SAVESTRING */

  case IEDIT_MAIN_MENU:
    /* throw us out to whichever edit mode based on user input */
    switch (*arg) {
    case 'q':
    case 'Q':
      d->edit_mode = IEDIT_CONFIRM_SAVESTRING;
#if CONFIRM_SAVE
      send_to_char("Do you wish to save this object internally?\r\n", d->character);
#else
      iedit_parse(d, "y");
#endif
      break;
    case 'x':
    case 'X':
      d->edit_mode = IEDIT_CONFIRM_SAVESTRING;
#if CONFIRM_SAVE
      send_to_char("Do you wish to save this object internally?\r\n", d->character);
#else
      iedit_parse(d, "y");
#endif
      break;
    case '1':
      send_to_char("Enter namelist:", d->character);
      d->edit_mode = IEDIT_EDIT_NAMELIST;
      break;
    case '2':
      send_to_char("Enter short desc:", d->character);
      d->edit_mode = IEDIT_SHORTDESC;
      break;
    case '3':
      send_to_char("Enter normal desc:\r\n", d->character);
      d->edit_mode = IEDIT_DESC;
      break;
    case '4':
      /* let's go out to modify.c */
      send_to_char("Enter long desc:\r\n", d->character);
      d->edit_mode = IEDIT_LONGDESC;
      //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 '5':
      iedit_disp_type_menu(d);
      d->edit_mode = IEDIT_TYPE;
      break;
    case '6':
      iedit_disp_extra_menu(d);
      d->edit_mode = IEDIT_EXTRAS;
      break;
    case '7':
      iedit_disp_aff_menu(d);
      d->edit_mode = IEDIT_AFF_BITS;
      break;
    case '8':
      iedit_disp_wear_menu(d);
      d->edit_mode = IEDIT_WEAR;
      break;
    case '9':
      send_to_char("Enter weight:", d->character);
      d->edit_mode = IEDIT_WEIGHT;
      break;
    case 'a':
    case 'A':
      send_to_char("Enter cost:", d->character);
      d->edit_mode = IEDIT_COST;
      break;
    case 'b':
    case 'B':
      if (GET_OBJ_TYPE(OBJ) == ITEM_CYBERDECK)
        send_to_char("Enter I/O Speed: ", CH);
      else send_to_char("  0) Other\r\n  1) Plastic\r\n  2) Iron\r\n  3) Silver\r\n"
                   "Item compisition (affects only allergies): ", CH);
      d->edit_mode = IEDIT_COSTPERDAY;
      break;
    case 'c':
    case 'C':
      send_to_char("Enter timer:", d->character);
      d->edit_mode = IEDIT_TIMER;
      break;
    case 'd':
    case 'D':
      iedit_disp_material_menu(d);
      d->edit_mode = IEDIT_MATERIAL;
      break;
    case 'e':
    case 'E':
      iedit_disp_rating_menu(d);
      d->edit_mode = IEDIT_RATING;
      break;
    case 'f':
    case 'F':
      iedit_disp_val1_menu(d);
      break;
    case 'g':
    case 'G':
      iedit_disp_prompt_apply_menu(d);
      break;
    case 'h':
    case 'H':
      /* if extra desc doesn't exist . */
      if (!d->edit_obj->ex_description) {
        d->edit_obj->ex_description = new extra_descr_data;
        memset((char *) d->edit_obj->ex_description, 0, sizeof(extra_descr_data));
      }
      /* There is a reason I need the double pointer. If at the extra desc
       * menu user presses '0' then I need to free the extra description.
       * Since it's at the end of list it's pointer must be pointing to
       * NULL.. thus the double pointer */
      d->misc_data = (void **) &(d->edit_obj->ex_description);
      iedit_disp_extradesc_menu(d);
      break;
    default:
      /* hm, i just realized you probably can't see this.. maybe prompt for
       * an extra RETURN. well, maybe later */
      send_to_char("That's not a valid choice!\r\n", d->character);
      iedit_disp_menu(d);
      break;
    }
    break;                      /* end of IEDIT_MAIN_MENU */

  case IEDIT_EDIT_NAMELIST:
    if (d->edit_obj->name)
      delete [] d->edit_obj->name;
    d->edit_obj->name = str_dup(arg);
    iedit_disp_menu(d);
    break;
  case IEDIT_SHORTDESC:
    if (d->edit_obj->short_description)
      delete [] d->edit_obj->short_description;
    d->edit_obj->short_description = str_dup(arg);
    iedit_disp_menu(d);
    break;
  case IEDIT_DESC:
    if (d->edit_obj->description)
      delete [] d->edit_obj->description;
    d->edit_obj->description = str_dup(arg);
    iedit_disp_menu(d);
    break;
  case IEDIT_LONGDESC:
    // we shouldn't get here
    break;
  case IEDIT_TYPE:
    number = atoi(arg);
    if ((number < 1) || (number > NUM_ITEM_TYPES) || (number == ITEM_CYBERWARE && !access_level(CH, LVL_PRESIDENT)) ||
       (number == ITEM_BIOWARE && !access_level(CH, LVL_PRESIDENT))) {
      send_to_char("That's not a valid choice!\r\n", d->character);
      iedit_disp_type_menu(d);
    } else if (number != 0) {
      GET_OBJ_TYPE(d->edit_obj) = number;
      GET_OBJ_VAL(d->edit_obj, 0) = 0;
      GET_OBJ_VAL(d->edit_obj, 1) = 0;
      GET_OBJ_VAL(d->edit_obj, 2) = 0;
      GET_OBJ_VAL(d->edit_obj, 3) = 0;
      GET_OBJ_VAL(d->edit_obj, 4) = 0;
      GET_OBJ_VAL(d->edit_obj, 5) = 0;
      GET_OBJ_VAL(d->edit_obj, 6) = 0;
      GET_OBJ_VAL(d->edit_obj, 7) = 0;
      GET_OBJ_VAL(d->edit_obj, 8) = 0;
      GET_OBJ_VAL(d->edit_obj, 9) = 0;
    }
    iedit_disp_menu(d);
    break;
  case IEDIT_EXTRAS:
    number = atoi(arg);
    if ((number < 0) || (number > NUM_EXTRA_FLAGS)) {
      send_to_char("That's not a valid choice!\r\n", d->character);
      iedit_disp_extra_menu(d);
    } else {
      /* if 0, quit */
      if (number == 0)
        iedit_disp_menu(d);
      /* if already set.. remove */
      else {
        if (IS_SET(GET_OBJ_EXTRA(d->edit_obj), 1 << (number - 1)))
          REMOVE_BIT(GET_OBJ_EXTRA(d->edit_obj), 1 << (number - 1));
        else
          /* set */
          SET_BIT(GET_OBJ_EXTRA(d->edit_obj), 1 << (number - 1));
        iedit_disp_extra_menu(d);
      }
    }
    break;
  case IEDIT_AFF_BITS:
    number = atoi(arg);
    if ((number > 0) && (number <= NUM_AFF_FLAGS))
    {
      if (IS_SET(OBJ->obj_flags.bitvector, 1 << (number - 1)))
        REMOVE_BIT(OBJ->obj_flags.bitvector, 1 << (number - 1));
      else
        SET_BIT(OBJ->obj_flags.bitvector, 1 << (number - 1));
    }
    else if (number == 0)
    {
      iedit_disp_menu(d);
      return;
    }
    iedit_disp_aff_menu(d);

    break;
  case IEDIT_WEAR:
    number = atoi(arg);
    if ((number < 0) || (number > NUM_WEAR_FLAGS)) {
      send_to_char("That's not a valid choice!\r\n", d->character);
      iedit_disp_wear_menu(d);
    } else {
      /* if 0, quit */
      if (number == 0)
        iedit_disp_menu(d);
      /* if already set.. remove */
      else {
        if (IS_SET(GET_OBJ_WEAR(d->edit_obj), 1 << (number - 1)))
          REMOVE_BIT(GET_OBJ_WEAR(d->edit_obj), 1 << (number - 1));
        else
          SET_BIT(GET_OBJ_WEAR(d->edit_obj), 1 << (number - 1));
        iedit_disp_wear_menu(d);
      }
    }
    break;
  case IEDIT_WEIGHT:
    number = atoi(arg);
    GET_OBJ_WEIGHT(d->edit_obj) = number;
    iedit_disp_menu(d);
    break;
  case IEDIT_COST:
    number = atoi(arg);
    GET_OBJ_COST(d->edit_obj) = number;
    iedit_disp_menu(d);
    break;
  case IEDIT_COSTPERDAY:
    number = atoi(arg);
    if (number < 0 || number > ITEM_SILVER && GET_OBJ_TYPE(OBJ) != ITEM_CYBERDECK) {
      send_to_char("Invalid choice!\r\nItem composition: ", CH);
      return;
    }
    GET_OBJ_RENT(d->edit_obj) = number;
    iedit_disp_menu(d);
    break;
  case IEDIT_TIMER:
    number = atoi(arg);
    GET_OBJ_TIMER(d->edit_obj) = number;
    iedit_disp_menu(d);
    break;
  case IEDIT_VALUE_1:
    /* lucky, I don't need to check any of these for outofrange values */
    number = atoi(arg);
    switch (GET_OBJ_TYPE(d->edit_obj))
    {
      case ITEM_SCROLL: case ITEM_WAND: case ITEM_POTION: case ITEM_STAFF:
        if (number < 0 || number > 10) {
          send_to_char("Force must be between 1 and 10.\r\nSpell force: ", d->character);
          return;
        }
        if (GET_OBJ_TYPE(d->edit_obj) == ITEM_SCROLL || GET_OBJ_TYPE(d->edit_obj) == ITEM_POTION) {
          GET_OBJ_VAL(d->edit_obj, 0) = number;
          iedit_disp_val4_menu(d);
          return;
        }
        break;
      case ITEM_WEAPON:
        if (number < 0 || number > 50) {
          send_to_char("Value must be between 0 and 50:\r\n"
                       "Power (0 for melee weapon): ", d->character);
          return;
        }
        break;
      case ITEM_FIREWEAPON:
        if (number < 0 || number > 50) {
          send_to_char("Value must be between 0 and 50:\r\n"
                       "Power (0 for melee weapon): ", d->character);
          return;
        }
        number = 0;
        break;
      case ITEM_MISSILE:
        if (number < 0 || number > 1) {
          send_to_char("Value must be 0 or 1!\r\nMissile type: ", CH);
          return;
        }
        break;
      case ITEM_BIOWARE:
        if (number < 1 || number > 5) {
          send_to_char("Value must be between 1 and 5.\r\nRating of bioware: ", CH);
          return;
        }
        break;
      case ITEM_CYBERWARE:
        if (number < 1 || number > 5) {
          send_to_char("Value must be between 1 and 5.\r\nRating of cyberware: ", CH);
          return;
        }
        break;
      case ITEM_CYBERDECK:
        if (number < 1 || number > 15) {
          send_to_char("Value must be between 1 and 15.\r\nMPCP Rating: ", CH);
          return;
        }
        break;
      case ITEM_PROGRAM:
        if (number < 1 || number > 30) {
          iedit_program_types_menu(d);
          return;
        }
        break;
      case ITEM_WORKING_GEAR:
        if (number < 1 || number > 3) {
          CLS(CH);
          send_to_char("1) Medical\r\n"
                       "2) Electronic\r\n"
                       "3) Cyberdeck\r\n"
                       "Enter type of kit: ", CH);
          return;
        } else number--;
        break;
      case ITEM_DECK_ACCESSORY:
        if (number < 0 || number > 1) {
          send_to_char("Invalid option!  Accessory type: ", CH);
          return;
        }
        break;
      case ITEM_GUN_ACCESSORY:
        if (number < 0 || number > 2) {
          send_to_char("Invalid option!  Accessory location: ", CH);
          return;
        }
        break;
      case ITEM_DOCWAGON:
        if (number < 1 || number > 3) {
          send_to_char("Value must be between 1 and 3.  DocWagon type: ", CH);
          return;
        }
        break;
      case ITEM_PATCH:
        if (number < 1 || number > NUM_PATCHES) {
          iedit_disp_patch_menu(d);
          return;
        } else number--;
        break;
      case ITEM_FOCUS:
        if (number < FOCI_SPELL || number > FOCI_WEAPON) {
          send_to_char("Invalid option.\r\nFocus type: ", CH);
          return;
        }
        break;
      case ITEM_CLIMBING:
        if (number < 1 || number > 3) {
          send_to_char("Rating must range from 1 to 3.  Rating: ", CH);
          return;
        }
        break;
      case ITEM_MONEY:
        if (number < 0 || number > 25000) {
          send_to_char("Value must range between 0 and 25000 nuyen.\r\nValue: ", CH);
          return;
        }
        break;
    }
    GET_OBJ_VAL(d->edit_obj, 0) = number;
    /* proceed to menu 2 */
    iedit_disp_val2_menu(d);
    break;

  case IEDIT_VALUE_2:
   /* here, I do need to check for outofrange values */
   number = atoi(arg);
   switch (GET_OBJ_TYPE(d->edit_obj)) {
     case ITEM_POTION:
       if (number < 1 || number > NUM_SPELLS) {
         send_to_char("Invalid choice!", d->character);
         iedit_disp_val2_menu(d);
         return;
       } else {
         GET_OBJ_VAL(d->edit_obj, 1) = number;
         iedit_disp_val3_menu(d);
         return;
       }
       break;
     case ITEM_CONTAINER:
       number = atoi(arg);
       if (number < 0 || number > 4) {
         send_to_char("Invalid choice!\r\n", d->character);
         iedit_disp_container_flags_menu(d);
       } else {
       /* if 0, quit */
         if (number != 0) {
           if (IS_SET(GET_OBJ_VAL(d->edit_obj, 1), 1 << (number - 1)))
             REMOVE_BIT(GET_OBJ_VAL(d->edit_obj, 1), 1 << (number - 1));
           else
             SET_BIT(GET_OBJ_VAL(d->edit_obj, 1), 1 << (number - 1));
           iedit_disp_val2_menu(d);
           return;
         } else {
           iedit_disp_val3_menu(d);
           return;
         }
       }
       break;
     case ITEM_QUIVER:
       if (number < 0 || number > 3) {
         send_to_char("Invalid input!\r\nQuiver type: ", CH);
         return;
       }
       break;
     case ITEM_WEAPON:
     case ITEM_FIREWEAPON:
       if ((number < 1) || (number > 4)) {
         send_to_char("Value must be between 1 and 4.\r\n"
                      "Base damage (1 - Light, 2 - Moderate, 3 - Serious, 4 - Deadly): ", d->character);
         return;
       }
       break;
     case ITEM_PROGRAM:
       if (number < 1 || number > 20) {
         send_to_char("Rating must be between 1 and 20.\r\nProgram Rating: ", CH);
         return;
       }
       break;
     case ITEM_BIOWARE:
       if (number < 10 || number > 600) {
         send_to_char("Body index cost must be between 10 and 600.\r\nBody index cost (x 100): ", CH);
         return;
       }
       break;
     case ITEM_CYBERWARE:
       if (number < 10 || number > 600) {
         send_to_char("Essence cost must be between 10 and 600.\r\nEssence cost (x 100): ", CH);
         return;
       }
       break;
     case ITEM_DECK_ACCESSORY:
       switch (GET_OBJ_VAL(OBJ, 0)) {
         case TYPE_FILE:
           if (number < 0) {
             send_to_char("Size must be greater than 0.  File size: ", CH);
             return;
           }
           break;
         case TYPE_UPGRADE:
           if (number < 0 || number > 5) {
             send_to_char("Invalid choice!  Upgrade type: ", CH);
             return;
           }
           break;
       }
       break;
     case ITEM_PATCH:
       if ((number < 1) || (number > 10)) {
         send_to_char("Rating must be between 1 and 10.\r\n", CH);
         return;
       }
       break;
     case ITEM_GUN_ACCESSORY:
       if (number < 1 || number > 4) {
         send_to_char("Invalid option!  Accessory type: ", CH);
         return;
       }
       break;
     case ITEM_FOCUS:
       if (number < 1 || number > 10) {
         send_to_char("Rating must be between 1 and 10.\r\n", CH);
         return;
       }
       break;
     case ITEM_GUN_CLIP:
       if (number < 1 || number > 8) {
         send_to_char("Invalid option!\r\nClip type: ", CH);
         return;
       }
       number += 20;
       if (number == 27)
         number = 19;
       if (number == 28)
         number = 20;
       break;
     case ITEM_RADIO:
       if (number < 0 || number > 5) {
         send_to_char("Enter radio's range (0-5): ", CH);
         return;
       }
       break;
     case ITEM_MONEY:
       if (number < 1 || number > 2) {
         iedit_disp_val2_menu(d);
         return;
       }
       number--;
       break;
     default:
       break;
   }
   GET_OBJ_VAL(d->edit_obj, 1) = number;
   iedit_disp_val3_menu(d);
   break;

  case IEDIT_VALUE_3:
    number = atoi(arg);
    switch (GET_OBJ_TYPE(d->edit_obj)) {
      case ITEM_POTION:
        if (number < 1 || number > NUM_SPELLS) {
          send_to_char("Invalid choice!", d->character);
          iedit_disp_val3_menu(d);
          return;
        }
        break;
      case ITEM_DRINKCON:
      case ITEM_FOUNTAIN:
        if (number < 1 || number > NUM_DRINK_TYPES) {
          send_to_char("Invalid choice.", CH);
          iedit_disp_val4_menu(d);
          return;
        }
        number--; // to give the correct value to the object
        break;
      case ITEM_WEAPON:
      case ITEM_FIREWEAPON:
        if (number < 0 || number > 4) {
          send_to_char("Value must be between 0 and 4.\r\n", CH);
          iedit_disp_val3_menu(d);
          return;
        }
        break;
      case ITEM_BIOWARE:
        if (number < 0 || number > NUM_BIOWARE_TYPES) {
          iedit_disp_biotype_menu(d);
          return;
        }
        number--;
        break;
      case ITEM_CYBERWARE:
        if (number < 0 || number > NUM_CYBERWARE_TYPES) {
          iedit_disp_cybertype_menu(d);
          return;
        }
        number--;
        break;
      case ITEM_PROGRAM:
        if (number < 0) {
          send_to_char("Invalid input.\r\nProgram Size: ", CH);
          return;
        }
        break;
      case ITEM_DECK_ACCESSORY:
        if (GET_OBJ_VAL(OBJ, 0) == TYPE_FILE) {
          if (number < 1 || number > NUM_FILES) {
            iedit_disp_val3_menu(d);
            return;
          }
        } else switch (GET_OBJ_VAL(OBJ, 1)) {
          case 0:
            if (number < 1 || number > 15) {
              send_to_char("MPCP must be between 1 and 15.  MPCP Rating: ", CH);
              return;
            }
            break;
          case 1:
            if (number < 1 || number > 1000) {
              send_to_char("Invalid value!  Active memory increase: ", CH);
              return;
            }
            break;
          case 2:
            if (number < 1 || number > 20000) {
              send_to_char("Invalid value!  Storage memory increase: ", CH);
              return;
            }
            break;
          case 3:
            if (number < 1 || number > 100) {
              send_to_char("Invalid value!  Load speed increase: ", CH);
              return;
            }
            break;
          case 4:
            if (number < 1 || number > 50) {
              send_to_char("Invalid value!  I/O speed increase: ", CH);
              return;
            }
            break;
          case 5:
            if (number < 1 || number > 3) {
              send_to_char("Values must range from 1 to 3.  Reaction increase level: ", CH);
              return;
            }
            break;
        }
        break;
      case ITEM_GUN_ACCESSORY:
        if (number < -3 || number > -1) {
          send_to_char("Modifier must be between -3 and -1.  Recoil modifier: ", CH);
          return;
        }
        break;
      case ITEM_FOCUS:
        if (GET_OBJ_VAL(OBJ, 0) == FOCI_SPIRIT && (number < 1 || number > NUM_SPIRITS)) {
          send_to_char("Invalid response.  Focus spirit type: ", CH);
          return;
        } else if (GET_OBJ_VAL(OBJ, 0) == FOCI_SPELL && (number < 1 || number > NUM_SPELLS)) {
          send_to_char("Invalid choice!\r\n", CH);
          iedit_disp_val3_menu(d);
          return;
        } else if (GET_OBJ_VAL(OBJ, 0) == FOCI_SPELL_CAT) {
          if (number < 1 || number > 5) {
            send_to_char("Invalid choice!  Focus spell category: ", CH);
            return;
          } else number--;
        }
        break;
      case ITEM_SPELL_FORMULA:
        if ((number < 1) || (number > 50)) {
          send_to_char("Force must be between 1 and 50.\r\n", CH);
          return;
        }
        break;
      case ITEM_RADIO:
        if (number < 1 || number > 6) {
          send_to_char("Enter encryption/decryption rating (1-6): ", CH);
          return;
        }
        break;
      case ITEM_MONEY:
        if (number < 1 || number > 3) {
          iedit_disp_val3_menu(d);
          return;
        }
        break;
      default:
        break;
    }
    GET_OBJ_VAL(d->edit_obj, 2) = number;
    iedit_disp_val4_menu(d);
    break;

  case IEDIT_VALUE_4:
    number = atoi(arg);
    switch (GET_OBJ_TYPE(d->edit_obj)) {
      case ITEM_SCROLL:
      case ITEM_POTION:
      case ITEM_WAND:
      case ITEM_STAFF:
        if (number < 1 || number > NUM_SPELLS) {
          send_to_char("Invalid choice!", d->character);
          iedit_disp_val4_menu(d);
          return;
        }
        break;
      case ITEM_WEAPON:
        if (number < 1 || (!access_level(CH, LVL_PRESIDENT) && number == TYPE_BIFURCATE) || number > NUM_WEAPON_TYPES) {
          send_to_char("Invalid choice!", d->character);
          iedit_disp_weapon_menu(d);
          return;
        }
        switch (number + TYPE_HIT) {
          case TYPE_PISTOL:
          case TYPE_BLAST:
            GET_OBJ_VAL(OBJ, 7) = 0;
            GET_OBJ_VAL(OBJ, 8) = -1;
            GET_OBJ_VAL(OBJ, 9) = 0;
            break;
          case TYPE_SHOTGUN:
            GET_OBJ_VAL(OBJ, 7) = 0;
            GET_OBJ_VAL(OBJ, 8) = 0;
            GET_OBJ_VAL(OBJ, 9) = -1;
            break;
          case TYPE_GRENADE_LAUNCHER:
          case TYPE_ROCKET:
          case TYPE_RIFLE:
          case TYPE_MACHINE_GUN:
          case TYPE_CANNON:
          case TYPE_BIFURCATE:
            GET_OBJ_VAL(OBJ, 7) = 0;
            GET_OBJ_VAL(OBJ, 8) = 0;
            GET_OBJ_VAL(OBJ, 9) = 0;
            break;
          default:
            GET_OBJ_VAL(OBJ, 7) = -1;
            GET_OBJ_VAL(OBJ, 8) = -1;
            GET_OBJ_VAL(OBJ, 9) = -1;
        }
        break;
      case ITEM_FIREWEAPON:
        if (number < 1 || (!access_level(CH, LVL_PRESIDENT) && number == TYPE_BIFURCATE) || number > NUM_WEAPON_TYPES) {
          send_to_char("Invalid choice!", d->character);
          iedit_disp_weapon_menu(d);
          return;
        }
        number = TYPE_ARROW;
        break;
      case ITEM_PROGRAM:
        if (number < 1 || (!access_level(CH, LVL_PRESIDENT) && number == TYPE_BIFURCATE) ||
            number > NUM_WEAPON_TYPES) {
          iedit_disp_val6_menu(d);
          return;
        }
        number = number + TYPE_HIT - 1;
        break;
      case ITEM_SPELL_FORMULA:
        return;
      case ITEM_DECK_ACCESSORY:
        if (GET_OBJ_VAL(OBJ, 0) == TYPE_FILE) {
          number -= 1;
          if (number < 0 || number > (NUM_FILE_RATINGS - 1)) {
            iedit_disp_val4_menu(d);
            return;
          }
        } else if (number < 1 || number > 15) {
          send_to_char("MPCP value must be between 1 and 15!\r\nMPCP to enhance: ", CH);
          return;
        }
        break;
      default:
        break;
    }
    GET_OBJ_VAL(d->edit_obj, 3) = number;
    if (GET_OBJ_TYPE(OBJ) == ITEM_WEAPON)
      GET_OBJ_VAL(OBJ, 3) += TYPE_HIT;
    iedit_disp_val5_menu(d);
    break;

  case IEDIT_VALUE_5:
    number = atoi(arg);
    switch (GET_OBJ_TYPE(d->edit_obj)) {
      case ITEM_WEAPON:
      case ITEM_FIREWEAPON:
        if (number < 1 || number > NUM_SKILL_TYPES) {
          send_to_char("Invalid choice!", d->character);
          iedit_disp_skill_menu(d);
        } else {
    // this is to skip these general skills which aren't in the list
          number += 102;
          if (number >= SKILL_UNARMED_COMBAT)
            number += 3;
          if (number >= SKILL_FIREARMS)
            number++;
          if (number >= SKILL_GUNNERY)
            number++;
          if (number >= SKILL_PROJECTILES)
            number++;
          if (number >= SKILL_THROWING_WEAPONS)
            number++;

        }
        break;
      case ITEM_CYBERWARE:
        if (number < 0 || number > 5) {
          send_to_char("Enter radio's range (0-5): ", CH);
          return;
        }
        break;
      default:
        break;
    }
    GET_OBJ_VAL(d->edit_obj, 4) = number;
    iedit_disp_val6_menu(d);
    break;

  case IEDIT_VALUE_6:
    number = atoi(arg);
    switch (GET_OBJ_TYPE(d->edit_obj)) {
      case ITEM_WEAPON:
        break;
      case ITEM_FIREWEAPON:
        if (number < 0 || number > 1) {
          send_to_char("Value must be 0 or 1!\r\nType: ", CH);
          return;
        }
        break;
      case ITEM_CYBERWARE:
        if (number < 1 || number > 6) {
          send_to_char("Enter encryption/decryption rating (1-6): ", CH);
          return;
        }
        break;
      default:
        break;
    }
    GET_OBJ_VAL(d->edit_obj, 5) = number;
    iedit_disp_val7_menu(d);
    break;
  case IEDIT_VALUE_7:
    number = atoi(arg);
    switch (GET_OBJ_TYPE(d->edit_obj)) {
      case ITEM_WEAPON:
        break;
      case ITEM_FIREWEAPON:
        if (number < 1 || number > 10) {
          send_to_char("Strength min. must be between 1 and 10.  Enter strength minimum: ", CH);
          return;
        }
        break;
      case ITEM_SPELL_FORMULA:
        // adjust the values from the type of spell
        if (number <= 0 || number > NUM_SPELLS) {
          iedit_disp_spells_menu(d);
          return;
        }
        GET_OBJ_VAL(OBJ, 0) = grimoire[number].physical;
        GET_OBJ_VAL(OBJ, 1) = grimoire[number].category;
        GET_OBJ_VAL(OBJ, 3) = grimoire[number].target;
        GET_OBJ_VAL(OBJ, 4) = grimoire[number].drain;
        GET_OBJ_VAL(OBJ, 5) = grimoire[number].damage;
        GET_OBJ_VAL(OBJ, 8) = SPELL_ELEMENT_NONE;
        break;
      default:
        break;
    }
    GET_OBJ_VAL(d->edit_obj, 6) = number;
    iedit_disp_val8_menu(d);
    break;

  case IEDIT_VALUE_8:
    number = atoi(arg);
    switch (GET_OBJ_TYPE(d->edit_obj)) {
    case ITEM_SPELL_FORMULA:
      if (number < 0 || number > 1) {
        send_to_char("0 for mage, 1 for shaman: ", CH);
        return;
      }
      break;
    case ITEM_WEAPON:
      if (!access_level(CH, LVL_PRESIDENT))
        if (!read_object(number, VIRTUAL)) {
          send_to_char("Invalid vnum.\r\n", CH);
          iedit_disp_val8_menu(d);
        }
      if (number > 0) {
        modified = FALSE;
        for (j = 0; (j < MAX_OBJ_AFFECT && !modified); j++)
          if (!(OBJ->affected[j].modifier)) {
            OBJ->affected[j].location = read_object(number, VIRTUAL)->affected[0].location;
            OBJ->affected[j].modifier = read_object(number, VIRTUAL)->affected[0].modifier;
            modified = TRUE;
          }
        GET_OBJ_WEIGHT(OBJ) += GET_OBJ_WEIGHT(read_object(number, VIRTUAL));
        GET_OBJ_COST(OBJ) += GET_OBJ_COST(read_object(number, VIRTUAL));
      }
      break;
    default:
      break;
    }
    GET_OBJ_VAL(d->edit_obj, 7) = number;
    iedit_disp_val9_menu(d);
    break;

  case IEDIT_VALUE_9:
    number = atoi(arg);
    switch (GET_OBJ_TYPE(d->edit_obj)) {
    case ITEM_WEAPON:
      if (!access_level(CH, LVL_PRESIDENT))
        if (!read_object(number, VIRTUAL)) {
          send_to_char("Invalid vnum.\r\n", CH);
          iedit_disp_val9_menu(d);
          return;
        }
      if (number > 0) {
        modified = FALSE;
        for (j = 0; (j < MAX_OBJ_AFFECT && !modified); j++)
          if (!(OBJ->affected[j].modifier)) {
            OBJ->affected[j].location = read_object(number, VIRTUAL)->affected[0].location;
            OBJ->affected[j].modifier = read_object(number, VIRTUAL)->affected[0].modifier;
            modified = TRUE;
          }
        GET_OBJ_WEIGHT(OBJ) += GET_OBJ_WEIGHT(read_object(number, VIRTUAL));
        GET_OBJ_COST(OBJ) += GET_OBJ_COST(read_object(number, VIRTUAL));
      }
      break;
    default:
      break;
    }
    GET_OBJ_VAL(d->edit_obj, 8) = number;
    iedit_disp_val10_menu(d);
    break;

  case IEDIT_VALUE_10:
    number = atoi(arg);
    switch (GET_OBJ_TYPE(d->edit_obj)) {
    case ITEM_WEAPON:
      if (!access_level(CH, LVL_PRESIDENT))
        if (!read_object(number, VIRTUAL)) {
          send_to_char("Invalid vnum.\r\n", CH);
          iedit_disp_val10_menu(d);
          return;
        }
      if (number > 0) {
        modified = FALSE;
        for (j = 0; (j < MAX_OBJ_AFFECT && !modified); j++)
          if (!(OBJ->affected[j].modifier)) {
            OBJ->affected[j].location = read_object(number, VIRTUAL)->affected[0].location;
            OBJ->affected[j].modifier = read_object(number, VIRTUAL)->affected[0].modifier;
            modified = TRUE;
          }
        GET_OBJ_WEIGHT(OBJ) += GET_OBJ_WEIGHT(read_object(number, VIRTUAL));
        GET_OBJ_COST(OBJ) += GET_OBJ_COST(read_object(number, VIRTUAL));
      }
      break;
    default:
      break;
    }
    GET_OBJ_VAL(d->edit_obj, 9) = number;
    iedit_disp_menu(d);
    break;

  case IEDIT_PROMPT_APPLY:
    number = atoi(arg);
    if (number == 0) {
      iedit_disp_menu(d);
      return;
    } else if (number < 0 || number > MAX_OBJ_AFFECT) {
      send_to_char("Invalid choice!\r\n", d->character);
      iedit_disp_prompt_apply_menu(d);
    } else {
      d->edit_number2 = number - 1;
      d->edit_mode = IEDIT_APPLY;
      iedit_disp_apply_menu(d);
    }
    break;
  case IEDIT_APPLY:
    number = atoi(arg);
    if (number == 0) {
      d->edit_obj->affected[d->edit_number2].location = 0;
      d->edit_obj->affected[d->edit_number2].modifier = 0;
      iedit_disp_prompt_apply_menu(d);
    } else if (number < 0 || number >= NUM_APPLY_FLAGS) {
      send_to_char("Invalid choice!\r\n", d->character);
      iedit_disp_apply_menu(d);
    } else {
      d->edit_obj->affected[d->edit_number2].location = number;
      send_to_char("Modifier:", d->character);
      d->edit_mode = IEDIT_APPLYMOD;
    }
    break;
  case IEDIT_APPLYMOD:
    number = atoi(arg);
    d->edit_obj->affected[d->edit_number2].modifier = number;
    iedit_disp_prompt_apply_menu(d);
    break;
  case IEDIT_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);
    iedit_disp_extradesc_menu(d);
    break;
  case IEDIT_MATERIAL:
    number = atoi(arg);
    if (number == 0)
      iedit_disp_menu(d);
    else if (number > 0 && number < NUM_MATERIALS + 1)
    {
      GET_OBJ_MATERIAL(OBJ) = number - 1;
      iedit_disp_menu(d);
    } else
      iedit_disp_material_menu(d);
    break;
  case IEDIT_RATING:
    number = atoi(arg);
    if (number == 0)
      iedit_disp_menu(d);
    else if (number > 0 && number < NUM_BARRIERS + 1) {
      GET_OBJ_CONDITION(OBJ) = GET_OBJ_BARRIER(OBJ) = barrier_ratings[number - 1];
      iedit_disp_menu(d);
    } else iedit_disp_rating_menu(d);
    break;

  case IEDIT_EXTRADESC_MENU:
    number = atoi(arg);
    switch (number) {
    case 0:
      {
        /* if something got left out */
        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 */
        iedit_disp_menu(d);
      }
      break;
    case 1:
      d->edit_mode = IEDIT_EXTRADESC_KEY;
      send_to_char("Enter keywords, separated by spaces:", d->character);
      break;
    case 2:
      d->edit_mode = IEDIT_EXTRADESC_DESCRIPTION;
      send_to_char("Enter 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 keyword or description has not been changed don't allow person to
       * edit next */
      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);
        iedit_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;
          /* edit new extra, we NEED double pointer because i will set
           * *d->misc_data to NULL later */
          d->misc_data =
            (void **) &((struct extra_descr_data *) * d->misc_data)->next;

        }
        iedit_disp_extradesc_menu(d);

      }
      break;
    default:
      send_to_char("Invalid choice!\r\n", d->character);
      iedit_disp_extradesc_menu(d);
      break;
    }
    break;
  default:
    break;
  }
}

#undef OBJ

void write_objs_to_disk(int zone)
{
  int counter, counter2, realcounter;
  FILE *fp;
  struct obj_data *obj;
  struct extra_descr_data *ex_desc;

  zone = real_zone(zone);

  obj = Mem->GetObject();

  sprintf(buf, "%s/%d.obj", OBJ_PREFIX, zone_table[zone].number);
  fp = fopen(buf, "w+");

  /* start running through all objects in this zone */
  for (counter = zone_table[zone].number * 100; counter <= zone_table[zone].top; counter++) {
    /* write object to disk */
    realcounter = real_object(counter);
    if (realcounter >= 0) {
      *obj = obj_proto[realcounter];
      fprintf(fp, "#%d\n", GET_OBJ_VNUM(obj));
      fprintf(fp, "%s~\n", obj->name ? obj->name : "unnamed");
      fprintf(fp, "%s~\n", obj->short_description ? obj->short_description : "an unnamed object");
      fprintf(fp, "%s~\n", obj->description ? obj->description : "An unnamed object sits here");
      if (obj->long_description)
        fprintf(fp, "%s~\n", cleanup(buf2, obj->long_description));
      else fprintf(fp, "You see an uncreative object.~\n");
      fprintf(fp, "%d %d %d %d %d %ld\n", GET_OBJ_TYPE(obj), GET_OBJ_EXTRA(obj), GET_OBJ_WEAR(obj),
                  GET_OBJ_MATERIAL(obj), GET_OBJ_BARRIER(obj), obj->obj_flags.bitvector);
      fprintf(fp, "%d %d %d %d %d %d %d %d %d %d\n", GET_OBJ_VAL(obj, 0), GET_OBJ_VAL(obj, 1),
                  GET_OBJ_VAL(obj, 2), GET_OBJ_VAL(obj, 3), GET_OBJ_VAL(obj, 4), GET_OBJ_VAL(obj, 5),
                  GET_OBJ_VAL(obj, 6), GET_OBJ_VAL(obj, 7), GET_OBJ_VAL(obj, 8), GET_OBJ_VAL(obj, 9));
      fprintf(fp, "%d %d %d\n", GET_OBJ_WEIGHT(obj), GET_OBJ_COST(obj), GET_OBJ_RENT(obj));
      /* do we have extra descriptions? */
      if (obj->ex_description)
        for (ex_desc = obj->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));
        }
      /* do we have affects? */
      for (counter2 = 0; counter2 < MAX_OBJ_AFFECT; counter2++)
        if (obj->affected[counter2].modifier) {
          fprintf(fp, "A\n");
          fprintf(fp, "%d %d\n", obj->affected[counter2].location,
          obj->affected[counter2].modifier);
        }
    }
  }
  /* write final line, close */
  fprintf(fp, "$~\n");
  fclose(fp);
  /* nuke temp object, but not the strings */
  Mem->ClearObject(obj);
  write_index_file("obj");
}