/
roa/
roa/lib/boards/
roa/lib/config/
roa/lib/edits/
roa/lib/help/
roa/lib/misc/
roa/lib/plrobjs/
roa/lib/quests/
roa/lib/socials/
roa/lib/www/
roa/lib/www/LEDSign/
roa/lib/www/LEDSign/fonts/
roa/lib/www/LEDSign/scripts/
roa/src/s_inc/
roa/src/sclient/
roa/src/sclient/binary/
roa/src/sclient/text/
roa/src/util/
/************************************************************************
Realms of Aurealis 		James Rhone aka Vall of RoA

z_olc.c				RoAOLCv2.1 Zone OnLine Creation	
				and editting code.

		******** Heavily modified and expanded ********
		*** BE AWARE OF ALL RIGHTS AND RESERVATIONS ***
		******** Heavily modified and expanded ********
		        All rights reserved henceforth. 

    Please note that no guarantees are associated with any code from
Realms of Aurealis.  All code which has been released to the general
public has been done so with an 'as is' pretense.  RoA is based on both
Diku and CircleMUD and ALL licenses from both *MUST* be adhered to as well
as the RoA license.   *** Read, Learn, Understand, Improve ***
*************************************************************************/
#include "conf.h"
#include "sysdep.h"

#include "structures.h"
#include "comm.h"
#include "interpreter.h"
#include "acmd.h"
#include "db.h"
#include "utils.h"
#include "mudlimits.h"
#include "handler.h"
#include "roaolc.h"
#include "lists.h"
#include "htown.h"
#include "global.h"
#include "thief.h"

/* external vars */
extern char   		zlock_reset;
extern char		*zone_bits[];
extern char		*atmos_names[];

/* external functions */
extern int  real_zone(int zone);
extern void reset_roazone(int zone);
extern char *get_name_by_id(long idnum);
extern int  unidle_this_zone(int zone);
extern void reload_zone(int zone);
extern void  free_room_affects(struct room_affect_type *head);
extern rtrig *free_rtriggers(rtrig *ths);

/* internal functions */
int  create_roazone_cmds(int zone);
int  save_roazone_cmds(int zone);

ROA_MENU(zedit_top_menu);
ROA_MENU(zedit_confirm_quit);
ROA_MENU(zedit_confirm_save);
ROA_MENU(confirm_ipp_menu);

// wax all objects in zone, mobs that are in/from this zone
int purge_zone(int zone)
{
  chdata *ch, *next_ch;
  obdata *ob, *next_ob;
  int i, d;
  rmdata *r;

  if (!REAL_ZONE(zone))
  {
    sprintf(buf, "SYSERR: Attempting to purge invalid zone #%d.",zone);
    mudlog(buf, BRF, LEV_IMM, FALSE);
    return FALSE;
  }

  // NOW, must purge all traps on dirs and rooms... 4/26/98 -jtrhone
  for (i = 0; i < top_of_world; i++)
  {
    r = &world[i];
    if (r->zone == zone)
    {
      if (TRAPS(r))
        TRAPS(r) = trap_from_room(TRAPS(r), r);

      for (d = 0; d < NUM_OF_DIRS; d++)
        if (DIR(i, d) && TRAPS(DIR(i, d)))
          TRAPS(DIR(i, d)) = trap_from_dir(TRAPS(DIR(i, d)), DIR(i, d));

      // also, wipe all room affects
      if (r->room_affects)
      {
        free_room_affects(r->room_affects);
        r->room_affects = NULL;
      }

      // now, wax rtrigs and waits  6/6/98 -jtrhone
      RTRIGS(r) = free_rtriggers(RTRIGS(r));
      FREENULL(RTARGET_CHAR(r));
      FREENULL(RTARGET_OBJ(r));
      RPROC_WAIT(r) = 0;
      RPROC_CUR(r) = RPROC_BEG(r);
      RTRIG_WAITING(r) = FALSE;
    }
  }

  // go thru entire character list, if in zone or from zone, wax, unless
  // meets special conditions...
  for (ch = character_list; ch; ch = next_ch)
  {
    next_ch = ch->next;

    if (IS_PC(ch))
      continue;

    if (zlock_reset &&                        // zone was zlocked (unnatural) 
	(INVALID_ROOM(ch->in_room) 	 ||   // mob not in valid room
         world[ch->in_room].zone == zone ||   // mob in our zone 
	 GET_MOB_VNUM(ch) / 100 == zone))     // mob from our zone
    {
      extract_char(ch);
      continue;
    }

    // or, natural reset, not fighting, full hit, not charmed, not mounted
    // and in our zone or invalid room
    if (!FIGHTING(ch) && !CHARMED(ch) && GET_HIT(ch) >= GET_MAX_HIT(ch) &&
        !IS_MOUNTED(ch) &&
        (ch->in_room <= NOWHERE || world[ch->in_room].zone == zone)) 
      extract_char(ch);
  }
    
  for (ob = object_list; ob; ob = next_ob)
  {
    next_ob = ob->next;

    // if zlocked, unnatural, or untouched object
    // not carried, 
    if (zlock_reset || !ob->touched)
      if (!ob->carried_by && ob->in_room > NOWHERE && 
	  world[ob->in_room].zone == zone)
      {
        while ((next_ob = ob->contains))
	  extract_obj(next_ob);
	next_ob = ob->next;
        extract_obj(ob);
      }
  }

  return TRUE;
}

/* zone must exist! purges everything and resets zone at 100% probs */
void unnatural_reset(int zone)
{
  if (real_zone(zone) < 0)
  {
    sprintf(buf, "SYSERR: Attempted reset of invalid zone (%d).",zone);
    mudlog(buf, BRF, LEV_IMM, TRUE);
    return;
  }

  /* now, we load the zone rooms if they arent in memory */
  if (ZONE_FREED(zone))
    reload_zone(zone);

  zlock_reset = TRUE;
  purge_zone(zone);
  reset_roazone(zone);
  zlock_reset = FALSE;
}

/* zone must exist! purges everything and resets zone at preset probs */
void natural_reset(int zone)
{
  if (real_zone(zone) < 0)
  {
    sprintf(buf, "SYSERR: Attempted reset of invalid zone (%d).",zone);
    mudlog(buf, BRF, LEV_IMM, TRUE);
    return;
  }

  /* now, we load the zone rooms if they arent in memory */
  if (ZONE_FREED(zone))
    reload_zone(zone);

  zlock_reset = TRUE;
  purge_zone(zone);
  zlock_reset = FALSE;
  reset_roazone(zone);
}

