1stMUD4.0/bin/
1stMUD4.0/doc/MPDocs/
1stMUD4.0/player/
1stMUD4.0/win32/
1stMUD4.0/win32/rom/
/**************************************************************************
*  Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,        *
*  Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe.   *
*                                                                         *
*  Merc Diku Mud improvements copyright (C) 1992, 1993 by Michael         *
*  Chastain, Michael Quan, and Mitchell Tse.                              *
*                                                                         *
*  In order to use any part of this Merc Diku Mud, you must comply with   *
*  both the original Diku license in 'license.doc' as well the Merc       *
*  license in 'license.txt'.  In particular, you may not remove either of *
*  these copyright notices.                                               *
*                                                                         *
*  Much time and thought has gone into this software and you are          *
*  benefiting.  We hope that you share your changes too.  What goes       *
*  around, comes around.                                                  *
***************************************************************************
*       ROM 2.4 is copyright 1993-1998 Russ Taylor                        *
*       ROM has been brought to you by the ROM consortium                 *
*           Russ Taylor (rtaylor@hypercube.org)                           *
*           Gabrielle Taylor (gtaylor@hypercube.org)                      *
*           Brian Moore (zump@rom.org)                                    *
*       By using this code, you have agreed to follow the terms of the    *
*       ROM license, in the file Rom24/doc/rom.license                    *
***************************************************************************
*       1stMUD ROM Derivative (c) 2001-2003 by Ryan Jennings              *
*            http://1stmud.dlmud.com/  <r-jenn@shaw.ca>                   *
***************************************************************************/
#include "merc.h"
#include "olc.h"
#include "recycle.h"
#include "lookup.h"
#include "interp.h"
#include "globals.h"
#include "tables.h"
#include "tablesave.h"

CHAR_DATA xChar;
PC_DATA xPc;
DESCRIPTOR_DATA xDesc;
OBJ_DATA xObj2;

typedef enum
{ SET_CHAR, SET_PC, SET_DESC, SET_OBJ }
set_t;

struct set_comm_type
{
	const char *name;
	void *argument;
	ED_FUN *function;
	const void *parameter;
	VALIDATE_FUN *validator;
};

