rasputin/bin/
rasputin/cnf/
rasputin/doc/cwg/
rasputin/lib/
rasputin/lib/etc/
rasputin/lib/etc/boards/
rasputin/lib/house/
rasputin/lib/misc/
rasputin/lib/plralias/A-E/
rasputin/lib/plralias/F-J/
rasputin/lib/plralias/K-O/
rasputin/lib/plralias/P-T/
rasputin/lib/plralias/U-Z/
rasputin/lib/plralias/ZZZ/
rasputin/lib/plrfiles/
rasputin/lib/plrfiles/A-E/
rasputin/lib/plrfiles/F-J/
rasputin/lib/plrfiles/K-O/
rasputin/lib/plrfiles/P-T/
rasputin/lib/plrfiles/U-Z/
rasputin/lib/plrfiles/ZZZ/
rasputin/lib/plrobjs/
rasputin/lib/plrobjs/A-E/
rasputin/lib/plrobjs/F-J/
rasputin/lib/plrobjs/K-O/
rasputin/lib/plrobjs/P-T/
rasputin/lib/plrobjs/U-Z/
rasputin/lib/plrobjs/ZZZ/
rasputin/lib/plrvars/A-E/
rasputin/lib/plrvars/F-J/
rasputin/lib/plrvars/K-O/
rasputin/lib/plrvars/P-T/
rasputin/lib/plrvars/U-Z/
rasputin/lib/plrvars/ZZZ/
rasputin/lib/world/gld/
rasputin/lib/world/trg/
rasputin/src/
rasputin/src/doc/
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 *  gedit.c:  Olc written for shoplike guildmasters, code by             *
 *             Jason Goodwin                                             *
 *    Made for Circle3.0 bpl11, its copyright applies                    *
 *                                                                       *
 *  Made for Oasis OLC                                                   *
 *  Copyright 1996 Harvey Gilpin.                                        *
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

#include "conf.h"
#include "sysdep.h"

CVSHEADER("$CVSHeader: cwg/rasputin/src/gedit.c,v 1.6 2004/12/31 17:50:49 fnord Exp $");

#include "structs.h"
#include "utils.h"

#include "comm.h"
#include "db.h"
#include "shop.h"
#include "guild.h"
#include "oasis.h"
#include "screen.h"
#include "spells.h"
#include "genolc.h"
#include "genshp.h"
#include "genzon.h"
#include "interpreter.h"
#include "gengld.h"

/*-------------------------------------------------------------------*/
/* external variables */
extern struct guild_data *guild_index;
extern struct spell_info_type spell_info[];
extern int top_guild;

extern zone_rnum real_zone_by_thing(room_vnum vznum);

/*-------------------------------------------------------------------*/
/*. Function prototypes . */

void gedit_setup_new(struct descriptor_data *d);
void gedit_setup_existing(struct descriptor_data *d, int rgm_num);
void gedit_parse(struct descriptor_data *d, char *arg);
void gedit_disp_menu(struct descriptor_data *d);
void gedit_no_train_menu(struct descriptor_data *d);
void gedit_save_internally(struct descriptor_data *d);
void gedit_save_to_disk(int num);
void copy_guild(struct guild_data *tgm, struct guild_data *fgm);
void free_guild_strings(struct guild_data *guild);
void free_guild(struct guild_data *guild);
void gedit_modify_string(char **str, char *new);

extern const char *trade_letters[];

/*. External . */
SPECIAL(guild);

/*
 * Should check more things.
 */
void gedit_save_internally(struct descriptor_data *d)
{
  OLC_GUILD(d)->vnum = OLC_NUM(d);
  add_guild(OLC_GUILD(d));
}

void gedit_save_to_disk(int num)
{
  save_guilds(num);
}


/*-------------------------------------------------------------------*\
  utility functions 
 \*-------------------------------------------------------------------*/

