dbx/cnf/
dbx/lib/
dbx/lib/misc/
dbx/lib/text/help/
dbx/lib/world/
dbx/lib/world/qst/
dbx/src/
/*
** dg_olc.c: this source file is used in extending Oasis style OLC for
** dg-scripts onto a CircleMUD that already has dg-scripts (as released
** by Mark Heilpern on 1/1/98) implemented.
**
** Parts of this file by Chris Jacobson of _Aliens vs Predator: The MUD_
*/


#define NO_CPS_LOGGING /* avoid logging of CHECK_PLAYER_SPECIALS on mobs */
#include "conf.h"
#include "sysdep.h"

#include "structs.h"
#include "utils.h"
#include "comm.h"
#include "db.h"
#include "olc.h"
#include "dg_olc.h"
#include "dg_event.h"

/* declare externally defined globals */
extern struct index_data **trig_index;
extern const char *trig_types[], *otrig_types[], *wtrig_types[];
extern struct descriptor_data *descriptor_list;
extern struct trig_data *trigger_list;
extern int top_of_trigt;
extern struct zone_data *zone_table;


/* prototype externally defined functions */
void trig_data_copy(trig_data *this_data, const trig_data *trg);
void free_varlist(struct trig_var_data *vd);

void trigedit_disp_menu(struct descriptor_data *d);
void trigedit_save(struct descriptor_data *d);

/* copy an entire script from one holder (mob/obj/room) to another */
void script_copy(void *dst, void *src, int type)
{
  struct script_data *s_src = NULL;
  struct script_data *s_dst = NULL;
  trig_data *t_src, *t_dst;

  /* find the scripts of the source and destination */
  switch (type)
  {
    case MOB_TRIGGER:
      s_src = SCRIPT((struct char_data *)src);
      s_dst = SCRIPT((struct char_data *)dst);
      ((struct char_data *)dst)->proto_script =
        ((struct char_data *)src)->proto_script;
     break;
    case OBJ_TRIGGER:
      s_src = SCRIPT((struct obj_data *)src);
      s_dst = SCRIPT((struct obj_data *)dst);
      ((struct obj_data *)dst)->proto_script =
        ((struct obj_data *)src)->proto_script;
      break;
    case WLD_TRIGGER:
      s_src = SCRIPT((struct room_data *)src);
      s_dst = SCRIPT((struct room_data *)dst);
      ((struct room_data *)dst)->proto_script =
        ((struct room_data *)src)->proto_script;
      break;
    default:
      log("SYSERR: Unknown type code sent to script_copy()!");
      break;
  }

  /* make sure the dst doesnt already have a script       */
  /* if it does, delete it                                */
  if (s_dst) extract_script(s_dst);

  /* copy the scrip data */
  s_dst->types = s_src->types;
  t_src = TRIGGERS(s_src);
  while (t_src)
  {
    CREATE(t_dst, trig_data, 1);
    if (!TRIGGERS(s_dst)) TRIGGERS(s_dst) = t_dst;
    trig_data_copy(t_dst, t_src);
    t_dst = t_dst->next;
    t_src = t_src->next;
  }

}

/* called when a mob or object is being saved to disk, so its script can */
/* be saved */
void script_save_to_disk(FILE *fp, void *item, int type)
{
  struct trig_proto_list *t;

  if (type==MOB_TRIGGER)
    t = ((struct char_data *)item)->proto_script;
  else if (type==OBJ_TRIGGER)
    t = ((struct obj_data *)item)->proto_script;
  else if (type==WLD_TRIGGER)
    t = ((struct room_data *)item)->proto_script;
  else {
    log("SYSERR: Invalid type passed to script_save_mobobj_to_disk()");
    return;
  }

  while (t)
  {
    fprintf(fp,"T %d\n", t->vnum);
    t = t->next;
  }
}