const struct set_comm_type char_set_comm_table[] = {
	{"name", (void *) &xChar.name, olced_str, NULL, NULL},
	{"short", (void *) &xChar.short_descr, olced_str, NULL, NULL},
	{"long", (void *) &xChar.long_descr, olced_str, (void *) 1, NULL},
	{"description", (void *) &xChar.description, olced_desc, NULL, NULL},
	{"id", (void *) &xChar.id, olced_time, NULL, NULL},
	{"class", (void *) &xChar.Class, olced_mclass, (void *) MAX_REMORT,
	 NULL},
	{"stance", (void *) &xChar.stance, olced_stance, (void *) MAX_STANCE, NULL},
	{"stats", (void *) &xChar.perm_stat, olced_stats, (void *) STAT_MAX, NULL},
	{"damage", (void *) &xChar.damage[0], olced_dice, NULL, NULL},

	{"damtype", (void *) &xChar.dam_type, olced_poslookup,
	 (void *) attack_lookup, NULL},
	{"startpos", (void *) &xChar.start_pos, olced_flag, (void *) position_flags,
	 NULL},
	{"defpos", (void *) &xChar.default_pos, olced_flag, (void *) position_flags,
	 NULL},
	{"deity", (void *) &xChar.deity, olced_deity, NULL, NULL},
	{"master", (void *) &xChar.master, olced_getchar, NULL, NULL},
	{"leader", (void *) &xChar.leader, olced_getchar, NULL, NULL},
	{"fighting", (void *) &xChar.fighting, olced_getchar, NULL, NULL},
	{"reply", (void *) &xChar.reply, olced_getchar, NULL, NULL},
	{"pet", (void *) &xChar.pet, olced_getchar, NULL, NULL},
	{"hunting", (void *) &xChar.hunting, olced_getchar, NULL, NULL},
	{"prompt", (void *) &xChar.prompt, olced_str, NULL, NULL},
	{"prefix", (void *) &xChar.prefix, olced_str, NULL, NULL},
	{"sex", (void *) &xChar.sex, olced_flag, (void *) sex_flags, NULL},
	{"race", (void *) &xChar.race, olced_race, NULL, NULL},
	{"level", (void *) &xChar.level, olced_number, NULL, validate_level},
	{"trust", (void *) &xChar.trust, olced_number, NULL, validate_level},
	{"lines", (void *) &xChar.lines, olced_number, NULL, NULL},
	{"idle", (void *) &xChar.timer, olced_number, NULL, NULL},
	{"wait", (void *) &xChar.wait, olced_number, NULL, NULL},
	{"daze", (void *) &xChar.daze, olced_number, NULL, NULL},
	{"hit", (void *) &xChar.hit, olced_number_long, NULL, NULL},
	{"maxhit", (void *) &xChar.max_hit, olced_number_long, NULL, NULL},
	{"mana", (void *) &xChar.mana, olced_number_long, NULL, NULL},
	{"maxmana", (void *) &xChar.max_mana, olced_number_long, NULL, NULL},
	{"move", (void *) &xChar.move, olced_number_long, NULL, NULL},
	{"maxmove", (void *) &xChar.max_move, olced_number_long, NULL, NULL},
	{"gold", (void *) &xChar.gold, olced_number_long, NULL, NULL},
	{"silver", (void *) &xChar.silver, olced_number_long, NULL, NULL},
	{"exp", (void *) &xChar.exp, olced_number, NULL, NULL},
	{"act", (void *) &xChar.act, olced_flag, (void *) act_flags, NULL},
	{"comm", (void *) &xChar.comm, olced_flag, (void *) comm_flags, NULL},
	{"imm", (void *) &xChar.imm_flags, olced_flag, (void *) imm_flags, NULL},
	{"res", (void *) &xChar.res_flags, olced_flag, (void *) res_flags, NULL},
	{"vuln", (void *) &xChar.vuln_flags, olced_flag, (void *) vuln_flags, NULL},
	{"wizi", (void *) &xChar.invis_level, olced_number, NULL, validate_level},
	{"incog", (void *) &xChar.incog_level, olced_number, NULL, validate_level},
	{"aff", (void *) &xChar.affected_by, olced_flag, (void *) affect_flags,
	 NULL},
	{"position", (void *) &xChar.position, olced_flag, (void *) position_flags,
	 NULL},
	{"practice", (void *) &xChar.practice, olced_number, NULL, NULL},
	{"train", (void *) &xChar.train, olced_number, NULL, NULL},

	{"align", (void *) &xChar.alignment, olced_number, NULL, validate_align},
	{"wimpy", (void *) &xChar.wimpy, olced_number, NULL, NULL},
	{"form", (void *) &xChar.form, olced_flag, (void *) form_flags, NULL},
	{"rank", (void *) &xChar.rank, olced_number, NULL, NULL},
	{"parts", (void *) &xChar.parts, olced_flag, (void *) part_flags, NULL},
	{"size", (void *) &xChar.size, olced_flag, (void *) size_flags, NULL},
	{"material", (void *) &xChar.material, olced_str, NULL, NULL},
	{"hours", (void *) &xChar.played, olced_number, NULL, NULL},
	{"off", (void *) &xChar.off_flags, olced_flag, (void *) off_flags, NULL},
	{NULL, NULL, NULL, NULL, NULL}
};