ACMD(do_oasis_gedit)
{
  int number = NOWHERE, save = 0;
  guild_rnum real_num;
  struct descriptor_data *d;
  char *buf3;
  char buf1[MAX_INPUT_LENGTH];
  char buf2[MAX_INPUT_LENGTH];
  
  /****************************************************************************/
  /** Parse any arguments.                                                   **/
  /****************************************************************************/
  buf3 = two_arguments(argument, buf1, buf2);
  
  if (!*buf1) {
    send_to_char(ch, "Specify a guild VNUM to edit.\r\n");
    return;
  } else if (!isdigit(*buf1)) {
    if (str_cmp("save", buf1) != 0) {
      send_to_char(ch, "Yikes!  Stop that, someone will get hurt!\r\n");
      return;
    }
    
    save = TRUE;
    
    if (is_number(buf2))
      number = atoi(buf2);
    else if (GET_OLC_ZONE(ch) > 0) {
      zone_rnum zlok;
      
      if ((zlok = real_zone(GET_OLC_ZONE(ch))) == NOWHERE)
        number = NOWHERE;
      else
        number = genolc_zone_bottom(zlok);
    }
    
    if (number == NOWHERE) {
      send_to_char(ch, "Save which zone?\r\n");
      return;
    }
  }
  
  /****************************************************************************/
  /** If a numeric argument was given, get it.                               **/
  /****************************************************************************/
  if (number == NOWHERE)
    number = atoi(buf1);
  
  /****************************************************************************/
  /** Check that the guild isn't already being edited.                        **/
  /****************************************************************************/
  for (d = descriptor_list; d; d = d->next) {
    if (STATE(d) == CON_GEDIT) {
      if (d->olc && OLC_NUM(d) == number) {
        send_to_char(ch, "That guild is currently being edited by %s.\r\n",
          PERS(d->character, ch));
        return;
      }
    }
  }
  
  /****************************************************************************/
  /** Point d to the builder's descriptor.                                   **/
  /****************************************************************************/
  d = ch->desc;
  
  /****************************************************************************/
  /** Give the descriptor an OLC structure.                                  **/
  /****************************************************************************/
  if (d->olc) {
    mudlog(BRF, ADMLVL_IMMORT, TRUE,
      "SYSERR: do_oasis_gedit: Player already had olc structure.");
    free(d->olc);
  }
  
  CREATE(d->olc, struct oasis_olc_data, 1);
  
  /****************************************************************************/
  /** Find the zone.                                                         **/
  /****************************************************************************/
  if ((OLC_ZNUM(d) = real_zone_by_thing(number)) == NOWHERE) {
    send_to_char(ch, "Sorry, there is no zone for that number!\r\n");
    free(d->olc);
    d->olc = NULL;
    return;
  }
  
  /****************************************************************************/
  /** Everyone but IMPLs can only edit zones they have been assigned.        **/
  /****************************************************************************/
  if (!can_edit_zone(ch, OLC_ZNUM(d))) {
    send_to_char(ch, "You do not have permission to edit this zone.\r\n");
    
    /**************************************************************************/
    /** Free the OLC structure.                                              **/
    /**************************************************************************/
    free(d->olc);
    d->olc = NULL;
    return;
  }
  
  if (save) {
    send_to_char(ch, "Saving all guilds in zone %d.\r\n",
      zone_table[OLC_ZNUM(d)].number);
    mudlog(CMP, MAX(ADMLVL_BUILDER, GET_INVIS_LEV(ch)), TRUE,
      "OLC: %s saves guild info for zone %d.",
      GET_NAME(ch), zone_table[OLC_ZNUM(d)].number);
    
    /**************************************************************************/
    /** Save the guild to the guild file.                                    **/
    /**************************************************************************/
    gedit_save_to_disk(OLC_ZNUM(d));
    
    /**************************************************************************/
    /** Free the OLC structure.                                              **/
    /**************************************************************************/
    free(d->olc);
    d->olc = NULL;
    return;
  }
  
  OLC_NUM(d) = number;
  
  if ((real_num = real_guild(number)) != NOTHING)
    gedit_setup_existing(d, real_num);
  else
    gedit_setup_new(d);
  
  STATE(d) = CON_GEDIT;
  
  act("$n starts using OLC.", TRUE, d->character, 0, 0, TO_ROOM);
  SET_BIT_AR(PLR_FLAGS(ch), PLR_WRITING);
  
  mudlog(BRF, ADMLVL_IMMORT, TRUE, "OLC: %s starts editing zone %d allowed zone %d",
    GET_NAME(ch), zone_table[OLC_ZNUM(d)].number, GET_OLC_ZONE(ch));
}