ACMD(do_zlock)
{
  dsdata *d;
  char buf[MAX_STRING_LENGTH];
  int i, zone;
  int force = FALSE;
    
  if (IS_NPC(ch))
  {
    send_to_char("Oh no!  None of that stuff!\n\r", ch);
    return;
  }

  if (!*argument)
  {
    for (i = 0; i < NUM_ZONES; i++)
    {
      if (REAL_ZONE(i) && ZONE_FLAGGED(i, Z_LOCKED))
      {
	sprintf(buf, "Zone %3d locked by %s\n\r",
		i, get_name_by_id(zone_table[i].locked_id));
	send_to_char(buf, ch);
      }
    }
    return;
  }

  argument = one_argument(argument, buf);
  while (*buf == '-')
  {
    force = !strncmp("-force", buf, strlen(buf));
    argument = one_argument(argument, buf);
  }
    
  zone = atoi(buf);
    
  if (!olc_perms(ch, LEV_IMPL, zone))
    return;
    
  if (!REAL_ZONE(zone))
  {
    send_to_char("Invalid zone number.\n\r", ch);
    return;
  }

  if (ZONE_FLAGGED(zone, Z_LOCKED) && !ch->pc_specials->saved.zone_locked)
  {
    sprintf(buf, "Zone %3d already locked by %s\n\r",
	    zone, get_name_by_id(zone_table[zone].locked_id));
    send_to_char(buf, ch);
    return;
  }

  if ((zone == DEF_HOMETOWN && GET_LEVEL(ch) < LEV_IMPL) || 
       zone == LIMBO_ZONE || zone == HOUSE_ZONE)
  {
    send_to_char("That zone may not be locked.\n\r", ch);
    return;
  }

  if (ch->pc_specials->saved.zone_locked && 
      ch->pc_specials->saved.zone_locked != zone)
  {
    send_to_char("You already have another zone locked.\n\r", ch);
    return;
  }

  for (d = descriptor_list; d; d = d->next)
  {
    if (d->character && d->character->in_room > NOWHERE &&
        world[d->character->in_room].zone == zone &&
        d->character != ch && GET_LEVEL(d->character) < LEV_GOD)
    {
      if (!force)
      {
	sprintf(buf, "Can't lock %d because %s is there.\n\r",
		zone, d->character->player.name);
	send_to_char(buf, ch);
	return;
      }
      else
      {
	act("Teleporting $N to default htown.", FALSE,ch,0,d->character,TO_CHAR);
	act("$n disappears in a puff of smoke.", TRUE,d->character,0,0,TO_ROOM);
	char_from_room(d->character);
	char_to_room(d->character, real_room(DEF_GATEWAY));
	act("$n arrives from a puff of smoke.", TRUE,d->character,0,0,TO_ROOM);
	act("$n has teleported you!", TRUE, ch, 0, d->character, TO_VICT);
	do_look_at_room(d->character, 0, 0);
      }
    }
  }

  if (!PLR2_FLAGGED(ch, PLR2_IPP))
  {
    MENU_HANDLER_ARG(ch) = (void *) 0;
    menu_jump(ch, confirm_ipp_menu);
    return;
  }

  zone_table[zone].locked_id = GET_IDNUM(ch);
  ch->pc_specials->saved.zone_locked = zone;

  sprintf(buf, "SYSUPD: %s locked zone #%%6%d%%0.", GET_NAME(ch), zone);
  mudlog(buf, BUG, MAX(GET_INVIS_LEV(ch), LEV_IMM), TRUE);

  SET_BIT(ZONE_FLAGS(zone), Z_LOCKED);
  sprintf(buf, "Zone #%%6%d%%0 (%s) locked.\n\r",zone, zone_table[zone].name); S2C();

  unidle_this_zone(zone);
  zone_table[zone].age = 0;
  unnatural_reset(zone);
}

ACMD(do_zunlock)
{
  char buf[MAX_STRING_LENGTH];
  int zone = ch->pc_specials->saved.zone_locked;
    
  if (IS_NPC(ch))
  {
    send_to_char("Oh no!  None of that stuff!\n\r", ch);
    return;
  }

  if (!olc_perms(ch, LEV_CIMP, zone))
    return;
    
  if (!ch->pc_specials->saved.zone_locked && GET_LEVEL(ch) < LEV_CIMP)
  {
    send_to_char("You don't have any zones locked.\n\r", ch);
    return;
  }

  argument = one_argument(argument, buf);

  if (strlen(buf) && !strncmp("-save", buf, strlen(buf)))
  {
    if (*argument && GET_LEVEL(ch) >= LEV_CIMP)
      zone = atoi(argument);
	
    if (!REAL_ZONE(zone))
    {
      send_to_char("That zone does not exist.\n\r",ch);
      return;
    }

    if (!ZONE_FLAGGED(zone, Z_LOCKED))
    {
      send_to_char("That zone is not locked.\n\r", ch);
      return;
    }
	
    create_roazone_cmds(zone);
    save_roazone_cmds(zone);

    sprintf(buf,"%d",zone);
    do_mobsave(ch, buf, 0, 0);
    do_objsave(ch, buf, 0, 0);
    do_wldsave(ch, buf, 0, 0);
  }
  else 
  if (!strlen(buf) || strncmp("-nosave", buf, strlen(buf)))
  {
    send_to_char("%Bzunlock < -save | -nosave > [<zone num>]%0\n\r", ch);
    return;
  }
  else
  {
    if (*argument && GET_LEVEL(ch) >= LEV_CIMP)
      zone = atoi(argument);
	
    if (!REAL_ZONE(zone))
    {
      send_to_char("That zone does not exist.\n\r",ch);
      return;
    }

    if (!ZONE_FLAGGED(zone, Z_LOCKED))
    {
      send_to_char("That zone is not locked.\n\r", ch);
      return;
    }
  }

  sprintf(buf, "SYSUPD: %s unlocked zone #%%6%d%%0.", GET_NAME(ch), zone);
  mudlog(buf, BUG, MAX(GET_INVIS_LEV(ch), LEV_IMM), TRUE);
	
  zone_table[zone].locked_id = 0;
  ch->pc_specials->saved.zone_locked = 0;

  REMOVE_BIT(ZONE_FLAGS(zone), Z_LOCKED); 
  send_to_char("Zone unlocked.\n\r", ch);

  unidle_this_zone(zone);
  zone_table[zone].age = 0;

  /* reset weather depending on time (just hit target temp ) -roa*/
  if (zone_table[zone].seasons[0].avg_day_temp > -999)
  {
    zone_table[zone].current_gtemp = zone_table[zone].previous_gtemp =
	(global_weather.sunlight == SUN_RISE || 
	 global_weather.sunlight == SUN_LIGHT) ? 
        zone_table[zone].seasons[global_weather.season].avg_day_temp:
        zone_table[zone].seasons[global_weather.season].avg_night_temp;
  }
  zone_table[zone].has_rained = FALSE;
  zone_table[zone].hour_to_rain = number(0, 23);

  /* now do a natural reset on the zone */
  natural_reset(zone);
}

/* used for the recursive nature of objects in objects when adding the
   zone coms to the comlist string of a zone */