const struct set_comm_type pc_set_comm_table[] = {
	{"poofin", (void *) &xPc.bamfin, olced_str, NULL, NULL},
	{"poofout", (void *) &xPc.bamfout, olced_str, NULL, NULL},
	{"title", (void *) &xPc.title, olced_str, NULL, NULL},
	{"whodesc", (void *) &xPc.who_descr, olced_str, NULL, NULL},
	{"permhit", (void *) &xPc.perm_hit, olced_number_long, NULL, NULL},
	{"permmana", (void *) &xPc.perm_mana, olced_number_long, NULL, NULL},
	{"permmove", (void *) &xPc.perm_move, olced_number_long, NULL, NULL},
	{"truesex", (void *) &xPc.true_sex, olced_flag, (void *) sex_flags,
	 NULL},
	{"points", (void *) &xPc.points, olced_number, NULL, NULL},
	{"questpoints", (void *) &xPc.questpoints, olced_number, NULL, NULL},
	{"goldbank", (void *) &xPc.gold_bank, olced_number_long, NULL, NULL},
	{"silvbank", (void *) &xPc.silver_bank, olced_number_long, NULL, NULL},
	{"shares", (void *) &xPc.shares, olced_number, NULL, NULL},
	{"condition", (void *) &xPc.condition, olced_array, (void *) 4, NULL},
	{"skill", NULL, olced_docomm, (void *) do_sskill, NULL},
	{"timezone", (void *) &xPc.timezone, olced_neglookup, (void *) tzone_lookup,
	 NULL},
	{"home", (void *) &xPc.home, olced_larray, (void *) MAX_HOUSE_ROOMS, NULL},
	{"hkey", (void *) &xPc.home_key, olced_number, NULL, NULL},
	{"trivia", (void *) &xPc.trivia, olced_number, NULL, NULL},
	{"security", (void *) &xPc.security, olced_number, NULL, NULL},
	{NULL, NULL, NULL, NULL, NULL}
};

const struct set_comm_type desc_set_comm_table[] = {
	{"descflags", (void *) &xDesc.d_flags, olced_flag,
	 (void *) desc_flags, NULL},
	{NULL, NULL, NULL, NULL, NULL}
};

const struct set_comm_type obj2_set_comm_table[] = {
	{"owner", (void *) &xObj2.owner, olced_str, NULL, NULL},
	{"enchanted", (void *) &xObj2.enchanted, olced_bool, NULL, NULL},
	{"name", (void *) &xObj2.name, olced_str, NULL, NULL},
	{"short", (void *) &xObj2.short_descr, olced_str, NULL, NULL},
	{"description", (void *) &xObj2.description, olced_str, (void *) 1, NULL},
	{"type", (void *) &xObj2.item_type, olced_flag, (void *) type_flags, NULL},

	{"extra", (void *) &xObj2.extra_flags, olced_flag, (void *) extra_flags,
	 NULL},
	{"wear", (void *) &xObj2.wear_flags, olced_flag, (void *) wear_flags, NULL},

	{"wloc", (void *) &xObj2.wear_loc, olced_flag,
	 (void *) wear_loc_strings, NULL},
	{"weight", (void *) &xObj2.weight, olced_number, NULL, NULL},
	{"cost", (void *) &xObj2.cost, olced_number_long, NULL, NULL},
	{"level", (void *) &xObj2.level, olced_number, NULL, validate_level},
	{"condition", (void *) &xObj2.condition, olced_number, NULL, NULL},
	{"timer", (void *) &xObj2.timer, olced_number, NULL, NULL},
	{"material", (void *) &xObj2.material, olced_str, NULL, NULL},
	{"value0", (void *) &xObj2.value[0], olced_number_long, NULL, NULL},
	{"value1", (void *) &xObj2.value[1], olced_number_long, NULL, NULL},
	{"value2", (void *) &xObj2.value[2], olced_number_long, NULL, NULL},
	{"value3", (void *) &xObj2.value[3], olced_number_long, NULL, NULL},
	{"value4", (void *) &xObj2.value[4], olced_number_long, NULL, NULL},
	{NULL, NULL, NULL, NULL, NULL}
};