void trigedit_setup_new(struct descriptor_data *d)
{
  struct trig_data *trig;
  
  /*
   * Allocate a scratch trigger structure
   */
  CREATE(trig, struct trig_data, 1);

  trig->nr = -1;

  /*
   * Set up some defaults
   */ 
  trig->name = str_dup("new trigger");
  trig->trigger_type = MTRIG_GREET;

  /* cmdlist will be a large char string until the trigger is saved */
  CREATE(OLC_STORAGE(d), char, MAX_CMD_LENGTH);
  strcpy(OLC_STORAGE(d),
    "say My trigger commandlist is not complete!\r\n");
  trig->narg = 100;

  OLC_TRIG(d) = trig;
  OLC_VAL(d) = 0;  /* Has changed flag. (It hasn't so far, we just made it.) */
    
  trigedit_disp_menu(d);
}

void trigedit_setup_existing(struct descriptor_data *d, int rtrg_num)
{
  struct trig_data *trig;
  struct cmdlist_element *c;

  /*
   * Allocate a scratch trigger structure
   */
  CREATE(trig, struct trig_data, 1);

  trig_data_copy(trig, trig_index[rtrg_num]->proto);

  /* convert cmdlist to a char string */
  c = trig->cmdlist;
  CREATE(OLC_STORAGE(d), char, MAX_CMD_LENGTH);
  strcpy(OLC_STORAGE(d), "");
  
  while (c)
  {
    strcat(OLC_STORAGE(d), c->cmd);
    strcat(OLC_STORAGE(d), "\r\n");
    c = c->next;
  }
  /* now trig->cmdlist is something to pass to the text editor */
  /* it will be converted back to a real cmdlist_element list later */

  OLC_TRIG(d) = trig;
  OLC_VAL(d) = 0;  /* Has changed flag. (It hasn't so far, we just made it.) */
    
  trigedit_disp_menu(d);
}


void trigedit_disp_menu(struct descriptor_data *d)
{
  struct trig_data *trig = OLC_TRIG(d);
  char *attach_type;
  char trgtypes[256];

  get_char_cols(d->character);

  if (trig->attach_type==OBJ_TRIGGER) {
    attach_type = "Objects";
    sprintbit(GET_TRIG_TYPE(trig), otrig_types, trgtypes);
  } else if (trig->attach_type==WLD_TRIGGER) {
    attach_type = "Rooms";
    sprintbit(GET_TRIG_TYPE(trig), wtrig_types, trgtypes);
  } else {
    attach_type = "Mobiles";
    sprintbit(GET_TRIG_TYPE(trig), trig_types, trgtypes);
  }
      
  sprintf(buf,
#if defined(CLEAR_SCREEN)
""
#endif

  "Trigger Editor [%s%d%s]\r\n\r\n"
  "%s1)%s Name         : %s%s\r\n"
  "%s2)%s Intended for : %s%s\r\n"
  "%s3)%s Trigger types: %s%s\r\n"
  "%s4)%s Numberic Arg : %s%d\r\n"
  "%s5)%s Arguments    : %s%s\r\n"
  "%s6)%s Commands:\r\n%s%s\r\n"
  "%sQ)%s Quit\r\n"
  "Enter Choice :",

  grn, OLC_NUM(d), nrm, 			/* vnum on the title line */
  grn, nrm, yel, GET_TRIG_NAME(trig),		/* name                   */
  grn, nrm, yel, attach_type,			/* attach type            */
  grn, nrm, yel, trgtypes,			/* greet/drop/etc         */
  grn, nrm, yel, trig->narg,			/* numeric arg            */
  grn, nrm, yel, trig->arglist?trig->arglist:"",/* strict arg             */
  grn, nrm, cyn, OLC_STORAGE(d),		/* the command list       */
  grn, nrm);                                    /* quit colors            */

  send_to_char(buf, d->character);
  OLC_MODE(d) = TRIGEDIT_MAIN_MENU;
}