void add_obj_to_obj(obdata *obj, char *clist)
{
    obdata *ob;

    for (ob = obj; ob; ob = ob->next_content)
    {
      sprintf(buf, "P %d\n",GET_OBJ_VNUM(ob));
      str_cat(clist, buf, MAX_COMLIST_LENGTH, "z_olc.c");
      if (ob->contains)
      {
        str_cat(clist, "{\n", MAX_COMLIST_LENGTH, "z_olc.c");
        add_obj_to_obj(ob->contains, clist);
        str_cat(clist, "}\n", MAX_COMLIST_LENGTH, "z_olc.c");
      }
    }
}

/* used to add objects of a room to the comlist string of a zone */
void add_room_inventory(obdata *obj, char *clist, int room)
{
  obdata *ob = 0;

  for (ob = obj; ob; ob = ob->next_content)
  {
    sprintf(buf, "O %d %d\n",GET_OBJ_VNUM(ob), room);
    str_cat(clist, buf, MAX_COMLIST_LENGTH, "z_olc.c");
    if (ob->contains)
    {
      str_cat(clist, "{\n", MAX_COMLIST_LENGTH, "z_olc.c");
      add_obj_to_obj(ob->contains, clist);
      str_cat(clist, "}\n", MAX_COMLIST_LENGTH, "z_olc.c");
    }
  }
}

/* used to add a mobs equipment to the comlist string of a zone */
void add_mob_equip(chdata *ch, char *clist)
{
  int pos;

  for (pos = 0; pos < MAX_WEAR; pos++)
    if (EQ(ch, pos))
    {
      sprintf(buf, "E %d %d\n", GET_OBJ_VNUM(EQ(ch, pos)), pos);
      str_cat(clist, buf, MAX_COMLIST_LENGTH, "z_olc.c");
      if(EQ(ch, pos)->contains)
      {
	str_cat(clist, "{\n", MAX_COMLIST_LENGTH, "z_olc.c");
	add_obj_to_obj(EQ(ch, pos)->contains, clist);
	str_cat(clist, "}\n", MAX_COMLIST_LENGTH, "z_olc.c");
      }
    }
}

/* used to add a mobs inventory to the comlist string on a zone */
void add_mob_inventory(chdata *ch, char *clist)
{
  obdata *ob;

  for (ob = ch->carrying; ob; ob = ob->next_content)
  {
    sprintf(buf, "G %d\n",GET_OBJ_VNUM(ob));
    str_cat(clist, buf, MAX_COMLIST_LENGTH, "z_olc.c");
    if (ob->contains)
    {
      str_cat(clist, "{\n", MAX_COMLIST_LENGTH, "z_olc.c");
      add_obj_to_obj(ob->contains, clist);
      str_cat(clist, "}\n", MAX_COMLIST_LENGTH, "z_olc.c");
    }
  }
}

/* new roa zone command creation throws them into a string on the zone 
   data struct -Roa jtrhone */
// updated 1/22/98 -jtrhone
// do NOT save objs in zone file if it's a PLSHOPKEEP mob
// objs save for them in a seperate file
int create_roazone_cmds(int zone)
{
    zndata *z = &zone_table[zone];
    chdata *ch, *next_ch;
    int top;
    int r_room, room, door;
    int pos;
    char clist[MAX_COMLIST_LENGTH];  /* note: zone comlist cant go beyond this */
    BOOL isblock = FALSE;
    struct room_affect_type *raf;

    clist[0] = '\0';
    for (ch = character_list; ch; ch = ch->next)
    {
	next_ch = ch->next;
	if (IS_NPC(ch) && !INVALID_ROOM(ch->in_room) && world[ch->in_room].zone == zone)
	{
	    sprintf(buf, "M %d %d %d\n", mob_index[ch->nr].vnum, world[ch->in_room].number, 
                    mob_index[ch->nr].number);
	    str_cat(clist, buf, MAX_COMLIST_LENGTH, "z_olc.c");

	    for (isblock = FALSE, pos = 0; pos < MAX_WEAR; pos++)
	     if (EQ(ch, pos))
		isblock = TRUE;

	     if (isblock) /* do the mobs equipment */
		add_mob_equip(ch, clist);

	     if (ch->carrying && !MOB_FLAGGED(ch, MOB_PLSHOPKEEP))
		add_mob_inventory(ch, clist);
	}
    }

    top = zone*100+99;
    for (room = zone*100; room <= top; room++)
    {
      trap *t;
      rmdata *r;

      if ((r_room = real_room(room)) <= NOWHERE)
	continue;

      r = &world[r_room];

      /* do the recursive room object add */
      if (r->contents)
	add_room_inventory(r->contents, clist, room);

      // add any room affects (NOTE: WILL DEFAULT TO LEVEL IMPL/2 without caster)
      // 4/28/98 -jtrhone
      for (raf = r->room_affects; raf; raf=raf->next)
      {
        sprintf(buf, "R %d %d %d %ld\n", room, raf->spell, raf->duration, raf->bitvector); 
        str_cat(clist, buf, MAX_COMLIST_LENGTH, "z_olc.c");
      }

      // direction of -1 means room trap  4/26/98 -jtrhone
      if ((t = TRAPS(r)))
      {
        sprintf(buf, "T %d -1 %d %d %d %d\n", room, /* door, */ t->type, t->level, t->bitv, t->timer); 
        str_cat(clist, buf, MAX_COMLIST_LENGTH, "z_olc.c");
      }

      for (door = 0; door < NUM_OF_DIRS; door++)
        if (DIR(r_room, door))
        {
          sprintf(buf, "D %d %d %d\n", room, door, DIR(r_room, door)->exinfo); 
          str_cat(clist, buf, MAX_COMLIST_LENGTH, "z_olc.c");

          // if its trapped, write some basic info out  4/26/98 -jtrhone
          if ((t = TRAPS(DIR(r_room, door))))
          {
            sprintf(buf, "T %d %d %d %d %d %d\n", room, door, t->type, t->level, t->bitv, t->timer); 
            str_cat(clist, buf, MAX_COMLIST_LENGTH, "z_olc.c");
          }
        }
    }

  str_cat(clist, "$\n~\n", MAX_COMLIST_LENGTH, "z_olc.c");

  FREENULL(z->comlist);
  z->comlist = STR_DUP(clist);

  return 0;
}