void gedit_setup_new(struct descriptor_data *d)
{
	int i;
	struct guild_data *guild;

	/*. Alloc some guild shaped space . */
	CREATE(guild, struct guild_data, 1);

	/*. Some default values . */
	G_TRAINER(guild) = -1;
	G_OPEN(guild) = 0;
	G_CLOSE(guild) = 28;
	G_CHARGE(guild) = 1.0;
	for (i = 0; i < SW_ARRAY_MAX; i++)
		G_WITH_WHO(guild)[i] = 0;
	G_FUNC(guild) = NULL;
	G_MINLVL(guild) = 0;

	/*. Some default strings . */
	G_NO_SKILL(guild) = strdup("%s Sorry, but I don't know that one.");
	G_NO_GOLD(guild) = strdup("%s Sorry, but I'm gonna need more gold first.");

	/* init the wasteful skills and spells table */

	for (i = 0; i < SKILL_TABLE_SIZE; i++)
		G_SK_AND_SP(guild, i) = 0;

	OLC_GUILD(d) = guild;
	gedit_disp_menu(d);
}

/*-------------------------------------------------------------------*/

void gedit_setup_existing(struct descriptor_data *d, int rgm_num)
{
	/*. Alloc some guild shaped space . */
	CREATE(OLC_GUILD(d), struct guild_data, 1);
	copy_guild(OLC_GUILD(d), guild_index + rgm_num);
	gedit_disp_menu(d);
}

/*-------------------------------------------------------------------*/

/**************************************************************************
 Menu functions 
**************************************************************************/

/*-------------------------------------------------------------------*/

void gedit_select_skills_menu(struct descriptor_data *d)
{
  int i, j = 0, found = 0;
  struct guild_data *guild;

  guild = OLC_GUILD(d);
  clear_screen(d);

  write_to_output(d, "Skills known:\r\n");

  for (i = 0; i < SKILL_TABLE_SIZE; i++) {
    if(spell_info[i].name != "!UNUSED!" && spell_info[i].skilltype == SKTYPE_SKILL) {
      write_to_output(d, "@n[@c%-3s@n] %-3d %-10.10s  ", 
                      YESNO(G_SK_AND_SP(guild, i)), i, spell_info[i].name);
      j++;
      found = 1;
    }
    if (found && !(j % 3)) {
      found = 0;
      write_to_output(d, "\r\n");
    }
  }
  write_to_output(d, "\r\nEnter skill num, 0 to quit:  ");

  OLC_MODE(d) = GEDIT_SELECT_SKILLS;
}

/*-------------------------------------------------------------------*/

void gedit_select_spells_menu(struct descriptor_data *d)
{
  int i, j = 0, found = 0;
  struct guild_data *guild;

  guild = OLC_GUILD(d);
  clear_screen(d);

  write_to_output(d, "Spells known:\r\n");

  for (i = 0; i <= SKILL_TABLE_SIZE; i++) {
    if(spell_info[i].name != "!UNUSED!" && IS_SET(spell_info[i].skilltype, SKTYPE_SPELL)) {
      write_to_output(d, "@n[@c%-3s@n] %-3d %-10.10s  ",
                      YESNO(G_SK_AND_SP(guild, i)), i, spell_info[i].name);
      j++;
      found = 1;
    }
    if (found && !(j % 3)) {
      found = 0;
      write_to_output(d, "\r\n");
    }
  }
  write_to_output(d, "\r\nEnter spell num, 0 to quit:  ");

  OLC_MODE(d) = GEDIT_SELECT_SPELLS;
}

/*-------------------------------------------------------------------*/

void gedit_select_lang_menu(struct descriptor_data *d)
{
  int i, j = 0, found = 0;
  struct guild_data *guild;

  guild = OLC_GUILD(d);
  clear_screen(d);

  write_to_output(d, "Skills known:\r\n");

  for (i = 0; i < SKILL_TABLE_SIZE ; i++) {
    if(spell_info[i].name != "!UNUSED!" && IS_SET(spell_info[i].skilltype, SKTYPE_LANG)) {
      write_to_output(d, "@n[@c%-3s@n] %-3d %-10.10s  ",
                      YESNO(G_SK_AND_SP(guild, i)), i, spell_info[i].name);
      j++;
      found = 1;
    }
    if (found && !(j % 3)) {
      found = 0;
      write_to_output(d, "\r\n");
    }
  }
  write_to_output(d, "\r\nEnter skill num, 0 to quit:  ");

  OLC_MODE(d) = GEDIT_SELECT_LANGS;
}