void trigedit_disp_types(struct descriptor_data *d)
{
  int i, columns = 0;
  const char **types;

  switch(OLC_TRIG(d)->attach_type)
  {
    case WLD_TRIGGER:
      types = wtrig_types;
      break;
    case OBJ_TRIGGER:
      types = otrig_types;
      break;
    case MOB_TRIGGER:
    default:
      types = trig_types;
      break;
  }

  get_char_cols(d->character);
#if defined(CLEAR_SCREEN)
  send_to_char("", d->character);
#endif
  for (i = 0; i < NUM_TRIG_TYPE_FLAGS; i++) {
    sprintf(buf, "%s%2d%s) %-20.20s  %s", grn, i + 1, nrm, types[i],
              !(++columns % 2) ? "\r\n" : "");
    send_to_char(buf, d->character);
  }
  sprintbit(GET_TRIG_TYPE(OLC_TRIG(d)), types, buf1);
  sprintf(buf, "\r\nCurrent types : %s%s%s\r\nEnter type (0 to quit) : ",
                cyn, buf1, nrm);
  send_to_char(buf, d->character);

}

void trigedit_parse(struct descriptor_data *d, char *arg)
{
  int i = 0;

  switch (OLC_MODE(d)) {
    case TRIGEDIT_MAIN_MENU:
     switch (tolower(*arg)) {
       case 'q':
         if (OLC_VAL(d)) { /* Anything been changed? */
           if (!GET_TRIG_TYPE(OLC_TRIG(d))) {
             send_to_char("Invalid Trigger Type! Answer a to abort quit!\r\n",
               d->character);     
           }
           send_to_char("Do you wish to save the changes to the trigger? (y/n): ",
             d->character);     
           OLC_MODE(d) = TRIGEDIT_CONFIRM_SAVESTRING;
         } else
           cleanup_olc(d, CLEANUP_ALL);
           return;
         case '1':
           OLC_MODE(d) = TRIGEDIT_NAME;
           send_to_char("Name: ", d->character);
           break;
         case '2':
           OLC_MODE(d) = TRIGEDIT_INTENDED;
           send_to_char("0: Mobiles, 1: Objects, 2: Rooms: ", d->character);
           break;
         case '3':
           OLC_MODE(d) = TRIGEDIT_TYPES;
           trigedit_disp_types(d);
           break;
         case '4':
           OLC_MODE(d) = TRIGEDIT_NARG;
           send_to_char("Numeric argument: ", d->character);
           break;
         case '5':
           OLC_MODE(d) = TRIGEDIT_ARGUMENT;
           send_to_char("Argument: ", d->character);
           break;
         case '6':
           OLC_MODE(d) = TRIGEDIT_COMMANDS;
           send_to_char(
             "Enter trigger commands: (/s saves /h for help)\r\n\r\n",
             d->character);
           d->backstr = NULL;
           if (OLC_STORAGE(d)) {
             send_to_char(OLC_STORAGE(d), d->character);
             d->backstr = str_dup(OLC_STORAGE(d));
           }
           d->str = &OLC_STORAGE(d);
           d->max_str = MAX_CMD_LENGTH;
           d->mail_to = 0;
           OLC_VAL(d) = 1;

           break;
         default:
           trigedit_disp_menu(d);
           return;
     }
     return;
    
    case TRIGEDIT_CONFIRM_SAVESTRING:
      switch(tolower(*arg)) {
        case 'y':
          trigedit_save(d);
          sprintf(buf, "OLC: %s edits trigger %d", GET_NAME(d->character),
            OLC_NUM(d));
          mudlog(buf, CMP, MAX(LVL_BUILDER, GET_INVIS_LEV(d->character)), TRUE);
          /* fall through */
        case 'n':
          cleanup_olc(d, CLEANUP_ALL);
          return;
        case 'a': /* abort quitting */
          break;
        default:
          send_to_char("Invalid choice!\r\n", d->character);
          send_to_char("Do you wish to save the trigger? : ", d->character);
          return;
      }
      break;

    case TRIGEDIT_NAME:
      if (OLC_TRIG(d)->name)
        free(OLC_TRIG(d)->name);
      OLC_TRIG(d)->name = str_dup((arg && *arg) ? arg : "undefined");
      OLC_VAL(d)++;
      break;

    case TRIGEDIT_INTENDED:
      if ((atoi(arg)>=MOB_TRIGGER) || (atoi(arg)<=WLD_TRIGGER))
        OLC_TRIG(d)->attach_type = atoi(arg);
      OLC_VAL(d)++;
      break;

    case TRIGEDIT_NARG:
      OLC_TRIG(d)->narg = atoi(arg);
      OLC_VAL(d)++;
      break;

    case TRIGEDIT_ARGUMENT:
      OLC_TRIG(d)->arglist = (*arg?str_dup(arg):NULL);
      OLC_VAL(d)++;
      break;

    case TRIGEDIT_TYPES:
      if ((i = atoi(arg)) == 0)
        break;
      else if (!((i < 0) || (i > NUM_TRIG_TYPE_FLAGS)))
        TOGGLE_BIT((GET_TRIG_TYPE(OLC_TRIG(d))), 1 << (i - 1));
      OLC_VAL(d)++;
      trigedit_disp_types(d);
      return;

    case TRIGEDIT_COMMANDS:
      break;

  }

  OLC_MODE(d) = TRIGEDIT_MAIN_MENU;
  trigedit_disp_menu(d);
}