/* new zone saving technique, RoA jtrhone */
int save_roazone_cmds(int zone)
{
    zndata *z = &zone_table[zone];
    char filename[40];
    FILE *zf;
    int i;
    
    if (!z->comlist)
    {
	sprintf(buf, "SYSNOTE: Zone #%d lacks comlist.",zone);
	mudlog(buf, BRF, LEV_IMM, FALSE);
    }

    sprintf(filename, "world/zon/%d.zonroa", zone);
    if (!(zf = fopen(filename, "w")))
    {
      sprintf(buf, "SYSERR: could not open %d.zonroa for writing.", zone);
      mudlog(buf, BRF, LEV_IMM, FALSE);
      return FALSE;
    }
    fprintf(zf, "#%d\n", z->number);
    fprintf(zf, "%s~\n", z->name);
    fprintf(zf, "%d %d %d\n", z->top, z->lifespan, z->reset_mode);
    fprintf(zf, "%d\n",z->bitvector);

    fprintf(zf, "@ %d %d\n", z->music_timer, z->wav_timer);
    if (z->sound_file)
      fprintf(zf, "%s~\n", z->sound_file);
    else
      fprintf(zf, "~\n");

    /* now we gotta write the zone weather -roa */
    for (i = 0; i < 4; i++)
      fprintf(zf, "W%d %d %d %d %d %d %d\n", i,
	      z->seasons[i].avg_day_temp,
	      z->seasons[i].avg_day_temp_var,
	      z->seasons[i].avg_night_temp,
	      z->seasons[i].avg_night_temp_var,
	      z->seasons[i].precip_percentage,
	      z->seasons[i].atmosphere_type);

    fprintf(zf, "W %d %d %d %d %d %d %d %d\n",
	    z->current_status, z->previous_status,
	    z->current_gtemp, z->previous_gtemp,
	    z->current_atemp, z->previous_atemp,
	    z->accum_type, z->accum);

    fprintf(zf, "*\n");
    for (i = 0; i < 4; i++)
    {
      if (z->seasons[i].sunrise)
      {
	killr(strcpy(buf, z->seasons[i].sunrise));
	fprintf(zf, "%s~\n",z->seasons[i].sunrise);
      }
      else
	fprintf(zf, "~\n");

      if (z->seasons[i].daytime)
      {
	killr(strcpy(buf, z->seasons[i].daytime));
	fprintf(zf, "%s~\n",z->seasons[i].daytime);
      }
      else
	fprintf(zf, "~\n");

      if (z->seasons[i].sunset)
      {
	killr(strcpy(buf, z->seasons[i].sunset));
	fprintf(zf, "%s~\n",z->seasons[i].sunset);
      }
      else
	fprintf(zf, "~\n");

      if (z->seasons[i].nighttime)
      {
	killr(strcpy(buf, z->seasons[i].nighttime));
	fprintf(zf, "%s~\n",z->seasons[i].nighttime);
      }
      else
	fprintf(zf, "~\n");
    }

    fprintf(zf, "%s~",z->comlist);
    fclose(zf);
    return TRUE;
}

// open a zone to the general public, removes closed flag basically
ACMD(do_zopen)
{
  if IS_NPC(ch) 
  {
    send_to_char("Oh no!  None of that stuff!\n\r", ch);
    return;
  }

  if (!ch->pc_specials->saved.zone_locked)
  {
    send_to_char("You don't have any zones locked.\n\r", ch);
    return;
  }

  REMOVE_BIT(ZONE_FLAGS(ch->pc_specials->saved.zone_locked), Z_CLOSED);
  send_to_char("Zone opened.\n\r",ch);
}

// close a zone, under construction, normal players not allowed...-roa
ACMD(do_zclose)
{
  if IS_NPC(ch) 
  {
    send_to_char("Oh no!  None of that stuff!\n\r", ch);
    return;
  }

  if (!ch->pc_specials->saved.zone_locked)
  {
    send_to_char("You don't have any zones locked.\n\r", ch);
    return;
  }

  SET_BIT(ZONE_FLAGS(ch->pc_specials->saved.zone_locked), Z_CLOSED);
  send_to_char("Zone closed.\n\r",ch);
}

// open a slot in the zone_table array, makes zone REAL_ZONE, edittable now
ACMD(do_zcreate)
{
  FILE *f;
  char filename[40];
  int zone, i;
    
  if IS_NPC(ch) 
  {
    send_to_char("Oh no!  None of that stuff!\n\r", ch);
    return;
  }

  if (!*argument)
  {
    send_to_char("What zone would you like to create?\n\r", ch);
    return;
  }
    
  zone = atoi(argument);
  if (REAL_ZONE(zone))
  {
    send_to_char("That zone already exists.\n\r",ch);
    return;
  }

  if (zone < 0 || zone >= 255)
  {
    send_to_char("Invalid zone number.\n\r", ch);
    return;
  }

  if (!olc_perms(ch, LEV_IMPL, zone))
    return;

  zone_table[zone].top        = zone * 100 + 99;
  zone_table[zone].lifespan   = 0;
  zone_table[zone].reset_mode = 0;
  zone_table[zone].age        = 0;
  zone_table[zone].number     = zone;
  zone_table[zone].name       = STR_DUP("unnamed zone");
  zone_table[zone].bitvector  = 0;
  zone_table[zone].seasons[0].avg_day_temp = -999;
  zone_table[zone].seasons[1].avg_day_temp = -999;
  zone_table[zone].seasons[2].avg_day_temp = -999;
  zone_table[zone].seasons[3].avg_day_temp = -999;
  SET_BIT(ZONE_FLAGS(zone), Z_CLOSED);

  create_roazone_cmds(zone);
  save_roazone_cmds(zone);

  /* add it to the index, by rewriting the whole index again */
  sprintf(filename, "%s/%s", ZON_PREFIX, INDEX_FILE);
  f = fopen(filename, "w");

  for (i = 0; i < NUM_ZONES; i++)
    if (REAL_ZONE(i))
      fprintf(f, "%d.zon\n", i);

  fprintf(f, "$\n");
  fclose(f);

  // now... zlock and zun -save to assure that ALL files are written
  // 1/28/98  -jtrhone
  sprintf(buf, "%d", zone);
  do_zlock(ch, buf, 0, 0); 
  do_zunlock(ch, " -save", 0, 0); 
}

ACMD(do_equip)
{
  chdata *vict;
  dsdata *desc;
  long affected_by;
  char name[80];
    
  if (IS_NPC(ch) || ch->in_room == NOWHERE)
  {
    send_to_char("Oh no!  None of that stuff!\n\r", ch);
    return;
  }

  if (!ch->pc_specials->saved.zone_locked)
  {
    send_to_char("You don't have any zones locked.\n\r", ch);
    return;
  }

  if (GET_LEVEL (ch) < LEV_IMPL &&
      world[ch->in_room].zone != ch->pc_specials->saved.zone_locked)
  {
    send_to_char("You must equip mobs in a locked zone.\n\r", ch);
    return;
  }
    
  if (!*argument)
  {
    send_to_char("Force who to wear?\n\r", ch);
    return;
  }
    
    argument = one_argument(argument, name);
    vict = get_char_room_vis(ch, name);
    if (!vict)
    {
	send_to_char("No such mob in this room.\n\r", ch);
	return;
    }
    
    if (IS_PC(vict))
    {
	send_to_char("You can't equip a player character.\n\r", ch);
	return;
    }

    send_to_char("Output from the mob:\n\r", ch);
    desc = vict->desc;
    vict->desc = ch->desc;
    affected_by = vict->specials.affected_by;
    vict->specials.affected_by |= AFF_INFRARED;
    vict->specials.affected_by &= ~AFF_BLIND;

    do_wear(vict, argument, 0, 0);

    vict->desc = desc;
    vict->specials.affected_by = affected_by;
}