const struct set_comm_type *get_set_table(set_t type)
{
	switch (type)
	{
	case SET_CHAR:
		return char_set_comm_table;
	case SET_PC:
		return pc_set_comm_table;
	case SET_DESC:
		return desc_set_comm_table;
	case SET_OBJ:
		return obj2_set_comm_table;
	default:
		return NULL;
	}
}

void show_set_commands(CHAR_DATA * ch, set_t type)
{
	int i;
	const struct set_comm_type *table = get_set_table(type);
	init_cols(ch, 5);

	for (i = 0; table[i].name != NULL; i++)
	{
		print_cols(chprint, ch, table[i].name);
		if (i + 1 % 5 == 0)
			chprintln(ch, "");
	}
	if (!done_newline)
		chprintln(ch, "");

	if (type == SET_CHAR)
	{
		show_set_commands(ch, SET_PC);
		show_set_commands(ch, SET_DESC);
	}
}

bool perform_set(CHAR_DATA * ch, set_t type, const char *argument, void *data)
{
	char arg[MIL];
	CHAR_DATA *vict = NULL;
	PC_DATA *pc;
	DESCRIPTOR_DATA *d;
	OBJ_DATA *obj;
	int temp;
	void *puntero;
	bool found = FALSE;
	const char *logline = argument;
	const struct set_comm_type *table = get_set_table(type);

	argument = one_argument(argument, arg);

	for (temp = 0; table[temp].name && !found; temp++)
	{
		if (LOWER(arg[0]) == LOWER(table[temp].name[0])
			&& !str_prefix(arg, table[temp].name))
		{
			switch (type)
			{
			case SET_CHAR:
				vict = (CHAR_DATA *) data;
				if (table[temp].argument)
					puntero =
						(void *) ((int) table[temp].argument - (int) &xChar +
								  (int) vict);
				else
					puntero = NULL;
				if ((*table[temp].function)
					(table[temp].name, ch, argument, puntero,
					 table[temp].parameter, table[temp].validator))
				{
					if (!IS_NPC(vict))
						save_char_obj(vict);
				}
				found = TRUE;
				break;
			case SET_PC:
				pc = (PC_DATA *) data;
				if (table[temp].argument)
					puntero =
						(void *) ((int) table[temp].argument - (int) &xPc +
								  (int) pc);
				else
					puntero = NULL;
				(*table[temp].function)
					(table[temp].name, ch, argument, puntero,
					 table[temp].parameter, table[temp].validator);
				found = TRUE;
				break;
			case SET_DESC:
				d = (DESCRIPTOR_DATA *) data;
				if (table[temp].argument)
					puntero =
						(void *) ((int) table[temp].argument - (int) &xDesc +
								  (int) d);
				else
					puntero = NULL;
				(*table[temp].function)
					(table[temp].name, ch, argument, puntero,
					 table[temp].parameter, table[temp].validator);
				found = TRUE;
				break;
			case SET_OBJ:
				obj = (OBJ_DATA *) data;
				if (table[temp].argument)
					puntero =
						(void *) ((int) table[temp].argument - (int) &xObj2 +
								  (int) obj);
				else
					puntero = NULL;
				if ((*table[temp].function)
					(table[temp].name, ch, argument, puntero,
					 table[temp].parameter, table[temp].validator))
				{
					if (obj->carried_by && !IS_NPC(obj->carried_by))
						save_char_obj(obj->carried_by);
				}
				found = TRUE;
				break;
			default:
				break;
			}
		}
	}
	if (!found && type == SET_CHAR)
	{
		vict = (CHAR_DATA *) data;
		if (vict->pcdata)
		{
			found = perform_set(ch, SET_PC, logline, vict->pcdata);
		}
		if (!found && vict->desc)
		{
			found = perform_set(ch, SET_DESC, logline, vict->desc);
		}
	}
	if (!found)
		show_set_commands(ch, type);
	return found;
}