/*
** print out the letter codes pertaining to the bits set in 'data'
*/
void sprintbits(int data, char *dest)
{
  int i;
  char *p = dest;

  for (i=0; i<32; i++) {
    if (data & (1<<i)) {
      *p = ((i<=25)?('a'+i):('A'+i));
      p++;
    }
  }
  *p = '\0';
}


/* save the zone's triggers to internal memory and to disk */
void trigedit_save(struct descriptor_data *d)
{
  int trig_rnum, i;
  int found = 0;
  char *s;
  trig_data *proto;
  trig_data *trig = OLC_TRIG(d);
  trig_data *live_trig;
  struct cmdlist_element *cmd, *next_cmd;
  struct index_data **new_index;
  struct descriptor_data *dsc;
  FILE *trig_file;
  int zone, top;
  char buf[MAX_CMD_LENGTH];
  char bitBuf[MAX_INPUT_LENGTH];
  char fname[MAX_INPUT_LENGTH];
  char logbuf[MAX_INPUT_LENGTH];


  if ((trig_rnum = real_trigger(OLC_NUM(d))) != -1) {
    proto = trig_index[trig_rnum]->proto;
    for (cmd = proto->cmdlist; cmd; cmd = next_cmd) { 
      next_cmd = cmd->next;
      if (cmd->cmd)
        free(cmd->cmd);
      free(cmd);
    }


    free(proto->arglist);
    free(proto->name);

    /* Recompile the command list from the new script */
    s = OLC_STORAGE(d);

    CREATE(trig->cmdlist, struct cmdlist_element, 1);
    trig->cmdlist->cmd = str_dup(strtok(s, "\n\r"));
    cmd = trig->cmdlist;

    while ((s = strtok(NULL, "\n\r"))) {
      CREATE(cmd->next, struct cmdlist_element, 1);
      cmd = cmd->next;
      cmd->cmd = str_dup(s);
    }

    /* make the prorotype look like what we have */
    trig_data_copy(proto, trig);

    /* go through the mud and replace existing triggers         */
    live_trig = trigger_list;
    while (live_trig)
    {
      if (GET_TRIG_RNUM(live_trig) == trig_rnum) {
        if (live_trig->arglist) {
          free(live_trig->arglist);
          live_trig->arglist = NULL;
        }
        if (live_trig->name) {
          free(live_trig->name);
          live_trig->name = NULL;
        }

        if (proto->arglist)
          live_trig->arglist = str_dup(proto->arglist);
        if (proto->name)
          live_trig->name = str_dup(proto->name);

        live_trig->cmdlist = proto->cmdlist;
        live_trig->curr_state = live_trig->cmdlist;
        live_trig->trigger_type = proto->trigger_type;
        live_trig->attach_type = proto->attach_type;
        live_trig->narg = proto->narg;
        live_trig->data_type = proto->data_type;
        live_trig->depth = 0;
        live_trig->wait_event = NULL;
        if (GET_TRIG_WAIT(live_trig))
          remove_event(GET_TRIG_WAIT(live_trig));
        free_varlist(live_trig->var_list);
      }

      live_trig = live_trig->next_in_world;
    }
  } else {
    /* this is a new trigger */
    CREATE(new_index, struct index_data *, top_of_trigt + 2);

    /* Recompile the command list from the new script */
    s = OLC_STORAGE(d);
         
    CREATE(trig->cmdlist, struct cmdlist_element, 1);
    trig->cmdlist->cmd = str_dup(strtok(s, "\n\r"));
    cmd = trig->cmdlist;
                                
    while ((s = strtok(NULL, "\n\r"))) {
      CREATE(cmd->next, struct cmdlist_element, 1);
      cmd = cmd->next;
      cmd->cmd = str_dup(s);
    }

    for (i = 0; i < top_of_trigt; i++) {
      if (!found) {
        if (trig_index[i]->vnum > OLC_NUM(d)) {
          found = TRUE;
          trig_rnum = i;
                        
          CREATE(new_index[trig_rnum], struct index_data, 1);
          GET_TRIG_RNUM(OLC_TRIG(d)) = trig_rnum;
          new_index[trig_rnum]->vnum = OLC_NUM(d);
          new_index[trig_rnum]->number = 0; 
          new_index[trig_rnum]->func = NULL;
          CREATE(proto, struct trig_data, 1);
          new_index[trig_rnum]->proto = proto;
          trig_data_copy(proto, trig);

          if (trig->name)
            proto->name = str_dup(trig->name);
          if (trig->arglist)
            proto->arglist = str_dup(trig->arglist);  

          new_index[trig_rnum + 1] = trig_index[trig_rnum];

          proto = trig_index[trig_rnum]->proto;
          proto->nr = trig_rnum + 1;
        } else {
          new_index[i] = trig_index[i];
        }
      } else {
         new_index[i + 1] = trig_index[i];
         proto = trig_index[i]->proto;
         proto->nr = i + 1;
      }
    }

    if (!found) {
      trig_rnum = i;
      CREATE(new_index[trig_rnum], struct index_data, 1);
      GET_TRIG_RNUM(OLC_TRIG(d)) = trig_rnum;  
      new_index[trig_rnum]->vnum = OLC_NUM(d);
      new_index[trig_rnum]->number = 0;
      new_index[trig_rnum]->func = NULL;
                        
      CREATE(proto, struct trig_data, 1);
      new_index[trig_rnum]->proto = proto;
      trig_data_copy(proto, trig);

      if (trig->name)
        proto->name = str_dup(trig->name);
      if (trig->arglist)
        proto->arglist = str_dup(trig->arglist);  
    }
                
    free(trig_index);
                        
    trig_index = new_index;
    top_of_trigt++;         

    /* HERE IT HAS TO GO THROUGH AND FIX ALL SCRIPTS/TRIGS OF HIGHER RNUM */
    for (live_trig = trigger_list; live_trig; live_trig = live_trig->next_in_world)
      if (GET_TRIG_RNUM(live_trig) > trig_rnum)
        GET_TRIG_RNUM(live_trig)++;
        
    /*
     * Update other trigs being edited.
     */
     for (dsc = descriptor_list; dsc; dsc = dsc->next)
       if (dsc->connected == CON_TRIGEDIT)
         if (GET_TRIG_RNUM(OLC_TRIG(dsc)) >= trig_rnum)
           GET_TRIG_RNUM(OLC_TRIG(dsc))++;

  }

  /* now write the trigger out to disk, along with the rest of the  */
  /* triggers for this zone, of course                              */
  /* note: we write this to disk NOW instead of letting the builder */
  /* have control because if we lose this after having assigned a   */
  /* new trigger to an item, we will get SYSERR's upton reboot that */
  /* could make things hard to debug.                               */

  zone = zone_table[OLC_ZNUM(d)].number;
  top = zone_table[OLC_ZNUM(d)].top;

#ifdef CIRCLE_MAC
  sprintf(fname, "%s:%i.new", TRG_PREFIX, zone);
#else
  sprintf(fname, "%s/%i.new", TRG_PREFIX, zone);
#endif

  if (!(trig_file = fopen(fname, "w"))) {
    sprintf(logbuf,"SYSERR: OLC: Can't open trig file \"%s\"", fname);
    mudlog(logbuf, BRF, MAX(LVL_GOD, GET_INVIS_LEV(d->character)), TRUE);
    return;
  }
        
  for (i = zone * 100; i <= top; i++) {
    if ((trig_rnum = real_trigger(i)) != -1) {
      trig = trig_index[trig_rnum]->proto;

      if (fprintf(trig_file, "#%d\n", i) < 0) {
        sprintf(logbuf, "SYSERR: OLC: Can't write trig file!"); 
        mudlog(logbuf, BRF, MAX(LVL_GOD, GET_INVIS_LEV(d->character)), TRUE);
        fclose(trig_file);
        return;
      }
      sprintbits(GET_TRIG_TYPE(trig), bitBuf);
      fprintf(trig_file,      "%s~\n"
                              "%d %s %d\n"
                              "%s~\n",
           (GET_TRIG_NAME(trig)) ? (GET_TRIG_NAME(trig)) : "unknown trigger",
           trig->attach_type,
           bitBuf, GET_TRIG_NARG(trig),
           GET_TRIG_ARG(trig) ? GET_TRIG_ARG(trig) : "");
                
      /* Build the text for the script */
      strcpy(buf,"");
      for (cmd = trig->cmdlist; cmd; cmd = cmd->next) {
        strcat(buf, cmd->cmd);
        strcat(buf, "\r\n");
      }

      if (!buf[0])
        strcpy(buf, "* Empty script");
                
      fprintf(trig_file, "%s~\n", buf);
      *buf = '\0';
    }
  }
        
  fprintf(trig_file, "$~\n");
  fclose(trig_file);
                
#ifdef CIRCLE_MAC
  sprintf(buf, "%s:%d.trg", TRG_PREFIX, zone);
#else
  sprintf(buf, "%s/%d.trg", TRG_PREFIX, zone);
#endif
        
  rename(fname, buf);
}