ACMD(do_forcewield)
{
    chdata *vict;
    dsdata *desc;
    long affected_by;
    char name[80];
    
    if (IS_NPC(ch) || ch->in_room == NOWHERE)
    {
	send_to_char("Oh no!  None of that stuff!\n\r", ch);
	return;
    }


    if (!ch->pc_specials->saved.zone_locked)
    {
	send_to_char("You don't have any zones locked.\n\r", ch);
	return;
    }

    if (GET_LEVEL (ch) < LEV_IMPL &&
	(ch->pc_specials->saved.zone_locked == 0 || 
	 ch->pc_specials->saved.zone_locked < ch->pc_specials->saved.olc_min_zone ||
	 ch->pc_specials->saved.zone_locked > ch->pc_specials->saved.olc_max_zone ||
	 world[ch->in_room].zone != ch->pc_specials->saved.zone_locked))
    {
	send_to_char("You don't have privileges to edit that zone.\n\r", ch);
	return;
    }
    
    if (!*argument)
    {
	send_to_char("Force who to wield?\n\r", ch);
	return;
    }
    
    argument = one_argument(argument, name);
    vict = get_char_room_vis(ch, name);
    if (!vict)
    {
	send_to_char("No such mob in this room.\n\r", ch);
	return;
    }
    
    if (IS_PC(vict))
    {
	send_to_char("You can't equip a player character.\n\r", ch);
	return;
    }

    send_to_char("Output from the mob:\n\r", ch);
    desc = vict->desc;
    vict->desc = ch->desc;
    affected_by = vict->specials.affected_by;
    vict->specials.affected_by |= AFF_INFRARED;
    vict->specials.affected_by &= ~AFF_BLIND;

    do_wield(vict, argument, 0, 0);

    vict->desc = desc;
    vict->specials.affected_by = affected_by;
}

ACMD(do_forcehold)
{
    chdata *vict;
    dsdata *desc;
    long affected_by;
    char name[80];
    
    if (IS_NPC(ch) || ch->in_room == NOWHERE)
    {
	send_to_char("Oh no!  None of that stuff!\n\r", ch);
	return;
    }

    if (!ch->pc_specials->saved.zone_locked)
    {
	send_to_char("You don't have any zones locked.\n\r", ch);
	return;
    }

    if (GET_LEVEL (ch) < LEV_IMPL &&
	(ch->pc_specials->saved.zone_locked == 0 || 
	 ch->pc_specials->saved.zone_locked < ch->pc_specials->saved.olc_min_zone ||
	 ch->pc_specials->saved.zone_locked > ch->pc_specials->saved.olc_max_zone ||
	 world[ch->in_room].zone != ch->pc_specials->saved.zone_locked))
    {
	send_to_char("You don't have privileges to edit that zone.\n\r", ch);
	return;
    }
    
    if (!*argument)
    {
	send_to_char("Force who to wield?\n\r", ch);
	return;
    }
    
    argument = one_argument(argument, name);
    vict = get_char_room_vis(ch, name);
    if (!vict)
    {
	send_to_char("No such mob in this room.\n\r", ch);
	return;
    }
    
    if (IS_PC(vict))
    {
	send_to_char("You can't equip a player character.\n\r", ch);
	return;
    }

    send_to_char("Output from the mob:\n\r", ch);
    desc = vict->desc;
    vict->desc = ch->desc;
    affected_by = vict->specials.affected_by;
    vict->specials.affected_by |= AFF_INFRARED;
    vict->specials.affected_by &= ~AFF_BLIND;

    do_grab(vict, argument, 0, 0);

    vict->desc = desc;
    vict->specials.affected_by = affected_by;
}


/***************************************************************
 Zone editting menus	RoA   JtRhone
 
 The following code provides a menu editting system of zone statistics.
 It's similar to the r/m/oedit menuing system.  
 Eliminates the single functions for lifespan/zname/zone flags/etc.
 10/6/96 - added weather support to this file, writes data out
	   and new submenus from zedit_top allow for customization -roa
 ***************************************************************/
ACMD(do_zedit)
{
    char buf[80];
    int znum;
    
    if (IS_NPC(ch))
	return;

    one_argument(argument, buf);

    if (!*buf && ch->in_room > NOWHERE)
      znum = world[ch->in_room].zone;
    else
      znum = atoi(buf);

    if (znum <= 0)
    {
	send_to_char("usage: ZEDIT <zone nr>\n\r", ch);
	return;
    }
    
    if (!REAL_ZONE(znum))
    {
      send_to_char("That zone does not exist.\n\r",ch);
      return;
    }

    if (!olc_perms(ch, LEV_CIMP, znum))
      return;

    if (!ZONE_FLAGGED(znum, Z_LOCKED) && GET_LEVEL(ch) < LEV_CIMP) 
    {
       send_to_char("You must ZLOCK that zone before you can edit it.\n\r",ch);
       return;
    }

    CREATE(ch->pc_specials->zone_editted, zndata, 1);
    *ch->pc_specials->zone_editted = zone_table[znum];

    SET_BIT(PLR_FLAGS(ch), PLR_BUILDING);

    MENU_DEPTH(ch) = 0;
    menu_jump(ch, zedit_top_menu);
}

/* add extra menu for viewing the zone comlist data RoA jtrhone*/
void zedit_view_comlist_menu(chdata *ch, char *input_str)
{
    char buf[20000];
    char *p;
    int field;
    zndata *z = ch->pc_specials->zone_editted;
    
    if (!input_str)
    {
        menu_title_send("ZoneEdit Comlist Viewing Menu", ch);
        if (strlen(z->comlist) < MAX_STRING_LENGTH - 10)
	  sprintf(buf, "%s\n\r",z->comlist);
	else
	  sprintf(buf, "Comlist TOO long...\n\r");
	page_string(ch->desc, buf, TRUE);

	MENU_PROMPT(ch) = "** Enter 0 for main zedit menu ** ";
	return;
    }

    strcpy(buf, input_str);
    p = strtok(buf, " 	\n\r");
    if (p)
	field = atoi(p);
    else
	field = 0;

    switch (field)
    {
      case 0:
	menu_back(ch);
	return;
	break;

      default:
	send_to_char("That field cannot be changed.\n\r", ch);
	break;
    }
}