/*-------------------------------------------------------------------*/

void gedit_select_wp_menu(struct descriptor_data *d)
{
  int i, j = 0, found = 0;
  struct guild_data *guild;

  guild = OLC_GUILD(d);
  clear_screen(d);

  write_to_output(d, "Skills known:\r\n");

  for (i = 0; i < SKILL_TABLE_SIZE; i++) {
    if(spell_info[i].name != "!UNUSED!" && IS_SET(spell_info[i].skilltype, SKTYPE_WEAPON)) {
      write_to_output(d, "@n[@c%-3s@n] %-3d %-10.10s  ",
                      YESNO(G_SK_AND_SP(guild, i)), i, spell_info[i].name);
      j++;
      found = 1;
    }
    if (found && !(j % 3)) {
      found = 0;
      write_to_output(d, "\r\n");
    }
  }
  write_to_output(d, "\r\nEnter skill num, 0 to quit:  ");

  OLC_MODE(d) = GEDIT_SELECT_WPS;
}

/*-------------------------------------------------------------------*/

void gedit_no_train_menu(struct descriptor_data *d)
{
  char bits[MAX_STRING_LENGTH];
  int i, count = 0;
  struct guild_data *guild;

  guild = OLC_GUILD(d);
  clear_screen(d);

  for (i = 0; i < NUM_TRADERS; i++) {
    write_to_output(d, "@g%2d@n) %-20.20s   %s", i + 1, trade_letters[i],
                    !(++count % 2) ? "\r\n" : "");
  }

  sprintbitarray(G_WITH_WHO(guild), trade_letters, sizeof(bits), bits);
  write_to_output(d, "\r\nCurrent train flags: @c%s@n\r\n"
                  "Enter choice, 0 to quit : ", bits);
  OLC_MODE(d) = GEDIT_NO_TRAIN;
}

/*-------------------------------------------------------------------*/
/*. Display main menu . */

void gedit_disp_menu(struct descriptor_data *d)
{
	struct guild_data *guild;
	char buf1[MAX_STRING_LENGTH];

	guild = OLC_GUILD(d);

	clear_screen(d);

	sprintbitarray(G_WITH_WHO(guild), trade_letters, sizeof(buf1), buf1);

	write_to_output(d, 
			  "-- Guild Number: [@c%d@n]\r\n"
			  "@g 0@n) Guild Master : [@c%d@n] @y%s\r\n"
			  "@g 1@n) Doesn't know skill:\r\n @y%s\r\n"
			  "@g 2@n) Player no gold:\r\n @y%s\r\n"
			  "@g 3@n) Open   :  [@c%d@n]\r\n"
			  "@g 4@n) Close  :  [@c%d@n]\r\n"
			  "@g 5@n) Charge :  [@c%3.1f@n]\r\n"
			  "@g 6@n) Minlvl :  [@c%d@n]\r\n"
			  "@g 7@n) Who to Train:  @c%s\r\n"
			  "@g 8@n) Spells Menu\r\n"
			  "@g 9@n) Skills Menu\r\n"
			  "@g A@n) Weapon Profs Menu\r\n"
			  "@g B@n) Languages Menu\r\n"
			  "@g Q@n) Quit\r\n"
			  "Enter Choice : ",

			  OLC_NUM(d),
			  (G_TRAINER(guild) == -1) ? -1 : mob_index[G_TRAINER(guild)].vnum,
			  (G_TRAINER(guild) == -1) ? "none" : mob_proto[G_TRAINER(guild)].short_descr,
			  G_NO_SKILL(guild),
			  G_NO_GOLD(guild),
			  G_OPEN(guild),
			  G_CLOSE(guild),
			  G_CHARGE(guild),
			  G_MINLVL(guild),
			  buf1);

	OLC_MODE(d) = GEDIT_MAIN_MENU;
}