void dg_olc_script_free(struct descriptor_data *d)
{
  struct trig_proto_list *editscript, *prevscript;

  editscript = OLC_SCRIPT(d);
  while (editscript) {
    prevscript = editscript;
    editscript = editscript->next;
    free(prevscript);
  }
}


void dg_olc_script_copy(struct descriptor_data *d)
{
  struct trig_proto_list *origscript, *editscript;

  if (OLC_ITEM_TYPE(d)==MOB_TRIGGER)
    origscript = OLC_MOB(d)->proto_script;
  else if (OLC_ITEM_TYPE(d)==OBJ_TRIGGER)
    origscript = OLC_OBJ(d)->proto_script;
  else origscript = OLC_ROOM(d)->proto_script;

  if (origscript) {
    CREATE(editscript, struct trig_proto_list, 1);
    OLC_SCRIPT(d) = editscript;

    while (origscript) {
      editscript->vnum = origscript->vnum;
      origscript = origscript->next;
      if (origscript)
        CREATE(editscript->next, struct trig_proto_list, 1);
      editscript = editscript->next;
    }
  } else
      OLC_SCRIPT(d) = NULL;
}

void dg_script_menu(struct descriptor_data *d)
{
  struct trig_proto_list *editscript;
  int i = 0;

  /* make sure our input parser gets used */
  OLC_MODE(d) = OLC_SCRIPT_EDIT;
  OLC_SCRIPT_EDIT_MODE(d) = SCRIPT_MAIN_MENU;


#if defined(CLEAR_SCREEN) /* done wierd to compile with the vararg send() */
#define FMT    "     Script Editor\r\n\r\n     Trigger List:\r\n"
#else
#define FMT    "     Script Editor\r\n\r\n     Trigger List:\r\n"
#endif
  send_to_char(FMT,d->character);
#undef FMT

  editscript = OLC_SCRIPT(d);
  while (editscript) {
    sprintf(buf,"     %2d) [%s%d%s] %s%s%s", ++i, cyn,
      editscript->vnum, nrm, cyn,
      trig_index[real_trigger(editscript->vnum)]->proto->name, nrm);
    send_to_char(buf, d->character);
    if (trig_index[real_trigger(editscript->vnum)]->proto->attach_type !=
        OLC_ITEM_TYPE(d))
      sprintf(buf,"   %s** Mis-matched Trigger Type **%s\r\n",grn,nrm);
    else
      sprintf(buf,"\r\n");
    send_to_char(buf, d->character);

    editscript = editscript->next;
  }
  if (i==0) send_to_char("     <none>\r\n", d->character);

  sprintf(buf, "\r\n"
    " %sN%s)  New trigger for this script\r\n"
    " %sD%s)  Delete a trigger in this script\r\n"
    " %sX%s)  Exit Script Editor\r\n\r\n"
    "     Enter choice :",
    grn, nrm, grn, nrm, grn, nrm);
  send_to_char(buf,d->character);
}