ROA_MENU(zedit_weather_mesg_menu)
{
  char buf[MAX_STRING_LENGTH];
  char *p;
  int field;
  zndata *z = ch->pc_specials->zone_editted;

  if (!input_str)
  {
    menu_title_send("ZoneEdit Weather Message Menu", ch);
    sprintf(buf, " 1.) %%2Spring Sunrise%%0: %s\n\r",z->seasons[0].sunrise);S2C();
    sprintf(buf, " 2.) %%2Spring Daytime%%0: %s\n\r",z->seasons[0].daytime);S2C();
    sprintf(buf, " 3.) %%2Spring Sunset%%0: %s\n\r",z->seasons[0].sunset);S2C();
    sprintf(buf, " 4.) %%2Spring Nighttime%%0: %s\n\r",z->seasons[0].nighttime);S2C();

    sprintf(buf, " 5.) %%3%%BSummer Sunrise%%0: %s\n\r",z->seasons[1].sunrise);S2C();
    sprintf(buf, " 6.) %%3%%BSummer Daytime%%0: %s\n\r",z->seasons[1].daytime);S2C();
    sprintf(buf, " 7.) %%3%%BSummer Sunset%%0: %s\n\r",z->seasons[1].sunset);S2C();
    sprintf(buf, " 8.) %%3%%BSummer Nighttime%%0: %s\n\r",z->seasons[1].nighttime);S2C();

    sprintf(buf, " 9.) %%3Autumn Sunrise%%0: %s\n\r",z->seasons[2].sunrise);S2C();
    sprintf(buf, "10.) %%3Autumn Daytime%%0: %s\n\r",z->seasons[2].daytime);S2C();
    sprintf(buf, "11.) %%3Autumn Sunset%%0: %s\n\r",z->seasons[2].sunset);S2C();
    sprintf(buf, "12.) %%3Autumn Nighttime%%0: %s\n\r",z->seasons[2].nighttime);S2C();

    sprintf(buf, "13.) %%BWinter Sunrise%%0: %s\n\r",z->seasons[3].sunrise);S2C();
    sprintf(buf, "14.) %%BWinter Daytime%%0: %s\n\r",z->seasons[3].daytime);S2C();
    sprintf(buf, "15.) %%BWinter Sunset%%0: %s\n\r",z->seasons[3].sunset);S2C();
    sprintf(buf, "16.) %%BWinter Nighttime%%0: %s\n\r",z->seasons[3].nighttime);S2C();
    MENU_PROMPT(ch) = "Enter field number to change or 0 to end: ";
    return;
  }

  strcpy(buf, input_str);
  p = strtok(buf, " 	\n\r");
  if (p)
	field = atoi(p);
  else
	field = 0;

  switch (field)
  {
    case 0:
	menu_back(ch);
	return;
	break;

    case 1:
	do_string_arg(ch, "Enter spring sunrise mesg:\n\r", &z->seasons[0].sunrise, "");
 	break;
    case 2:
	do_string_arg(ch, "Enter spring daytime mesg:\n\r", &z->seasons[0].daytime, "");
 	break;
    case 3:
	do_string_arg(ch, "Enter spring sunset mesg:\n\r", &z->seasons[0].sunset, "");
 	break;
    case 4:
	do_string_arg(ch, "Enter spring nighttime mesg:\n\r", &z->seasons[0].nighttime, "");
 	break;

    case 5:
	do_string_arg(ch, "Enter summer sunrise mesg:\n\r", &z->seasons[1].sunrise, "");
 	break;
    case 6:
	do_string_arg(ch, "Enter summer daytime mesg:\n\r", &z->seasons[1].daytime, "");
 	break;
    case 7:
	do_string_arg(ch, "Enter summer sunset mesg:\n\r", &z->seasons[1].sunset, "");
 	break;
    case 8:
	do_string_arg(ch, "Enter summer nighttime mesg:\n\r", &z->seasons[1].nighttime, "");
 	break;

    case 9:
	do_string_arg(ch, "Enter autumn sunrise mesg:\n\r", &z->seasons[2].sunrise, "");
 	break;
    case 10:
	do_string_arg(ch, "Enter autumn daytime mesg:\n\r", &z->seasons[2].daytime, "");
 	break;
    case 11:
	do_string_arg(ch, "Enter autumn sunset mesg:\n\r", &z->seasons[2].sunset, "");
 	break;
    case 12:
	do_string_arg(ch, "Enter autumn nighttime mesg:\n\r", &z->seasons[2].nighttime, "");
 	break;

    case 13:
	do_string_arg(ch, "Enter winter sunrise mesg:\n\r", &z->seasons[3].sunrise, "");
 	break;
    case 14:
	do_string_arg(ch, "Enter winter daytime mesg:\n\r", &z->seasons[3].daytime, "");
 	break;
    case 15:
	do_string_arg(ch, "Enter winter sunset mesg:\n\r", &z->seasons[3].sunset, "");
 	break;
    case 16:
	do_string_arg(ch, "Enter winter nighttime mesg:\n\r", &z->seasons[3].nighttime, "");
 	break;

    default:
	send_to_char("That field cannot be changed.\n\r", ch);
	break;
  }
}

