AwakeMUD-0.8.18B/
AwakeMUD-0.8.18B/doc/
AwakeMUD-0.8.18B/lib/
AwakeMUD-0.8.18B/lib/etc/
AwakeMUD-0.8.18B/lib/etc/pfiles/
AwakeMUD-0.8.18B/lib/misc/
AwakeMUD-0.8.18B/lib/text/
AwakeMUD-0.8.18B/lib/text/help/
AwakeMUD-0.8.18B/lib/text/wizhelp/
AwakeMUD-0.8.18B/lib/veh/
AwakeMUD-0.8.18B/lib/world/
AwakeMUD-0.8.18B/lib/world/mob/
AwakeMUD-0.8.18B/lib/world/mtx/
AwakeMUD-0.8.18B/lib/world/qst/
AwakeMUD-0.8.18B/lib/world/shp/
AwakeMUD-0.8.18B/lib/world/veh/
/*
 * file: vedit.cc
 * author: Dunkelzahn
 * (c)2001 The AwakeMUD Consortium, Daniel Gelinske
 * purpose: vedit, vehicle editor addon
 * to AwakeOLC, a component of AwakeMUD
 * */

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

#include "structs.h"
#include "awake.h"
#include "constants.h"
#include "interpreter.h"
#include "comm.h"
#include "utils.h"
#include "db.h"
#include "dblist.h"
#include "screen.h"
#include "olc.h"
#include "memory.h"

#define VEH     d->edit_veh

extern class memoryClass *Mem;

void write_vehs_to_disk(int zone);

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

/* display main menu */
void vedit_disp_menu(struct descriptor_data * d)
{
  CLS(CH);
  send_to_char(CH, "Vehicle number: %s%d%s\r\n", CCCYN(CH, C_CMP), d->edit_number,
               CCNRM(CH, C_CMP));
  send_to_char(CH, "1) Vechile namelist: %s%s%s\r\n", CCCYN(CH, C_CMP),
               d->edit_veh->name, CCNRM(CH, C_CMP));
  send_to_char(CH, "2) Vehicle shortdesc: %s%s%s\r\n", CCCYN(CH, C_CMP),
               d->edit_veh->short_description, CCNRM(CH, C_CMP));
  send_to_char(CH, "3) Vehicle descript (Stationary): %s%s%s\r\n", CCCYN(CH, C_CMP),
               d->edit_veh->description, CCNRM(CH, C_CMP));
  send_to_char(CH, "4) Vehicle longdesc: \r\n%s\r\n",
               d->edit_veh->long_description ? d->edit_veh->long_description :
               "(not set)");
  send_to_char(CH, "5) Vehicle Inside Descript: \r\n%s\r\n",
               d->edit_veh->inside_description ? d->edit_veh->inside_description : "(not set)");
  send_to_char(CH, "6) Vehicle Inside Rear Descript: \r\n%s\r\n", 
               d->edit_veh->rear_description ? d->edit_veh->rear_description : "(not set)");
  send_to_char(CH, "7) Arrive text: ^c%s^n,  8) Leave text: ^c%s^n\r\n",
               d->edit_veh->arrive, d->edit_veh->leave);
  d->edit_veh->flags.PrintBits(buf1, MAX_STRING_LENGTH, veh_flag, NUM_VFLAGS);
  send_to_char(CH, "9) Flags: ^c%s^n\r\n", buf1);
  send_to_char(CH, "a) H(^c%d^n) Sp(^c%d^n) Acc(^c%d^n) B(^c%d^n) Ar(^c%d^n)\r\n",
               d->edit_veh->handling, d->edit_veh->speed, d->edit_veh->accel, d->edit_veh->body,
               d->edit_veh->armor);
  send_to_char(CH, "   Sig(^c%d^n) Au(^c%d^n) P(^c%d^n) Seat(^c%d/%d^n) Load(^c%d^n) Cost(^c%d^n)\r\n",
               d->edit_veh->sig, d->edit_veh->autonav, d->edit_veh->pilot, d->edit_veh->seating[1], d->edit_veh->seating[0],
               (int)d->edit_veh->load, d->edit_veh->cost);
  send_to_char(CH, "b) Type: ^C%s^n\r\n", veh_type[d->edit_veh->type]);
  send_to_char(CH, "c) Stock Engine: ^C%s^n\r\n", engine_type[d->edit_veh->engine]);
  send_to_char("q) Quit and save\r\n"
               "x) Exit and abort\r\n"
               "Enter your choice:\r\n", CH);
  d->edit_mode = VEDIT_MAIN_MENU;
}

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