int dg_script_edit_parse(struct descriptor_data *d, char *arg)
{
  struct trig_proto_list *trig, *currtrig;
  int count, pos, vnum;

  switch(OLC_SCRIPT_EDIT_MODE(d)) {
    case SCRIPT_MAIN_MENU:
      switch(tolower(*arg)) {
        case 'x':
          if (OLC_ITEM_TYPE(d)==MOB_TRIGGER) {
            trig = OLC_MOB(d)->proto_script;
            OLC_MOB(d)->proto_script = OLC_SCRIPT(d);
          } else if (OLC_ITEM_TYPE(d)==OBJ_TRIGGER) {
            trig = OLC_OBJ(d)->proto_script;
            OLC_OBJ(d)->proto_script = OLC_SCRIPT(d);
          } else {
            trig = OLC_ROOM(d)->proto_script;
            OLC_ROOM(d)->proto_script = OLC_SCRIPT(d);
          }

          while (trig) {
            currtrig = trig->next;
            free(trig);
            trig = currtrig;
          }
          return 0;
        case 'n':
          send_to_char("\r\nPlease enter position, vnum   (ex: 1, 200):",
            d->character);
          OLC_SCRIPT_EDIT_MODE(d) = SCRIPT_NEW_TRIGGER;
          break;
        case 'd':
          send_to_char("     Which entry should be deleted?  0 to abort :",
            d->character);
          OLC_SCRIPT_EDIT_MODE(d) = SCRIPT_DEL_TRIGGER;
          break;
        default:
          dg_script_menu(d);
          break;
      }
      return 1;

    case SCRIPT_NEW_TRIGGER:
      vnum = -1;
      count = sscanf(arg,"%d, %d",&pos,&vnum);
      if (count==1) {
        vnum = pos;
        pos = 999;
      }

      if (pos<=0) break; /* this aborts a new trigger entry */

      if (vnum==0) break; /* this aborts a new trigger entry */

      if (real_trigger(vnum)<0) {
        send_to_char("Invalid Trigger VNUM!\r\n"
            "Please enter position, vnum   (ex: 1, 200):",
            d->character);
        return 1;
      }

      /* add the new info in position */
      currtrig = OLC_SCRIPT(d);
      CREATE(trig, struct trig_proto_list, 1);
      trig->vnum = vnum;

      if (pos==1 || !currtrig) {
        trig->next = OLC_SCRIPT(d);
        OLC_SCRIPT(d) = trig;
      } else {
        while (currtrig->next && --pos) {
          currtrig = currtrig->next;
        }
        trig->next = currtrig->next;
        currtrig->next = trig;
      }
      OLC_VAL(d)++;
      break;

    case SCRIPT_DEL_TRIGGER:
      pos = atoi(arg);
      if (pos<=0) break;

      if (pos==1 && OLC_SCRIPT(d)) {
        OLC_VAL(d)++;
        currtrig = OLC_SCRIPT(d);
        OLC_SCRIPT(d) = currtrig->next;
        free(currtrig);
        break;
      }

      pos--;
      currtrig = OLC_SCRIPT(d);
      while (--pos && currtrig) currtrig = currtrig->next;
      /* now curtrig points one before the target */
      if (currtrig && currtrig->next) {
        OLC_VAL(d)++;
        trig = currtrig->next;
        currtrig->next = trig->next;
        free(trig);
      }
      break;
  }

  dg_script_menu(d);
  return 1;      
}