/* the main weather menu called from zedit_top -roa */
ROA_MENU(zedit_weather_menu)
{
    char buf[MAX_STRING_LENGTH];
    char *p;
    int field;
    zndata *z = ch->pc_specials->zone_editted;
    
    if (!input_str)
    {
        menu_title_send("ZoneEdit Weather Menu", ch);
	send_to_char("%B%6-=-=-=-%0 %2Spring%0 %B%6-=-=-=-%0\n\r",ch);
	sprintf(buf, "1.) %%6Avg. Day Temp%%0: %d deg,  ",
		z->seasons[0].avg_day_temp);
	S2C();
	sprintf(buf, "2.) %%6Avg. Day Temp Variance%%0: %d deg.\n\r",
		z->seasons[0].avg_day_temp_var);
	S2C();
	sprintf(buf, "3.) %%6Avg. Night Temp%%0: %d deg,  ",
		z->seasons[0].avg_night_temp);
	S2C();
	sprintf(buf, "4.) %%6Avg. Night Temp Variance%%0: %d deg.\n\r",
		z->seasons[0].avg_night_temp_var);
	S2C();
	sprintf(buf, "5.) %%6Avg. Precip Percentage%%0: %d percent.\n\r",
		z->seasons[0].precip_percentage);
	S2C();
        sprinttype(z->seasons[0].atmosphere_type, atmos_names, buf2);
	sprintf(buf, "6.) %%6Atmosphere_type%%0: %s.\n\r",buf2);
	S2C();

	send_to_char("%B%6-=-=-=-%0 %B%1Summer%0 %B%6-=-=-=-%0\n\r",ch);
	sprintf(buf, "7.) %%6Avg. Day Temp%%0: %d deg,  ",
		z->seasons[1].avg_day_temp);
	S2C();
	sprintf(buf, "8.) %%6Avg. Day Temp Variance%%0: %d deg.\n\r",
		z->seasons[1].avg_day_temp_var);
	S2C();
	sprintf(buf, "9.) %%6Avg. Night Temp%%0: %d deg,  ",
		z->seasons[1].avg_night_temp);
	S2C();
	sprintf(buf, "10.) %%6Avg. Night Temp Variance%%0: %d deg.\n\r",
		z->seasons[1].avg_night_temp_var);
	S2C();
	sprintf(buf, "11.) %%6Avg. Precip Percentage%%0: %d percent.\n\r",
		z->seasons[1].precip_percentage);
	S2C();
        sprinttype(z->seasons[1].atmosphere_type, atmos_names, buf2);
	sprintf(buf, "12.) %%6Atmosphere_type%%0: %s.\n\r",buf2);
	S2C();

	send_to_char("%B%6-=-=-=-%0 %3Autumn%0 %B%6-=-=-=-%0\n\r",ch);
	sprintf(buf, "13.) %%6Avg. Day Temp%%0: %d deg,  ",
		z->seasons[2].avg_day_temp);
	S2C();
	sprintf(buf, "14.) %%6Avg. Day Temp Variance%%0: %d deg.\n\r",
		z->seasons[2].avg_day_temp_var);
	S2C();
	sprintf(buf, "15.) %%6Avg. Night Temp%%0: %d deg,  ",
		z->seasons[2].avg_night_temp);
	S2C();
	sprintf(buf, "16.) %%6Avg. Night Temp Variance%%0: %d deg.\n\r",
		z->seasons[2].avg_night_temp_var);
	S2C();
	sprintf(buf, "17.) %%6Avg. Precip Percentage%%0: %d percent.\n\r",
		z->seasons[2].precip_percentage);
	S2C();
        sprinttype(z->seasons[2].atmosphere_type, atmos_names, buf2);
	sprintf(buf, "18.) %%6Atmosphere_type%%0: %s.\n\r",buf2);
	S2C();

	send_to_char("%B%6-=-=-=-%0 %BWinter%0 %B%6-=-=-=-%0\n\r",ch);
	sprintf(buf, "19.) %%6Avg. Day Temp%%0: %d deg,  ",
		z->seasons[3].avg_day_temp);
	S2C();
	sprintf(buf, "20.) %%6Avg. Day Temp Variance%%0: %d deg.\n\r",
		z->seasons[3].avg_day_temp_var);
	S2C();
	sprintf(buf, "21.) %%6Avg. Night Temp%%0: %d deg,  ",
		z->seasons[3].avg_night_temp);
	S2C();
	sprintf(buf, "22.) %%6Avg. Night Temp Variance%%0: %d deg.\n\r",
		z->seasons[3].avg_night_temp_var);
	S2C();
	sprintf(buf, "23.) %%6Avg. Precip Percentage%%0: %d percent.\n\r",
		z->seasons[3].precip_percentage);
	S2C();
        sprinttype(z->seasons[3].atmosphere_type, atmos_names, buf2);
	sprintf(buf, "24.) %%6Atmosphere_type%%0: %s.\n\r",buf2);
	S2C();

	MENU_PROMPT(ch) = "Enter field number to change or 0 to end: ";
        return;
    }

    strcpy(buf, input_str);
    p = strtok(buf, " 	\n\r");
    if (p)
	field = atoi(p);
    else
	field = 0;

    switch (field)
    {
      case 0:
	menu_back(ch);
	return;
	break;

	/* spring */
      case 1:
	GET_INTEGER_ARG(ch, "Enter Avg Spring Daytime Temp: ", 
                        z->seasons[0].avg_day_temp, -999, 999);
        break;
      case 2:
	GET_INTEGER_ARG(ch, "Enter Avg Spring Daytime Temp Variance: ", 
                        z->seasons[0].avg_day_temp_var, 0, 500);
        break;
      case 3:
	GET_INTEGER_ARG(ch, "Enter Avg Spring Nighttime Temp: ", 
                        z->seasons[0].avg_night_temp, -999, 999);
        break;
      case 4:
	GET_INTEGER_ARG(ch, "Enter Avg Spring Nighttime Temp Variance: ", 
                        z->seasons[0].avg_night_temp_var, 0, 500);
        break;
      case 5:
	GET_INTEGER_ARG(ch, "Enter Avg Spring Precip Percentage (0-100): ", 
                        z->seasons[0].precip_percentage, 0, 100);
        break;
      case 6:
	get_integer_list(ch, "Enter Atmosphere type: ",
			 &z->seasons[0].atmosphere_type,
			 sizeof(z->seasons[0].atmosphere_type),
			 atmos_names);
	break;

	/* summer */
      case 7:
	GET_INTEGER_ARG(ch, "Enter Avg Summer Daytime Temp: ", 
                        z->seasons[1].avg_day_temp, -999, 999);
        break;
      case 8:
	GET_INTEGER_ARG(ch, "Enter Avg Summer Daytime Temp Variance: ", 
                        z->seasons[1].avg_day_temp_var, 0, 500);
        break;
      case 9:
	GET_INTEGER_ARG(ch, "Enter Avg Summer Nighttime Temp: ", 
                        z->seasons[1].avg_night_temp, -999, 999);
        break;
      case 10:
	GET_INTEGER_ARG(ch, "Enter Avg Summer Nighttime Temp Variance: ", 
                        z->seasons[1].avg_night_temp_var, 0, 500);
        break;
      case 11:
	GET_INTEGER_ARG(ch, "Enter Avg Summer Precip Percentage (0-100): ", 
                        z->seasons[1].precip_percentage, 0, 100);
        break;
      case 12:
	get_integer_list(ch, "Enter Atmosphere type: ",
			 &z->seasons[1].atmosphere_type,
			 sizeof(z->seasons[1].atmosphere_type),
			 atmos_names);
	break;

	/* autumn */
      case 13:
	GET_INTEGER_ARG(ch, "Enter Avg Autumn Daytime Temp: ", 
                        z->seasons[2].avg_day_temp, -999, 999);
        break;
      case 14:
	GET_INTEGER_ARG(ch, "Enter Avg Autumn Daytime Temp Variance: ", 
                        z->seasons[2].avg_day_temp_var, 0, 500);
        break;
      case 15:
	GET_INTEGER_ARG(ch, "Enter Avg Autumn Nighttime Temp: ", 
                        z->seasons[2].avg_night_temp, -999, 999);
        break;
      case 16:
	GET_INTEGER_ARG(ch, "Enter Avg Autumn Nighttime Temp Variance: ", 
                        z->seasons[2].avg_night_temp_var, 0, 500);
        break;
      case 17:
	GET_INTEGER_ARG(ch, "Enter Avg Autumn Precip Percentage (0-100): ", 
                        z->seasons[2].precip_percentage, 0, 100);
        break;
      case 18:
	get_integer_list(ch, "Enter Atmosphere type: ",
			 &z->seasons[2].atmosphere_type,
			 sizeof(z->seasons[2].atmosphere_type),
			 atmos_names);
	break;

	/* winter */
      case 19:
	GET_INTEGER_ARG(ch, "Enter Avg Winter Daytime Temp: ", 
                        z->seasons[3].avg_day_temp, -999, 999);
        break;
      case 20:
	GET_INTEGER_ARG(ch, "Enter Avg Winter Daytime Temp Variance: ", 
                        z->seasons[3].avg_day_temp_var, 0, 500);
        break;
      case 21:
	GET_INTEGER_ARG(ch, "Enter Avg Winter Nighttime Temp: ", 
                        z->seasons[3].avg_night_temp, -999, 999);
        break;
      case 22:
	GET_INTEGER_ARG(ch, "Enter Avg Winter Nighttime Temp Variance: ", 
                        z->seasons[3].avg_night_temp_var, 0, 500);
        break;
      case 23:
	GET_INTEGER_ARG(ch, "Enter Avg Winter Precip Percentage (0-100): ", 
                        z->seasons[3].precip_percentage, 0, 100);
        break;
      case 24:
	get_integer_list(ch, "Enter Atmosphere type: ",
			 &z->seasons[3].atmosphere_type,
			 sizeof(z->seasons[3].atmosphere_type),
			 atmos_names);
	break;
	
      default:
	send_to_char("That field cannot be changed.\n\r", ch);
	break;
    }
}