/**************************************************************************
  The GARGANTUAN event handler
**************************************************************************/

void gedit_parse(struct descriptor_data *d, char *arg)
{
	int i;

	if (OLC_MODE(d) > GEDIT_NUMERICAL_RESPONSE) {
		if (!isdigit(arg[0]) && ((*arg == '-') && (!isdigit(arg[1])))) {
			write_to_output(d, "Field must be numerical, try again : ");
			return;
		}
	}
	switch (OLC_MODE(d)) {
/*-------------------------------------------------------------------*/
		case GEDIT_CONFIRM_SAVESTRING:
			switch (*arg) {
				case 'y':
				case 'Y':
					send_to_char(d->character, "Saving Guild to memory.\r\n");
					gedit_save_internally(d);
					mudlog(CMP, MAX(ADMLVL_BUILDER, GET_INVIS_LEV(d->character)), TRUE,
						  "OLC: %s edits guild %d", GET_NAME(d->character), OLC_NUM(d));
					if (CONFIG_OLC_SAVE) {
						gedit_save_to_disk(real_zone_by_thing(OLC_NUM(d)));
						write_to_output(d, "Guild %d saved to disk.\r\n", OLC_NUM(d));
					} else
						write_to_output(d, "Guild %d saved to memory.\r\n", OLC_NUM(d));
						cleanup_olc(d, CLEANUP_STRUCTS);
			        return;
				case 'n':
				case 'N':
					cleanup_olc(d, CLEANUP_ALL);
					return;
				default:
					write_to_output(d, "Invalid choice!\r\nDo you wish to save the guild? : ");
					return;
			}
			break;

/*-------------------------------------------------------------------*/
		case GEDIT_MAIN_MENU:
			i = 0;
			switch (*arg) {
				case 'q':
				case 'Q':
					if (OLC_VAL(d)) {		/*. Anything been changed? . */
						write_to_output(d,  "Do you wish to save the changes to the Guild? (y/n) : ");
						OLC_MODE(d) = GEDIT_CONFIRM_SAVESTRING;
					} else
						cleanup_olc(d, CLEANUP_ALL);
					return;
				case '0':
					OLC_MODE(d) = GEDIT_TRAINER;
					write_to_output(d, "Enter vnum of guild master : ");
					return;
				case '1':
					OLC_MODE(d) = GEDIT_NO_SKILL;
					i--;
					break;
				case '2':
					OLC_MODE(d) = GEDIT_NO_CASH;
					i--;
					break;
				case '3':
					OLC_MODE(d) = GEDIT_OPEN;
					write_to_output(d, "When does this shop open (a day has 28 hours) ? ");
					i++;
					break;
				case '4':
					OLC_MODE(d) = GEDIT_CLOSE;
					write_to_output(d, "When does this shop close (a day has 28 hours) ? ");
					i++;
					break;
				case '5':
					OLC_MODE(d) = GEDIT_CHARGE;
					i++;
					break;
				case '6':
					OLC_MODE(d) = GEDIT_MINLVL;
					write_to_output(d, "Minumum Level will Train: ");
					i++;
					return;
				case '7':
					OLC_MODE(d) = GEDIT_NO_TRAIN;
					gedit_no_train_menu(d);
					return;
				case '8':
					OLC_MODE(d) = GEDIT_SELECT_SPELLS;
					gedit_select_spells_menu(d);
					return;
				case '9':
					OLC_MODE(d) = GEDIT_SELECT_SKILLS;
					gedit_select_skills_menu(d);
					return;
				case 'a':
				case 'A':
					OLC_MODE(d) = GEDIT_SELECT_WPS;
					gedit_select_wp_menu(d);
					return;
				case 'b':
				case 'B':
					OLC_MODE(d) = GEDIT_SELECT_LANGS;
					gedit_select_lang_menu(d);
					return;
				default:
					gedit_disp_menu(d);
					return;
			}

				if (i == 0)
					break;
				else if (i == 1)
					write_to_output(d, "\r\nEnter new value : ");
				else if (i == -1)
					write_to_output(d, "\r\nEnter new text :\r\n] ");
				else
					write_to_output(d, "Oops...\r\n");
			return;
/*-------------------------------------------------------------------*/
			/*. String edits . */
		case GEDIT_NO_SKILL:
			gedit_modify_string(&G_NO_SKILL(OLC_GUILD(d)), arg);
			break;
		case GEDIT_NO_CASH:
			gedit_modify_string(&G_NO_GOLD(OLC_GUILD(d)), arg);
			break;

/*-------------------------------------------------------------------*/
			/*. Numerical responses . */

		case GEDIT_TRAINER:
			if (isdigit(*arg)) {
				i = atoi(arg);
				if ((i = atoi(arg)) != -1)
					if ((i = real_mobile(i)) == NOBODY) {
						write_to_output(d, "That mobile does not exist, try again : ");
						return;
					}
				G_TRAINER(OLC_GUILD(d)) = i;
				if (i == -1)
					break;
				/*. Fiddle with special procs . */
				G_FUNC(OLC_GUILD(d)) = mob_index[i].func;
				mob_index[i].func = guild;
				break;
			} else {
				write_to_output(d, "Invalid response.\r\n");
				gedit_disp_menu(d);
				return;
			}
		case GEDIT_OPEN:
			G_OPEN(OLC_GUILD(d)) = LIMIT(atoi(arg), 0, 28);
			break;
		case GEDIT_CLOSE:
			G_CLOSE(OLC_GUILD(d)) = LIMIT(atoi(arg), 0, 28);;
			break;
		case GEDIT_CHARGE:
			sscanf(arg, "%f", &G_CHARGE(OLC_GUILD(d)));
			break;
		case GEDIT_NO_TRAIN:
			    if ((i = LIMIT(atoi(arg), 0, NUM_TRADERS - 1)) > 0) {
				TOGGLE_BIT_AR(G_WITH_WHO(OLC_GUILD(d)), i - 1);
				gedit_no_train_menu(d);
				return;
			}
			break;

		case GEDIT_MINLVL:
			G_MINLVL(OLC_GUILD(d)) = MAX(atoi(arg), 0);
			break;

		case GEDIT_SELECT_SPELLS:
			i = atoi(arg);
			if (i == 0)
				break;
			i = MAX(1, MIN(i, SKILL_TABLE_SIZE));
			G_SK_AND_SP(OLC_GUILD(d), i) = !G_SK_AND_SP(OLC_GUILD(d), i);
			gedit_select_spells_menu(d);
			return;

		case GEDIT_SELECT_SKILLS:
			i = atoi(arg);
			if (i == 0)
				break;
			i = MAX(1, MIN(i, SKILL_TABLE_SIZE));
			G_SK_AND_SP(OLC_GUILD(d), i) = !G_SK_AND_SP(OLC_GUILD(d), i);
			gedit_select_skills_menu(d);
			return;

		case GEDIT_SELECT_WPS:
			i = atoi(arg);
			if (i == 0)
				break;
			i = MAX(1, MIN(i, SKILL_TABLE_SIZE));
			G_SK_AND_SP(OLC_GUILD(d), i) = !G_SK_AND_SP(OLC_GUILD(d), i);
			gedit_select_wp_menu(d);
			return;

		case GEDIT_SELECT_LANGS:
			i = atoi(arg);
			if (i == 0)
				break;
			i = MAX(1, MIN(i, SKILL_TABLE_SIZE));
			G_SK_AND_SP(OLC_GUILD(d), i) = !G_SK_AND_SP(OLC_GUILD(d), i);
			gedit_select_lang_menu(d);
			return;

/*-------------------------------------------------------------------*/
		default:
			/*. We should never get here . */
			cleanup_olc(d, CLEANUP_ALL);
			mudlog(BRF, ADMLVL_BUILDER, TRUE, "SYSERR: OLC: gedit_parse(): "
					 "Reached default case!");
			write_to_output(d, "Oops...\r\n");
			break;
	}
/*-------------------------------------------------------------------*/
/*. END OF CASE 
  If we get here, we have probably changed something, and now want to
  return to main menu.  Use OLC_VAL as a 'has changed' flag . */

	OLC_VAL(d) = 1;
	gedit_disp_menu(d);
}