CH_CMD(do_set_char)
{
	DESCRIPTOR_DATA d;
	bool result = FALSE;
	char name[MIL];
	CHAR_DATA *victim;

	argument = first_arg(argument, name, FALSE);

	if (IS_NULLSTR(name))
	{
		show_set_commands(ch, SET_CHAR);
		chprintln(ch, "Syntax: set char <name> <args...>");
		return;
	}

	if ((victim = get_char_world(ch, name)) == NULL)
	{
		result = load_char_obj(&d, name);
		if (result)
		{
			if (get_trust(d.character) > get_trust(ch))
			{
				chprintln(ch, "Sorry, you can't do that.");
				free_char(d.character);
				return;
			}
			victim = d.character;
		}
		else
		{
			chprintln(ch, "There is no such character.");
			free_char(d.character);
			return;
		}
	}
	perform_set(ch, SET_CHAR, argument, victim);
	if (result)
		free_char(victim);
	return;
}

CH_CMD(do_set_pc)
{
	DESCRIPTOR_DATA d;
	bool result = FALSE;
	char name[MIL];
	CHAR_DATA *victim;

	argument = first_arg(argument, name, FALSE);

	if (IS_NULLSTR(name))
	{
		show_set_commands(ch, SET_PC);
		chprintln(ch, "Syntax: set player <name> <args...>");
		return;
	}

	if ((victim = get_char_world(ch, name)) == NULL || IS_NPC(victim))
	{
		result = load_char_obj(&d, name);
		if (result)
		{
			if (get_trust(d.character) > get_trust(ch))
			{
				chprintln(ch, "Sorry, you can't do that.");
				free_char(d.character);
				return;
			}
			victim = d.character;
		}
		else
		{
			chprintln(ch, "There is no such player.");
			free_char(d.character);
			return;
		}
	}
	if (!victim->pcdata)
	{
		chprintln(ch, "No such player.");
		if (result)
			free_char(victim);
		return;
	}
	perform_set(ch, SET_PC, argument, victim->pcdata);
	if (result)
		free_char(victim);
	return;
}

CH_CMD(do_set_desc)
{
	char name[MIL];
	CHAR_DATA *victim;
	DESCRIPTOR_DATA *d = NULL;

	argument = first_arg(argument, name, FALSE);

	if (IS_NULLSTR(name))
	{
		show_set_commands(ch, SET_DESC);
		chprintln(ch, "Syntax: set descriptor <name> <args...>");
		return;
	}

	if ((victim = get_char_world(ch, name)) == NULL || !victim->desc)
	{
		if (is_number(name))
		{
			for (d = descriptor_first; d; d = d->next)
				if (atoi(name) == d->descriptor)
					break;
		}
		if (!d)
		{
			chprintln(ch, "Player has no descriptor.");
			return;
		}
	}
	else
		d = victim->desc;
	perform_set(ch, SET_DESC, argument, d);
	return;
}

CH_CMD(do_set_obj)
{
	OBJ_DATA *obj;
	char name[MIL];

	argument = first_arg(argument, name, FALSE);

	if (IS_NULLSTR(name))
	{
		show_set_commands(ch, SET_OBJ);
		chprintln(ch, "Syntax: set object <name> <args...>");
		return;
	}

	if ((obj = get_obj_world(ch, name)) == NULL)
	{
		chprintln(ch, "There is no such object.");
		return;
	}
	perform_set(ch, SET_OBJ, argument, obj);
	return;
}

CH_CMD(do_set_help)
{
	chprintln(ch, "Syntax: set char <name> <option> <value>\n\r"
			  "      : set obj <name> <option> <value>\n\r"
			  "      : set desc <name> <option> <value>\n\r"
			  "      : set skill <name> <skill|all> <value>");
}

CH_CMD(do_set)
{
	vinterpret(ch, argument, "character", do_set_char, "mobile", do_set_char,
			   "player", do_set_pc, "object", do_set_obj, "descriptor",
			   do_set_desc, "skill", do_sset, "spell", do_sset, NULL,
			   do_set_help);
}