/* the zedit's top menu, where all other submenus are called from -roa */
void zedit_top_menu(chdata *ch, char *input_str)
{
    char buf[MAX_STRING_LENGTH];
    char buf2[MAX_STRING_LENGTH];
    char *p;
    int field;
    zndata *z = ch->pc_specials->zone_editted;
    
    if (!input_str)
    {
        menu_title_send("ZoneEdit Main Menu", ch);
	sprintf(buf, "\n\r%%6Zone Number%%0: %d  %%6Zone top%%0: %d  %%6Lock_id%%0: %d\n\n\r",
		z->number, z->top, z->locked_id);
	S2C();
	sprintf(buf, " 1.) %%6Name%%0      : %s\n\r", z->name); 
	S2C();
	sprintf(buf, " 2.) %%6Lifespan%%0  : %d ticks\n\r", z->lifespan);
	S2C();
	sprintf(buf, " 3.) %%6Reset Mode%%0: %d ",z->reset_mode);
	switch(z->reset_mode){
	  case 1: strcat(buf, "(Reset if no PCs within)\n\r"); break;
	  case 2: strcat(buf, "(Reset regardless)\n\r");       break;
	  default: strcat(buf, "(Does not age or reset)\n\r"); break;
	}
	S2C();
	sprintbit(z->bitvector, zone_bits, buf2);
	sprintf(buf, " 4.) %%6ZoneFlags%%0 : %%5%s%%0\n\r", buf2); S2C();
  	send_to_char(" 5.) %6Weather Data Menu...%0\n\r",ch);
  	send_to_char(" 6.) %6Weather Message Menu...%0\n\r",ch);

	sprintf(buf, " 7.) %%6Sound File%%0  : %s\n\r", z->sound_file);
	S2C();
	sprintf(buf, " 8.) %%6Sound replay timer%%0  : %d (qticks)\n\r", z->music_timer);
	S2C();

  	send_to_char("10.) %6Comlist Viewing Menu...%0\n\r",ch);
	send_to_char("\n\r", ch);
	MENU_PROMPT(ch) = "Enter field number to change or 0 to end: ";
	return;
    }

    strcpy(buf, input_str);
    p = strtok(buf, " 	\n\r");
    if (p)
	field = atoi(p);
    else
	field = 0;

    switch (field)
    {
      case 0:
	menu_jump(ch, zedit_confirm_quit);
	break;

      case 1:
	do_string_arg(ch, "Enter zone name:\n\r", &z->name, "");
	break;
	
      case 2:
	GET_INTEGER_ARG(ch, "Enter zone lifespan in ticks: ", z->lifespan, 0, 999);
        break;

      case 3:
	GET_INTEGER_ARG(ch, "Enter zone reset mode (0, 1, 2): ", z->reset_mode, 0, 2);
        break;

      case 4:
	toggle_menu(ch, "Enter zone bit to toggle: ", &z->bitvector, zone_bits);
	break;

      case 5:
	menu_push(ch);
	MENU_RETURN(ch) = 0;
	MENU_HANDLER_ARG(ch) = (void *) 0;
	menu_jump(ch, zedit_weather_menu);
	break;

      case 6:
	menu_push(ch);
	MENU_RETURN(ch) = 0;
	MENU_HANDLER_ARG(ch) = (void *) 0;
	menu_jump(ch, zedit_weather_mesg_menu);
	break;

      case 7:
	do_string_arg(ch, "Enter zone sound file:\n\r", &z->sound_file, "");
	break;

      case 8:
	GET_INTEGER_ARG(ch, "Enter sound replay timer (-1 for no replay): ", 
                        z->music_timer, -1, 32000);
        break;

      case 10: 
	menu_push(ch);
	MENU_RETURN(ch) = 0;
	MENU_HANDLER_ARG(ch) = (void *) 0;
	menu_jump(ch, zedit_view_comlist_menu);
	break;

      default:
	send_to_char("That field cannot be changed.\n\r", ch);
	break;
    }
}

void zedit_confirm_quit(chdata *ch, char *input_str)
{
    char buf[MAX_STRING_LENGTH];
    char *p;
    
    if (!input_str)
    {
	MENU_PROMPT(ch) = "Quit editting zone (yes/NO)? ";
	return;
    }    
    strcpy(buf, input_str);
    p = strtok(buf, " 	\n\r");
    if (p && strncasecmp("yes", p, strlen(p)) == 0)
	menu_jump(ch, zedit_confirm_save);
    else
	menu_jump(ch, zedit_top_menu);
}

void zedit_confirm_save(chdata *ch, char *input_str)
{
    char buf[MAX_STRING_LENGTH];
    zndata *z = ch->pc_specials->zone_editted;
    char *p;
  
    if (!input_str)
    {
	MENU_PROMPT(ch) = "Save editted zone (YES/no)? ";
	return;
    }
    strcpy(buf, input_str);
    p = strtok(buf, " 	\n\r");
    if (!p || strncasecmp("no", p, strlen(p)) != 0)
    {
      sprintf(buf, "IMMUPD: %s editted zone %d", GET_NAME(ch), z->number);
      mudlog(buf, BRF, GET_LEVEL(ch), TRUE);
      zone_table[z->number] = *z;
    }
    free(ch->pc_specials->zone_editted);
    ch->pc_specials->zone_editted = NULL;
    MENU_PROMPT(ch) = NULL;
    MENU_HANDLER(ch) = NULL;
    MENU_DEPTH(ch) = 0;
    REMOVE_BIT(PLR_FLAGS(ch), PLR_BUILDING);
}

ROA_MENU(confirm_ipp_menu)
{
  char buf[MAX_STRING_LENGTH];
  char *p;

  if (!input_str)
  {
    MENU_PROMPT(ch) = "Accept Intellectual Property Policy (YES/no)? ";
    return;
  }

  strcpy(buf, input_str);
  p = strtok(buf, "     \n\r");
  if (!p || strncasecmp("no", p, strlen(p)) != 0)
  {
    send_to_char("IPP accepted, you may now zlock normally.\n\r",ch);
    SET_BIT(PLR2_FLAGS(ch), PLR2_IPP);
  }
  else
    send_to_char("IPP not accepted, you must accept it to build.\n\r",ch);

  MENU_PROMPT(ch) = NULL;
  MENU_HANDLER(ch) = NULL;
  MENU_DEPTH(ch) = 0;
}