void vedit_disp_att(struct descriptor_data * d)
{
  CLS(CH);
  send_to_char(CH, "1) Handling:  ^c%d^n\r\n", d->edit_veh->handling);
  send_to_char(CH, "2) Speed:  ^c%d^n\r\n", d->edit_veh->speed);
  send_to_char(CH, "3) Acceleration: ^c%d^n\r\n", d->edit_veh->accel);
  send_to_char(CH, "4) Body:  ^c%d^n\r\n", d->edit_veh->body);
  send_to_char(CH, "5) Armor:  ^c%d^n\r\n", d->edit_veh->armor);
  send_to_char(CH, "6) Signature:  ^c%d^n\r\n", d->edit_veh->sig);
  send_to_char(CH, "7) AutoNav:  ^c%d^n\r\n", d->edit_veh->autonav);
  send_to_char(CH, "8) Pilot:  ^c%d^n\r\n", d->edit_veh->pilot);
  send_to_char(CH, "9) Seating:  ^c%d/%d^n\r\n", d->edit_veh->seating[1], d->edit_veh->seating[0]);
  send_to_char(CH, "0) Load:  ^c%d^n\r\n", (int)d->edit_veh->load);
  send_to_char(CH, "a) Cost:  ^c%d^n\r\n", d->edit_veh->cost);
  send_to_char(CH, "q) Quit\r\n");
  send_to_char(CH, "\r\nEnter your choice:\r\n");
  d->edit_mode = VEDIT_ATT;
}

void vedit_disp_type(struct descriptor_data * d)
{
  CLS(CH);
  send_to_char(CH, "0) Drone\r\n");
  send_to_char(CH, "1) Car\r\n");
  send_to_char(CH, "2) Bike\r\n");
  send_to_char(CH, "3) Truck\r\n");
  send_to_char(CH, "4) Fixed Wing\r\n");
  send_to_char(CH, "5) Rotorcraft\r\n");
  send_to_char(CH, "6) Vector Thrust\r\n");
  send_to_char(CH, "7) Hovercraft\r\n");
  send_to_char(CH, "8) MotorBoat\r\n");
  send_to_char(CH, "9) Ship\r\n");
  send_to_char(CH, "a) Lighter Than Air\r\n");
  send_to_char(CH, "Enter your choice:\r\n");
  d->edit_mode = VEDIT_TYPE;
}

void vedit_disp_flag_menu(struct descriptor_data *d)
{
  CLS(CH);
  for (int x = 1; x < NUM_VFLAGS; x++)
    send_to_char(CH, "%d) %s\r\n", x, veh_flag[x]);
  d->edit_veh->flags.PrintBits(buf1, MAX_STRING_LENGTH,
                               veh_flag, NUM_VFLAGS);
  send_to_char(CH, "Vehicle Flags: ^c%s^n\r\nSelect Flag (q to quit): ", buf1);
  d->edit_mode = VEDIT_FLAGS;
}


void vedit_parse(struct descriptor_data * d, char *arg)
{
  int             number;
  int             veh_number;   /* the RNUM */
  switch (d->edit_mode)
  {

  case VEDIT_CONFIRM_EDIT:
    /* if player hits 'Y' then edit veh */
    switch (*arg) {
    case 'y':
    case 'Y':
      vedit_disp_menu(d);
      break;
    case 'n':
    case 'N':
      STATE(d) = CON_PLAYING;
      /* free up the editing vehicle */
      if (d->edit_veh)
        Mem->DeleteVehicle(d->edit_veh);
      d->edit_veh = NULL;
      d->edit_number = 0;
      PLR_FLAGS(d->character).RemoveBit(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 VEDIT_CONFIRM_EDIT */

  case VEDIT_CONFIRM_SAVESTRING:
    switch (*arg) {
    case 'y':
    case 'Y': {
        /* write to internal tables */
        veh_number = real_vehicle(d->edit_number);
        if (veh_number > 0) {
          /* we need to run through each and every vehicle currently in the
           * game to see which ones are pointing to this prototype */
          struct veh_data *i;
          struct veh_data *temp;
          /* if vehicle is pointing to this prototype, then we need to replace
           * with the new one */
          for (i = veh_list; i; i = i->next) {
            if (veh_number == i->veh_number) {
              temp = Mem->GetVehicle();
              *temp = *i;
              *i = *d->edit_veh;
              /* copy game-time dependent vars over */
              i->in_room = temp->in_room;
              i->veh_number = veh_number;
              i->next_veh = temp->next_veh;
              i->contents = temp->contents;
              i->people = temp->people;
              i->damage = temp->damage;
              i->cspeed = temp->cspeed;
              i->seating[0] = temp->seating[0];
              i->seating[1] = temp->seating[1];
              for (int c = 0; c < NUM_MODS; c++)
                i->mod[c] = temp->mod[c];
              i->owner = temp->owner;
              Mem->ClearVehicle(temp);

            }
          }
          // this function updates pointers to the active list of vehicles
          // in the mud
          /* now safe to free old proto and write over */
          if (veh_proto[veh_number].name)
            delete [] veh_proto[veh_number].name;
          if (veh_proto[veh_number].description)
            delete [] veh_proto[veh_number].description;
          if (veh_proto[veh_number].short_description)
            delete [] veh_proto[veh_number].short_description;
          if (veh_proto[veh_number].long_description)
            delete [] veh_proto[veh_number].long_description;
          if (veh_proto[veh_number].inside_description)
            delete [] veh_proto[veh_number].inside_description;

          veh_proto[veh_number] = *d->edit_veh;
        } else {
          /* uhoh.. need to make a new place in the vehicle prototype table */
          int             found = FALSE;

          struct veh_data *new_veh_proto;
          struct index_data *new_veh_index;
          struct veh_data *temp_veh;

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

            clear_vehicle(new_veh_proto + top_of_veht + 1);
            new_veh_proto[top_of_veht + 1] = *(d->edit_veh);
            new_veh_proto[top_of_veht + 1].in_room = NOWHERE;
            new_veh_proto[top_of_veht + 1].veh_number = top_of_veht + 1;
            /* it is now safe (and necessary!) to assign real number to
             * the edit_veh, which has been -1 all this time */
            d->edit_veh->veh_number = top_of_veht + 1;
          }
          top_of_veht++;


          /* we also have to renumber all the vehicles currently
             existing in the world. This is because when I start
             extracting vehicles, bad things will happen! */
          for (temp_veh = veh_list; temp_veh; temp_veh = temp_veh->next)
            if (temp_veh->veh_number >= d->edit_veh->veh_number)
              temp_veh->veh_number++;


          /* free and replace old tables */
          delete [] veh_proto;
          delete [] veh_index;
          veh_proto = new_veh_proto;
          veh_index = new_veh_index;
        }

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

  case VEDIT_MAIN_MENU:
    /* throw us out to whichever edit mode based on user input */
    switch (*arg) {
    case 'q':
    case 'Q':
      d->edit_mode = VEDIT_CONFIRM_SAVESTRING;
      vedit_parse(d, "y");
      break;
    case 'x':
    case 'X':
      d->edit_mode = VEDIT_CONFIRM_SAVESTRING;
      vedit_parse(d, "n");
      break;
    case '1':
      send_to_char("Enter namelist:", d->character);
      d->edit_mode = VEDIT_EDIT_NAMELIST;
      break;
    case '2':
      send_to_char("Enter short desc:", d->character);
      d->edit_mode = VEDIT_SHORTDESC;
      break;
    case '3':
      send_to_char("Enter normal desc (Stationary):\r\n", d->character);
      d->edit_mode = VEDIT_DESC;
      break;
    case '4':
      /* let's go out to modify.c */
      send_to_char("Enter long desc:\r\n", d->character);
      d->edit_mode = VEDIT_LONGDESC;
      d->str = new (char *);
      if (!d->str) {
        mudlog("Malloc failed!", NULL, LOG_SYSLOG, TRUE);
        shutdown();
      }
      *(d->str) = NULL;
      d->max_str = MAX_MESSAGE_LENGTH;
      d->mail_to = 0;
      break;
    case '5':
      send_to_char("Enter inside desc:\r\n", d->character);
      d->edit_mode = VEDIT_INSDESC;
      d->str = new (char *);
      if (!d->str) {
        mudlog("Malloc failed!", NULL, LOG_SYSLOG, TRUE);
        shutdown();
      }
      *(d->str) = NULL;
      d->max_str = MAX_MESSAGE_LENGTH;
      d->mail_to = 0;
      break;
    case '6':
      send_to_char("Enter inside rear desc:\r\n", d->character);
      d->edit_mode = VEDIT_REARDESC;
      d->str = new (char *);
      if (!d->str) {
        mudlog("Malloc failed!", NULL, LOG_SYSLOG, TRUE);
        shutdown();
      }
      *(d->str) = NULL;
      d->max_str = MAX_MESSAGE_LENGTH;
      d->mail_to = 0;
      break;
    case '7':
      send_to_char("Enter arrive text:", d->character);
      d->edit_mode = VEDIT_ARRIVE;
      break;
    case '8':
      send_to_char("Enter leave text:", d->character);
      d->edit_mode = VEDIT_LEAVE;
      break;
    case '9':
      vedit_disp_flag_menu(d);
      break;
    case 'a':
      vedit_disp_att(d);
      d->edit_mode = VEDIT_ATT;
      break;
    case 'b':
      vedit_disp_type(d);
      d->edit_mode = VEDIT_TYPE;
      break;
    case 'c':
      for (number = 1; number <= ENGINE_DIESEL; number ++)
        send_to_char(CH, "  %d) %s\r\n", number, engine_type[number]);
      send_to_char("Enter default engine type: ", CH);
      d->edit_mode = VEDIT_ENGINE;
      break;
    default:
      send_to_char("That's not a valid choice!\r\n", d->character);
      vedit_disp_menu(d);
      break;
    }
    break;                      /* end of IEDIT_MAIN_MENU */
  case VEDIT_TYPE:
    switch(*arg) {
    case '1':
      d->edit_veh->type = VEH_CAR;
      vedit_disp_menu(d);
      break;
    case '2':
      d->edit_veh->type = VEH_BIKE;
      vedit_disp_menu(d);
      break;
    case '3':
      d->edit_veh->type = VEH_TRUCK;
      vedit_disp_menu(d);
      break;
    case '4':
      d->edit_veh->type = VEH_FIXEDWING;
      vedit_disp_menu(d);
      break;
    case '5':
      d->edit_veh->type = VEH_ROTORCRAFT;
      vedit_disp_menu(d);
      break;
    case '6':
      d->edit_veh->type = VEH_VECTORTHRUST;
      vedit_disp_menu(d);
      break;
    case '7':
      d->edit_veh->type = VEH_HOVERCRAFT;
      vedit_disp_menu(d);
      break;
    case '8':
      d->edit_veh->type = VEH_MOTORBOAT;
      vedit_disp_menu(d);
      break;
    case '9':
      d->edit_veh->type = VEH_SHIP;
      vedit_disp_menu(d);
      break;
    case 'a':
      d->edit_veh->type = VEH_LTA;
      vedit_disp_menu(d);
      break;
    case '0':
    default:
      d->edit_veh->type = VEH_DRONE;
      vedit_disp_menu(d);
      break;
    }
    break;
  case VEDIT_ATT:
    switch(*arg) {
    case '1':
      send_to_char(CH, "Enter Handling Attribute: ");
      d->edit_mode = VEDIT_HAND;
      break;
    case '2':
      send_to_char(CH, "Enter Speed Attribute: ");
      d->edit_mode = VEDIT_SP;
      break;
    case '3':
      send_to_char(CH, "Enter Acceleration Attribute: ");
      d->edit_mode = VEDIT_ACC;
      break;
    case '4':
      send_to_char(CH, "Enter Body Attribute: ");
      d->edit_mode = VEDIT_BOD;
      break;
    case '5':
      send_to_char(CH, "Enter Armor Attribute: ");
      d->edit_mode = VEDIT_ARMOR;
      break;
    case '6':
      send_to_char(CH, "Enter Signature Attribute: ");
      d->edit_mode = VEDIT_SIG;
      break;
    case '7':
      send_to_char(CH, "Enter Autonav Attribute: ");
      d->edit_mode = VEDIT_AUTO;
      break;
    case '8':
      send_to_char(CH, "Enter Pilot Attribute: ");
      d->edit_mode = VEDIT_PILOT;
      break;
    case '9':
      send_to_char(CH, "Enter Seating (Front) Attribute: ");
      d->edit_mode = VEDIT_SEAT;
      break;
    case '0':
      send_to_char(CH, "Enter Load Attribute: ");
      d->edit_mode = VEDIT_LOAD;
      break;
    case 'a':
      send_to_char(CH, "Enter Cost: ");
      d->edit_mode = VEDIT_COST;
      break;
    case 'q':
    case 'Q':
      vedit_disp_menu(d);
      break;
    default:
      vedit_disp_att(d);
      break;
    }
    break;
  case VEDIT_HAND:
    number = atoi(arg);
    if ((number < 0) || (number > 50)) {
      send_to_char("Value must range between 0 and 50.\r\n", CH);
      send_to_char("Enter Handling attribute: ", CH);
    } else {
      d->edit_veh->handling = number;
      vedit_disp_att(d);
    }
    break;
  case VEDIT_SP:
    number = atoi(arg);
    if ((number < 0) || (number > 1500)) {
      send_to_char("Value must range between 0 and 1500.\r\n", CH);
      send_to_char("Enter Speed attribute: ", CH);
    } else {
      d->edit_veh->speed = number;
      vedit_disp_att(d);
    }
    break;
  case VEDIT_ACC:
    number = atoi(arg);
    if ((number < 0) || (number > 50)) {
      send_to_char("Value must range between 0 and 50.\r\n", CH);
      send_to_char("Enter Acceleration attribute: ", CH);
    } else {
      d->edit_veh->accel = number;
      vedit_disp_att(d);
    }
    break;
  case VEDIT_BOD:
    number = atoi(arg);
    if ((number < 0) || (number > 50)) {
      send_to_char("Value must range between 0 and 50.\r\n", CH);
      send_to_char("Enter Body attribute: ", CH);
    } else {
      d->edit_veh->body = number;
      vedit_disp_att(d);
    }
    break;
  case VEDIT_ARMOR:
    number = atoi(arg);
    if ((number < 0) || (number > 50)) {
      send_to_char("Value must range between 0 and 50.\r\n", CH);
      send_to_char("Enter Armor attribute: ", CH);
    } else {
      d->edit_veh->armor = number;
      vedit_disp_att(d);
    }
    break;
  case VEDIT_SIG:
    number = atoi(arg);
    if ((number < 0) || (number > 50)) {
      send_to_char("Value must range between 0 and 50.\r\n", CH);
      send_to_char("Enter Signature attribute: ", CH);
    } else {
      d->edit_veh->sig = number;
      vedit_disp_att(d);
    }
    break;
  case VEDIT_AUTO:
    number = atoi(arg);
    if ((number < 0) || (number > 50)) {
      send_to_char("Value must range between 0 and 50.\r\n", CH);
      send_to_char("Enter AutoNav attribute: ", CH);
    } else {
      d->edit_veh->autonav = number;
      vedit_disp_att(d);
    }
    break;
  case VEDIT_PILOT:
    number = atoi(arg);
    if ((number < 0) || (number > 50)) {
      send_to_char("Value must range between 0 and 50.\r\n", CH);
      send_to_char("Enter Pilot attribute: ", CH);
    } else {
      d->edit_veh->pilot = number;
      vedit_disp_att(d);
    }
    break;
  case VEDIT_LOAD:
    number = atoi(arg);
    if ((number < 1) || (number > 15000)) {
      send_to_char("Value must range between 1 and 15000.\r\n", CH);
      send_to_char("Enter Load attribute: ", CH);
    } else {
      d->edit_veh->load = number;
      vedit_disp_att(d);
    }
    break;
  case VEDIT_SEAT:
    number = atoi(arg);
    if ((number < 0) || (number > 50)) {
      send_to_char("Value must range between 0 and 50.\r\n", CH);
      send_to_char("Enter Seating (Front) attribute: ", CH);
    } else {
      d->edit_veh->seating[1] = number;
      send_to_char("Enter Seating (Rear) attribute: ", CH);
      d->edit_mode = VEDIT_SEAT2;
    }
    break;
  case VEDIT_SEAT2:
    number = atoi(arg);
    if ((number < 0) || (number > 50)) {
      send_to_char("Value must range between 0 and 50.\r\n", CH);
      send_to_char("Enter Seating (Rear) attribute: ", CH);
    } else {
      d->edit_veh->seating[0] = number;
      vedit_disp_att(d);
    }
    break;
  case VEDIT_COST:
    number = atoi(arg);
    d->edit_veh->cost = number;
    vedit_disp_att(d);
    break;

  case VEDIT_EDIT_NAMELIST:
    if (d->edit_veh->name)
      delete [] d->edit_veh->name;
    d->edit_veh->name = str_dup(arg);
    vedit_disp_menu(d);
    break;
  case VEDIT_SHORTDESC:
    if (d->edit_veh->short_description)
      delete [] d->edit_veh->short_description;
    d->edit_veh->short_description = str_dup(arg);
    vedit_disp_menu(d);
    break;
  case VEDIT_DESC:
    if (d->edit_veh->description)
      delete [] d->edit_veh->description;
    d->edit_veh->description = str_dup(arg);
    vedit_disp_menu(d);
    break;
  case VEDIT_ARRIVE:
    if (d->edit_veh->arrive)
      delete [] d->edit_veh->arrive;
    d->edit_veh->arrive = str_dup(arg);
    vedit_disp_menu(d);
    break;
  case VEDIT_LEAVE:
    if (d->edit_veh->leave)
      delete [] d->edit_veh->leave;
    d->edit_veh->leave = str_dup(arg);
    vedit_disp_menu(d);
    break;
  case VEDIT_FLAGS:
    number = atoi(arg);
    if (number < 0 || number > NUM_VFLAGS)
      send_to_char(CH, "Invalid choice. Choose Flag (0 to quit):");
    else if (number == 0)
      vedit_disp_menu(d);
    else {
      d->edit_veh->flags.ToggleBit(number);
      vedit_disp_flag_menu(d);
    }
    break;
  case VEDIT_ENGINE:
    number = atoi(arg);
    if (number < 1 || number > ENGINE_DIESEL)
      send_to_char("Invalid Engine Type. Select Type : ", CH);
    else {
      d->edit_veh->engine = number;
      vedit_disp_menu(d);
    }
  default:
    break;
  }
}
#undef VEH

void write_vehs_to_disk(int zone)
{
  long counter, realcounter;
  FILE *fp;
  struct veh_data *veh;

  zone = real_zone(zone);

  veh = Mem->GetVehicle();

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

  /* start running through all vehicles in this zone */
  for (counter = zone_table[zone].number * 100; counter <= zone_table[zone].top; counter++) {
    /* write vehicle to disk */
    realcounter = real_vehicle(counter);
    if (realcounter >= 0) {
      *veh = veh_proto[realcounter];
      if (!strcmp("an unfinished object", veh->name))
        continue;
      fprintf(fp, "#%ld\n", veh_index[veh->veh_number].vnum);
      fprintf(fp, "Name:\t%s\n", veh->name ? veh->name : "unnamed");
      fprintf(fp, "ShortDesc:\t%s\n", veh->short_description ? veh->short_description : "an unnamed vehicle");
      fprintf(fp, "RoomDesc:\t%s\n", veh->description ? veh->description : "An unnamed vehicle sits here");
      fprintf(fp, "LongDesc:$\n%s~\n", cleanup(buf2, veh->long_description ? veh->long_description : "You see an uncreative vehicle."));
      fprintf(fp, "Inside:$\n%s~\n", cleanup(buf2, veh->inside_description ? veh->inside_description: "You see an uncreative vehicle."));
      fprintf(fp, "InsideRear:$\n%s~\n", cleanup(buf2, veh->rear_description ? veh->rear_description: "You see an uncreative vehicle."));
      fprintf(fp, "Leaving:\t%s\n", cleanup(buf2, veh->leave ? veh->leave : "leaves"));
      fprintf(fp, "Arriving:\t%s\n", cleanup(buf2, veh->arrive ? veh->arrive : "arrives"));
      fprintf(fp, "Handling:\t%d\n"
              "Speed:\t%d\n"
              "Accel:\t%d\n"
              "Body:\t%d\n"
              "Armour:\t%d\n"
              "Pilot:\t%d\n",
              veh->handling, veh->speed, veh->accel, veh->body, veh->armor, veh->pilot);
      fprintf(fp, "Sig:\t%d\n"
              "Autonav:\t%d\n"
              "Seating:\t%d\n"
              "SeatingBack:\t%d\n"
              "Load:\t%d\n"
              "Cost:\t%d\n"
              "Type:\t%d\n"
              "Flags:\t%s\n"
              "Engine:\t%d\n",
              veh->sig, veh->autonav, veh->seating[1], veh->seating[0], (int)veh->load, veh->cost, veh->type,
              veh->flags.ToString(), veh->engine);
      fprintf(fp, "BREAK\n");
    }
  }
  /* write final line, close */
  fprintf(fp, "END\n");
  fclose(fp);
  /* nuke temp vehicle, but not the strings */
  Mem->ClearVehicle(veh);
  write_index_file("veh");
}