mirror of
https://github.com/tbamud/tbamud.git
synced 2026-03-19 10:46:33 +01:00
1332 lines
39 KiB
C
1332 lines
39 KiB
C
/**************************************************************************
|
||
* File: oedit.c Part of tbaMUD *
|
||
* Usage: Oasis OLC - Objects. *
|
||
* *
|
||
* By Levork. Copyright 1996 Harvey Gilpin. 1997-2001 George Greer. *
|
||
**************************************************************************/
|
||
|
||
#include "conf.h"
|
||
#include "sysdep.h"
|
||
#include "structs.h"
|
||
#include "utils.h"
|
||
#include "comm.h"
|
||
#include "interpreter.h"
|
||
#include "spells.h"
|
||
#include "db.h"
|
||
#include "boards.h"
|
||
#include "constants.h"
|
||
#include "shop.h"
|
||
#include "genolc.h"
|
||
#include "genobj.h"
|
||
#include "genzon.h"
|
||
#include "oasis.h"
|
||
#include "improved-edit.h"
|
||
#include "dg_olc.h"
|
||
#include "fight.h"
|
||
#include "modify.h"
|
||
|
||
/* local functions */
|
||
static void oedit_setup_new(struct descriptor_data *d);
|
||
static void oedit_disp_container_flags_menu(struct descriptor_data *d);
|
||
static void oedit_disp_extradesc_menu(struct descriptor_data *d);
|
||
static void oedit_disp_prompt_apply_menu(struct descriptor_data *d);
|
||
static void oedit_liquid_type(struct descriptor_data *d);
|
||
static void oedit_disp_apply_menu(struct descriptor_data *d);
|
||
static void oedit_disp_weapon_menu(struct descriptor_data *d);
|
||
static void oedit_disp_spells_menu(struct descriptor_data *d);
|
||
static void oedit_disp_type_menu(struct descriptor_data *d);
|
||
static void oedit_disp_extra_menu(struct descriptor_data *d);
|
||
static void oedit_disp_wear_menu(struct descriptor_data *d);
|
||
static void oedit_disp_menu(struct descriptor_data *d);
|
||
static void oedit_disp_perm_menu(struct descriptor_data *d);
|
||
static void oedit_save_to_disk(int zone_num);
|
||
|
||
/* handy macro */
|
||
#define S_PRODUCT(s, i) ((s)->producing[(i)])
|
||
|
||
/* Label tables for object values by type */
|
||
|
||
/* Light */
|
||
static const char *light_val_labels[NUM_OBJ_VAL_POSITIONS] = {
|
||
"unused0", "unused1", "hours_left", "unused3",
|
||
"Value[4]", "Value[5]", "Value[6]", "Value[7]"
|
||
};
|
||
|
||
/* Scroll, Potion */
|
||
static const char *scroll_potion_val_labels[NUM_OBJ_VAL_POSITIONS] = {
|
||
"spell_level", "spell1", "spell2", "spell3",
|
||
"Value[4]", "Value[5]", "Value[6]", "Value[7]"
|
||
};
|
||
|
||
/* Wand, Staff */
|
||
static const char *wand_staff_val_labels[NUM_OBJ_VAL_POSITIONS] = {
|
||
"level", "max_charges", "remaining_charges", "spell",
|
||
"Value[4]", "Value[5]", "Value[6]", "Value[7]"
|
||
};
|
||
|
||
/* Weapon */
|
||
static const char *weapon_val_labels[NUM_OBJ_VAL_POSITIONS] = {
|
||
"dice_num", "dice_size", "weapon_type", "message_type",
|
||
"Value[4]", "Value[5]", "Value[6]", "Value[7]"
|
||
};
|
||
|
||
/* Armor */
|
||
static const char *armor_val_labels[NUM_OBJ_VAL_POSITIONS] = {
|
||
"piece_ac", "bulk", "magic_bonus", "stealth_disadv",
|
||
"durability", "str_requirement", "Value[6]", "Value[7]"
|
||
};
|
||
|
||
/* Container */
|
||
static const char *container_val_labels[NUM_OBJ_VAL_POSITIONS] = {
|
||
"capacity", "flags", "key_vnum", "corpse",
|
||
"Value[4]", "Value[5]", "Value[6]", "Value[7]"
|
||
};
|
||
|
||
/* Drinkcon / Fountain */
|
||
static const char *drink_val_labels[NUM_OBJ_VAL_POSITIONS] = {
|
||
"capacity", "contains", "liquid_type", "poisoned",
|
||
"Value[4]", "Value[5]", "Value[6]", "Value[7]"
|
||
};
|
||
|
||
/* Food */
|
||
static const char *food_val_labels[NUM_OBJ_VAL_POSITIONS] = {
|
||
"hours_full", "unused1", "unused2", "poisoned",
|
||
"Value[4]", "Value[5]", "Value[6]", "Value[7]"
|
||
};
|
||
|
||
/* Money */
|
||
static const char *money_val_labels[NUM_OBJ_VAL_POSITIONS] = {
|
||
"coins", "unused1", "unused2", "unused3",
|
||
"Value[4]", "Value[5]", "Value[6]", "Value[7]"
|
||
};
|
||
|
||
/* Furniture */
|
||
static const char *furniture_val_labels[NUM_OBJ_VAL_POSITIONS] = {
|
||
"max_seats", "current_occupants", "allowed_pos", "Value[3]",
|
||
"Value[4]", "Value[5]", "Value[6]", "Value[7]"
|
||
};
|
||
|
||
/* Generic fallback */
|
||
static const char *generic_val_labels[NUM_OBJ_VAL_POSITIONS] = {
|
||
"Value[0]", "Value[1]", "Value[2]", "Value[3]",
|
||
"Value[4]", "Value[5]", "Value[6]", "Value[7]"
|
||
};
|
||
|
||
static const char **get_val_labels(struct obj_data *obj)
|
||
{
|
||
switch (GET_OBJ_TYPE(obj)) {
|
||
case ITEM_LIGHT: return light_val_labels;
|
||
case ITEM_SCROLL:
|
||
case ITEM_POTION: return scroll_potion_val_labels;
|
||
case ITEM_WAND:
|
||
case ITEM_STAFF: return wand_staff_val_labels;
|
||
case ITEM_WEAPON: return weapon_val_labels;
|
||
case ITEM_ARMOR: return armor_val_labels;
|
||
case ITEM_CONTAINER: return container_val_labels;
|
||
case ITEM_DRINKCON:
|
||
case ITEM_FOUNTAIN: return drink_val_labels;
|
||
case ITEM_FOOD: return food_val_labels;
|
||
case ITEM_MONEY: return money_val_labels;
|
||
case ITEM_FURNITURE: return furniture_val_labels;
|
||
default: return generic_val_labels;
|
||
}
|
||
}
|
||
|
||
/* Utility and exported functions */
|
||
ACMD(do_oasis_oedit)
|
||
{
|
||
int number = NOWHERE, save = 0, real_num;
|
||
struct descriptor_data *d;
|
||
char buf1[MAX_STRING_LENGTH];
|
||
char buf2[MAX_STRING_LENGTH];
|
||
|
||
/* No building as a mob or while being forced. */
|
||
if (IS_NPC(ch) || !ch->desc || STATE(ch->desc) != CON_PLAYING)
|
||
return;
|
||
|
||
/* Parse any arguments. */
|
||
two_arguments(argument, buf1, buf2);
|
||
|
||
/* If there aren't any arguments they can't modify anything. */
|
||
if (!*buf1) {
|
||
send_to_char(ch, "Specify an object 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);
|
||
|
||
if (number < IDXTYPE_MIN || number > IDXTYPE_MAX) {
|
||
send_to_char(ch, "That object VNUM can't exist.\r\n");
|
||
return;
|
||
}
|
||
|
||
/* Check that whatever it is isn't already being edited. */
|
||
for (d = descriptor_list; d; d = d->next) {
|
||
if (STATE(d) == CON_OEDIT) {
|
||
if (d->olc && OLC_NUM(d) == number) {
|
||
send_to_char(ch, "That object is currently being edited by %s.\r\n",
|
||
PERS(d->character, ch));
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
|
||
/* Point d to the builder's descriptor (for easier typing later). */
|
||
d = ch->desc;
|
||
|
||
/* Give the descriptor an OLC structure. */
|
||
if (d->olc) {
|
||
mudlog(BRF, LVL_IMMORT, TRUE,
|
||
"SYSERR: do_oasis: Player already had olc structure.");
|
||
free(d->olc);
|
||
}
|
||
|
||
CREATE(d->olc, struct oasis_olc_data, 1);
|
||
|
||
/* Find the zone. */
|
||
OLC_ZNUM(d) = save ? real_zone(number) : real_zone_by_thing(number);
|
||
if (OLC_ZNUM(d) == NOWHERE) {
|
||
send_to_char(ch, "Sorry, there is no zone for that number!\r\n");
|
||
|
||
/* Free the descriptor's OLC structure. */
|
||
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_cannot_edit(ch, zone_table[OLC_ZNUM(d)].number);
|
||
/* Free the OLC structure. */
|
||
free(d->olc);
|
||
d->olc = NULL;
|
||
return;
|
||
}
|
||
|
||
/* If we need to save, save the objects. */
|
||
if (save) {
|
||
send_to_char(ch, "Saving all objects in zone %d.\r\n",
|
||
zone_table[OLC_ZNUM(d)].number);
|
||
mudlog(CMP, MAX(LVL_BUILDER, GET_INVIS_LEV(ch)), TRUE,
|
||
"OLC: %s saves object info for zone %d.", GET_NAME(ch),
|
||
zone_table[OLC_ZNUM(d)].number);
|
||
|
||
/* Save the objects in this zone. */
|
||
save_objects(OLC_ZNUM(d));
|
||
|
||
/* Free the descriptor's OLC structure. */
|
||
free(d->olc);
|
||
d->olc = NULL;
|
||
return;
|
||
}
|
||
|
||
OLC_NUM(d) = number;
|
||
|
||
/* If a new object, setup new, otherwise setup the existing object. */
|
||
if ((real_num = real_object(number)) != NOTHING)
|
||
oedit_setup_existing(d, real_num);
|
||
else
|
||
oedit_setup_new(d);
|
||
|
||
oedit_disp_menu(d);
|
||
STATE(d) = CON_OEDIT;
|
||
|
||
/* Send the OLC message to the players in the same room as the builder. */
|
||
act("$n starts using OLC.", TRUE, d->character, 0, 0, TO_ROOM);
|
||
SET_BIT_AR(PLR_FLAGS(ch), PLR_WRITING);
|
||
|
||
/* Log the OLC message. */
|
||
mudlog(CMP, MAX(LVL_IMMORT, GET_INVIS_LEV(ch)), TRUE, "OLC: %s starts editing zone %d allowed zone %d",
|
||
GET_NAME(ch), zone_table[OLC_ZNUM(d)].number, GET_OLC_ZONE(ch));
|
||
}
|
||
|
||
static void oedit_setup_new(struct descriptor_data *d)
|
||
{
|
||
CREATE(OLC_OBJ(d), struct obj_data, 1);
|
||
|
||
clear_object(OLC_OBJ(d));
|
||
OLC_OBJ(d)->name = strdup("unfinished object");
|
||
OLC_OBJ(d)->description = strdup("An unfinished object is lying here.");
|
||
OLC_OBJ(d)->short_description = strdup("an unfinished object");
|
||
SET_BIT_AR(GET_OBJ_WEAR(OLC_OBJ(d)), ITEM_WEAR_TAKE);
|
||
OLC_VAL(d) = 0;
|
||
OLC_DIRTY(d) = 0;
|
||
OLC_VAL_SLOT(d) = -1;
|
||
OLC_ITEM_TYPE(d) = OBJ_TRIGGER;
|
||
|
||
SCRIPT(OLC_OBJ(d)) = NULL;
|
||
OLC_OBJ(d)->proto_script = OLC_SCRIPT(d) = NULL;
|
||
}
|
||
|
||
void oedit_setup_existing(struct descriptor_data *d, int real_num)
|
||
{
|
||
struct obj_data *obj;
|
||
|
||
/* Allocate object in memory. */
|
||
CREATE(obj, struct obj_data, 1);
|
||
copy_object(obj, &obj_proto[real_num]);
|
||
|
||
/* Attach new object to player's descriptor. */
|
||
OLC_OBJ(d) = obj;
|
||
OLC_VAL(d) = 0;
|
||
OLC_DIRTY(d) = 0;
|
||
OLC_VAL_SLOT(d) = -1;
|
||
OLC_ITEM_TYPE(d) = OBJ_TRIGGER;
|
||
dg_olc_script_copy(d);
|
||
/* The edited obj must not have a script. It will be assigned to the updated
|
||
* obj later, after editing. */
|
||
SCRIPT(obj) = NULL;
|
||
OLC_OBJ(d)->proto_script = NULL;
|
||
}
|
||
|
||
void oedit_save_internally(struct descriptor_data *d)
|
||
{
|
||
int i;
|
||
obj_rnum robj_num;
|
||
struct descriptor_data *dsc;
|
||
struct obj_data *obj;
|
||
|
||
i = (real_object(OLC_NUM(d)) == NOTHING);
|
||
|
||
if ((robj_num = add_object(OLC_OBJ(d), OLC_NUM(d))) == NOTHING) {
|
||
log("oedit_save_internally: add_object failed.");
|
||
return;
|
||
}
|
||
|
||
/* Update triggers and free old proto list */
|
||
if (obj_proto[robj_num].proto_script &&
|
||
obj_proto[robj_num].proto_script != OLC_SCRIPT(d))
|
||
free_proto_script(&obj_proto[robj_num], OBJ_TRIGGER);
|
||
/* this will handle new instances of the object: */
|
||
obj_proto[robj_num].proto_script = OLC_SCRIPT(d);
|
||
|
||
/* this takes care of the objects currently in-game */
|
||
for (obj = object_list; obj; obj = obj->next) {
|
||
if (obj->item_number != robj_num)
|
||
continue;
|
||
/* remove any old scripts */
|
||
if (SCRIPT(obj))
|
||
extract_script(obj, OBJ_TRIGGER);
|
||
|
||
free_proto_script(obj, OBJ_TRIGGER);
|
||
copy_proto_script(&obj_proto[robj_num], obj, OBJ_TRIGGER);
|
||
assign_triggers(obj, OBJ_TRIGGER);
|
||
}
|
||
/* end trigger update */
|
||
|
||
if (!i) /* If it's not a new object, don't renumber. */
|
||
return;
|
||
|
||
/* Renumber produce in shops being edited. */
|
||
for (dsc = descriptor_list; dsc; dsc = dsc->next)
|
||
if (STATE(dsc) == CON_SEDIT)
|
||
for (i = 0; S_PRODUCT(OLC_SHOP(dsc), i) != NOTHING; i++)
|
||
if (S_PRODUCT(OLC_SHOP(dsc), i) >= robj_num)
|
||
S_PRODUCT(OLC_SHOP(dsc), i)++;
|
||
|
||
|
||
/* Update other people in zedit too. From: C.Raehl 4/27/99 */
|
||
for (dsc = descriptor_list; dsc; dsc = dsc->next)
|
||
if (STATE(dsc) == CON_ZEDIT)
|
||
for (i = 0; OLC_ZONE(dsc)->cmd[i].command != 'S'; i++)
|
||
switch (OLC_ZONE(dsc)->cmd[i].command) {
|
||
case 'P':
|
||
OLC_ZONE(dsc)->cmd[i].arg3 += (OLC_ZONE(dsc)->cmd[i].arg3 >= robj_num);
|
||
/* Fall through. */
|
||
case 'E':
|
||
case 'G':
|
||
case 'O':
|
||
OLC_ZONE(dsc)->cmd[i].arg1 += (OLC_ZONE(dsc)->cmd[i].arg1 >= robj_num);
|
||
break;
|
||
case 'R':
|
||
OLC_ZONE(dsc)->cmd[i].arg2 += (OLC_ZONE(dsc)->cmd[i].arg2 >= robj_num);
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
|
||
static void oedit_save_to_disk(int zone_num)
|
||
{
|
||
save_objects(zone_num);
|
||
}
|
||
|
||
/* Menu functions */
|
||
/* For container flags. */
|
||
static void oedit_disp_container_flags_menu(struct descriptor_data *d)
|
||
{
|
||
int i, columns = 0;
|
||
|
||
clear_screen(d);
|
||
write_to_output(d, "-- Container Flags Menu --\r\n");
|
||
|
||
for (i = 0; i < NUM_CONTAINER_FLAGS; i++) {
|
||
write_to_output(d, "%2d) %-15s%s", i, container_bits[i],
|
||
(++columns % 3 ? "" : "\r\n"));
|
||
}
|
||
|
||
if (columns % 3)
|
||
write_to_output(d, "\r\n");
|
||
|
||
write_to_output(d, "Enter container flag number (toggles on/off): ");
|
||
}
|
||
|
||
/* For extra descriptions. */
|
||
static void oedit_disp_extradesc_menu(struct descriptor_data *d)
|
||
{
|
||
struct extra_descr_data *extra_desc = OLC_DESC(d);
|
||
|
||
get_char_colors(d->character);
|
||
clear_screen(d);
|
||
write_to_output(d,
|
||
"Extra desc menu\r\n"
|
||
"%s1%s) Keywords: %s%s\r\n"
|
||
"%s2%s) Description:\r\n%s%s\r\n"
|
||
"%s3%s) Goto next description: %s\r\n"
|
||
"%s0%s) Quit\r\n"
|
||
"Enter choice : ",
|
||
|
||
grn, nrm, yel, (extra_desc->keyword && *extra_desc->keyword) ? extra_desc->keyword : "<NONE>",
|
||
grn, nrm, yel, (extra_desc->description && *extra_desc->description) ? extra_desc->description : "<NONE>",
|
||
grn, nrm, !extra_desc->next ? "Not set." : "Set.", grn, nrm);
|
||
OLC_MODE(d) = OEDIT_EXTRADESC_MENU;
|
||
}
|
||
|
||
/* Ask for *which* apply to edit. */
|
||
static void oedit_disp_prompt_apply_menu(struct descriptor_data *d)
|
||
{
|
||
char apply_buf[MAX_STRING_LENGTH];
|
||
int counter;
|
||
|
||
get_char_colors(d->character);
|
||
clear_screen(d);
|
||
|
||
for (counter = 0; counter < MAX_OBJ_AFFECT; counter++) {
|
||
if (OLC_OBJ(d)->affected[counter].modifier) {
|
||
sprinttype(OLC_OBJ(d)->affected[counter].location, apply_types, apply_buf, sizeof(apply_buf));
|
||
write_to_output(d, " %s%d%s) %+d to %s\r\n", grn, counter + 1, nrm,
|
||
OLC_OBJ(d)->affected[counter].modifier, apply_buf);
|
||
} else {
|
||
write_to_output(d, " %s%d%s) None.\r\n", grn, counter + 1, nrm);
|
||
}
|
||
}
|
||
write_to_output(d, "\r\nEnter affection to modify (0 to quit) : ");
|
||
OLC_MODE(d) = OEDIT_PROMPT_APPLY;
|
||
}
|
||
|
||
/* Ask for liquid type. */
|
||
static void oedit_liquid_type(struct descriptor_data *d)
|
||
{
|
||
int i, columns = 0;
|
||
|
||
clear_screen(d);
|
||
write_to_output(d, "-- Liquid Types Menu --\r\n");
|
||
|
||
for (i = 0; i < NUM_LIQ_TYPES; i++) {
|
||
write_to_output(d, "%2d) %-10s%s", i, drinks[i],
|
||
(++columns % 4 ? "" : "\r\n"));
|
||
}
|
||
|
||
if (columns % 4)
|
||
write_to_output(d, "\r\n");
|
||
|
||
write_to_output(d, "Enter liquid type number : ");
|
||
}
|
||
|
||
/* The actual apply to set. */
|
||
static void oedit_disp_apply_menu(struct descriptor_data *d)
|
||
{
|
||
get_char_colors(d->character);
|
||
clear_screen(d);
|
||
column_list(d->character, 0, apply_types, NUM_APPLIES, TRUE);
|
||
write_to_output(d, "\r\nEnter apply type (0 is no apply) : ");
|
||
OLC_MODE(d) = OEDIT_APPLY;
|
||
}
|
||
|
||
/* Weapon type. */
|
||
static void oedit_disp_weapon_menu(struct descriptor_data *d)
|
||
{
|
||
int i;
|
||
|
||
clear_screen(d);
|
||
write_to_output(d, "-- Weapon Types Menu --\r\n");
|
||
|
||
for (i = 0; i < NUM_ATTACK_TYPES; i++) {
|
||
write_to_output(d, "%2d) %s\r\n", i, attack_hit_text[i].singular);
|
||
}
|
||
|
||
write_to_output(d, "Enter weapon type number : ");
|
||
}
|
||
|
||
/* Spell type. */
|
||
static void oedit_disp_spells_menu(struct descriptor_data *d)
|
||
{
|
||
int i, columns = 0;
|
||
|
||
clear_screen(d);
|
||
write_to_output(d, "-- Spells Menu --\r\n");
|
||
|
||
for (i = 0; i < NUM_SPELLS; i++) {
|
||
if (*spell_info[i].name != '!')
|
||
write_to_output(d, "%3d) %-20s%s", i, spell_info[i].name,
|
||
(++columns % 3 ? "" : "\r\n"));
|
||
}
|
||
|
||
if (columns % 3)
|
||
write_to_output(d, "\r\n");
|
||
|
||
write_to_output(d, "Enter spell number (0 = none): ");
|
||
}
|
||
|
||
/* Display all object values dynamically, with labels for known slots */
|
||
/* Display all object values dynamically with labels based on type */
|
||
static void oedit_disp_values_menu(struct descriptor_data *d)
|
||
{
|
||
int i;
|
||
struct obj_data *obj = OLC_OBJ(d);
|
||
const char **labels;
|
||
|
||
/* Select appropriate labels for this item type */
|
||
switch (GET_OBJ_TYPE(obj)) {
|
||
case ITEM_ARMOR: labels = armor_val_labels; break;
|
||
case ITEM_WEAPON: labels = weapon_val_labels; break;
|
||
case ITEM_DRINKCON:
|
||
case ITEM_FOUNTAIN: labels = drink_val_labels; break;
|
||
case ITEM_CONTAINER: labels = container_val_labels; break;
|
||
case ITEM_FURNITURE: labels = furniture_val_labels; break;
|
||
default: labels = generic_val_labels; break;
|
||
}
|
||
|
||
write_to_output(d, "\r\n-- Object Values Menu --\r\n");
|
||
|
||
for (i = 0; i < NUM_OBJ_VAL_POSITIONS; i++) {
|
||
/* Hide current_occupants field for furniture - it's managed by the game engine */
|
||
if (GET_OBJ_TYPE(obj) == ITEM_FURNITURE && i == 1) {
|
||
write_to_output(d, "%2d) %-12s : %d (managed by game engine)\r\n",
|
||
i+1, labels[i], GET_OBJ_VAL(obj, i));
|
||
} else {
|
||
write_to_output(d, "%2d) %-12s : %d\r\n",
|
||
i+1, labels[i], GET_OBJ_VAL(obj, i));
|
||
}
|
||
}
|
||
|
||
write_to_output(d, "Q) Quit to main menu\r\nEnter choice : ");
|
||
|
||
OLC_MODE(d) = OEDIT_VALUES_MENU;
|
||
}
|
||
|
||
/* Object type. */
|
||
static void oedit_disp_type_menu(struct descriptor_data *d)
|
||
{
|
||
int counter, columns = 0;
|
||
|
||
get_char_colors(d->character);
|
||
clear_screen(d);
|
||
|
||
for (counter = 0; counter < NUM_ITEM_TYPES; counter++) {
|
||
write_to_output(d, "%s%2d%s) %-20.20s %s", grn, counter, nrm,
|
||
item_types[counter], !(++columns % 2) ? "\r\n" : "");
|
||
}
|
||
write_to_output(d, "\r\nEnter object type : ");
|
||
}
|
||
|
||
/* Object extra flags. */
|
||
static void oedit_disp_extra_menu(struct descriptor_data *d)
|
||
{
|
||
char buf[MAX_STRING_LENGTH];
|
||
int i, columns = 0;
|
||
|
||
clear_screen(d);
|
||
write_to_output(d, "-- Extra Flags Menu --\r\n");
|
||
|
||
for (i = 0; i < NUM_EXTRA_FLAGS; i++) {
|
||
/* Menu is 1-based for builders */
|
||
write_to_output(d, "%2d) %-20s%s", i + 1, extra_bits[i],
|
||
(++columns % 2 ? "" : "\r\n"));
|
||
}
|
||
if (columns % 2)
|
||
write_to_output(d, "\r\n");
|
||
|
||
/* Show current flags nicely */
|
||
sprintbitarray(GET_OBJ_EXTRA(OLC_OBJ(d)), extra_bits, EF_ARRAY_MAX, buf);
|
||
write_to_output(d, "\r\nObject flags: %s\r\n", buf);
|
||
|
||
write_to_output(d, "Enter object extra flag (0 to quit) : ");
|
||
}
|
||
|
||
/* Object perm flags. */
|
||
static void oedit_disp_perm_menu(struct descriptor_data *d)
|
||
{
|
||
char bits[MAX_STRING_LENGTH];
|
||
int counter, columns = 0;
|
||
|
||
get_char_colors(d->character);
|
||
clear_screen(d);
|
||
|
||
for (counter = 1; counter < NUM_AFF_FLAGS; counter++) {
|
||
write_to_output(d, "%s%2d%s) %-20.20s %s", grn, counter, nrm, affected_bits[counter], !(++columns % 2) ? "\r\n" : "");
|
||
}
|
||
sprintbitarray(GET_OBJ_AFFECT(OLC_OBJ(d)), affected_bits, EF_ARRAY_MAX, bits);
|
||
write_to_output(d, "\r\nObject permanent flags: %s%s%s\r\n"
|
||
"Enter object perm flag (0 to quit) : ", cyn, bits, nrm);
|
||
}
|
||
|
||
/* Object wear flags. */
|
||
static void oedit_disp_wear_menu(struct descriptor_data *d)
|
||
{
|
||
char bits[MAX_STRING_LENGTH];
|
||
int counter, columns = 0;
|
||
|
||
get_char_colors(d->character);
|
||
clear_screen(d);
|
||
|
||
for (counter = 0; counter < NUM_ITEM_WEARS; counter++) {
|
||
write_to_output(d, "%s%2d%s) %-20.20s %s", grn, counter + 1, nrm,
|
||
wear_bits[counter], !(++columns % 2) ? "\r\n" : "");
|
||
}
|
||
sprintbitarray(GET_OBJ_WEAR(OLC_OBJ(d)), wear_bits, TW_ARRAY_MAX, bits);
|
||
write_to_output(d, "\r\nWear flags: %s%s%s\r\n"
|
||
"Enter wear flag, 0 to quit : ", cyn, bits, nrm);
|
||
}
|
||
|
||
/* Display main menu. */
|
||
static void oedit_disp_menu(struct descriptor_data *d)
|
||
{
|
||
struct obj_data *obj;
|
||
char buf1[MAX_STRING_LENGTH], buf2[MAX_STRING_LENGTH];
|
||
|
||
obj = OLC_OBJ(d);
|
||
|
||
get_char_colors(d->character);
|
||
clear_screen(d);
|
||
|
||
/* Build buffers for type/flags */
|
||
sprinttype(GET_OBJ_TYPE(obj), item_types, buf1, sizeof(buf1));
|
||
sprintbitarray(GET_OBJ_EXTRA(obj), extra_bits, EF_ARRAY_MAX, buf2);
|
||
|
||
/* First part of menu */
|
||
write_to_output(d,
|
||
"-- Item Number : [%s%d%s]\r\n"
|
||
"%s1%s) Keywords : %s%s\r\n"
|
||
"%s2%s) S-Desc : %s%s\r\n"
|
||
"%s3%s) L-Desc :-\r\n%s%s\r\n"
|
||
"%s4%s) M-Desc :-\r\n%s%s"
|
||
"%s5%s) Type : %s%s\r\n"
|
||
"%s6%s) Extra flags : %s%s\r\n",
|
||
|
||
cyn, OLC_NUM(d), nrm,
|
||
grn, nrm, yel, (obj->name && *obj->name) ? obj->name : "undefined",
|
||
grn, nrm, yel, (obj->short_description && *obj->short_description) ? obj->short_description : "undefined",
|
||
grn, nrm, yel, (obj->description && *obj->description) ? obj->description : "undefined",
|
||
grn, nrm, yel, (obj->main_description && *obj->main_description) ? obj->main_description : "Not Set.\r\n",
|
||
grn, nrm, cyn, buf1,
|
||
grn, nrm, cyn, buf2
|
||
);
|
||
|
||
/* Wear flags and affects */
|
||
sprintbitarray(GET_OBJ_WEAR(obj), wear_bits, TW_ARRAY_MAX, buf1);
|
||
sprintbitarray(GET_OBJ_AFFECT(obj), affected_bits, AF_ARRAY_MAX, buf2);
|
||
|
||
/* Second half of menu */
|
||
write_to_output(d,
|
||
"%s7%s) Wear flags : %s%s\r\n"
|
||
"%s8%s) Weight : %s%d\r\n"
|
||
"%s9%s) Cost : %s%d\r\n"
|
||
"%sA%s) Cost/Day : %s%d\r\n"
|
||
"%sB%s) Timer : %s%d\r\n"
|
||
"%sM%s) Min Level : %s%d\r\n"
|
||
"%sP%s) Perm Affects: %s%s\r\n"
|
||
"%sS%s) Script : %s%s\r\n"
|
||
"%sW%s) Copy object\r\n"
|
||
"%sX%s) Delete object\r\n",
|
||
|
||
grn, nrm, cyn, buf1,
|
||
grn, nrm, cyn, GET_OBJ_WEIGHT(obj),
|
||
grn, nrm, cyn, GET_OBJ_COST(obj),
|
||
grn, nrm, cyn, GET_OBJ_RENT(obj),
|
||
grn, nrm, cyn, GET_OBJ_TIMER(obj),
|
||
grn, nrm, cyn, GET_OBJ_LEVEL(obj),
|
||
grn, nrm, cyn, buf2,
|
||
grn, nrm, cyn, OLC_SCRIPT(d) ? "Set." : "Not Set.",
|
||
grn, nrm,
|
||
grn, nrm
|
||
);
|
||
|
||
/* Unified values menu */
|
||
write_to_output(d,
|
||
"%sV%s) Edit object values (%d slots total)\r\n",
|
||
grn, nrm, NUM_OBJ_VAL_POSITIONS);
|
||
|
||
/* Quit */
|
||
write_to_output(d,
|
||
"%sQ%s) Quit\r\n"
|
||
"Enter choice : ",
|
||
grn, nrm);
|
||
|
||
OLC_MODE(d) = OEDIT_MAIN_MENU;
|
||
}
|
||
|
||
/* main loop (of sorts).. basically interpreter throws all input to here. */
|
||
void oedit_parse(struct descriptor_data *d, char *arg)
|
||
{
|
||
int number;
|
||
char *oldtext = NULL;
|
||
|
||
switch (OLC_MODE(d)) {
|
||
|
||
case OEDIT_CONFIRM_SAVESTRING:
|
||
switch (*arg) {
|
||
case 'y':
|
||
case 'Y':
|
||
oedit_save_internally(d);
|
||
mudlog(CMP, MAX(LVL_BUILDER, GET_INVIS_LEV(d->character)), TRUE,
|
||
"OLC: %s edits obj %d", GET_NAME(d->character), OLC_NUM(d));
|
||
if (CONFIG_OLC_SAVE) {
|
||
oedit_save_to_disk(real_zone_by_thing(OLC_NUM(d)));
|
||
write_to_output(d, "Object saved to disk.\r\n");
|
||
} else
|
||
write_to_output(d, "Object saved to memory.\r\n");
|
||
cleanup_olc(d, CLEANUP_ALL);
|
||
return;
|
||
case 'n':
|
||
case 'N':
|
||
OLC_OBJ(d)->proto_script = OLC_SCRIPT(d);
|
||
free_proto_script(OLC_OBJ(d), OBJ_TRIGGER);
|
||
cleanup_olc(d, CLEANUP_ALL);
|
||
return;
|
||
case 'a':
|
||
case 'A':
|
||
oedit_disp_menu(d);
|
||
return;
|
||
default:
|
||
write_to_output(d, "Invalid choice!\r\n");
|
||
write_to_output(d, "Do you wish to save your changes? : \r\n");
|
||
return;
|
||
}
|
||
|
||
case OEDIT_MAIN_MENU:
|
||
switch (*arg) {
|
||
case 'q': case 'Q':
|
||
if (OLC_DIRTY(d)) {
|
||
write_to_output(d, "Do you wish to save your changes? : ");
|
||
OLC_MODE(d) = OEDIT_CONFIRM_SAVESTRING;
|
||
} else
|
||
cleanup_olc(d, CLEANUP_ALL);
|
||
return;
|
||
case '1':
|
||
write_to_output(d, "Enter keywords : ");
|
||
OLC_MODE(d) = OEDIT_KEYWORD;
|
||
break;
|
||
case '2':
|
||
write_to_output(d, "Enter short desc : ");
|
||
OLC_MODE(d) = OEDIT_SHORTDESC;
|
||
break;
|
||
case '3':
|
||
write_to_output(d, "Enter long desc :-\r\n| ");
|
||
OLC_MODE(d) = OEDIT_LONGDESC;
|
||
break;
|
||
case '4':
|
||
OLC_MODE(d) = OEDIT_MAINDESC;
|
||
send_editor_help(d);
|
||
write_to_output(d, "Enter action description:\r\n\r\n");
|
||
if (OLC_OBJ(d)->main_description) {
|
||
write_to_output(d, "%s", OLC_OBJ(d)->main_description);
|
||
oldtext = strdup(OLC_OBJ(d)->main_description);
|
||
}
|
||
string_write(d, &OLC_OBJ(d)->main_description,
|
||
MAX_MESSAGE_LENGTH, 0, oldtext);
|
||
OLC_DIRTY(d) = 1;
|
||
break;
|
||
case '5':
|
||
oedit_disp_type_menu(d);
|
||
OLC_MODE(d) = OEDIT_TYPE;
|
||
break;
|
||
case '6':
|
||
oedit_disp_extra_menu(d);
|
||
OLC_MODE(d) = OEDIT_EXTRAS;
|
||
break;
|
||
case '7':
|
||
oedit_disp_wear_menu(d);
|
||
OLC_MODE(d) = OEDIT_WEAR;
|
||
break;
|
||
case '8':
|
||
write_to_output(d, "Enter weight : ");
|
||
OLC_MODE(d) = OEDIT_WEIGHT;
|
||
break;
|
||
case '9':
|
||
write_to_output(d, "Enter cost : ");
|
||
OLC_MODE(d) = OEDIT_COST;
|
||
break;
|
||
case 'a': case 'A':
|
||
write_to_output(d, "Enter cost per day : ");
|
||
OLC_MODE(d) = OEDIT_COSTPERDAY;
|
||
break;
|
||
case 'b': case 'B':
|
||
write_to_output(d, "Enter timer : ");
|
||
OLC_MODE(d) = OEDIT_TIMER;
|
||
break;
|
||
case 'd': case 'D':
|
||
oedit_disp_prompt_apply_menu(d);
|
||
break;
|
||
case 'e': case 'E':
|
||
if (OLC_OBJ(d)->ex_description == NULL) {
|
||
CREATE(OLC_OBJ(d)->ex_description, struct extra_descr_data, 1);
|
||
OLC_OBJ(d)->ex_description->next = NULL;
|
||
}
|
||
OLC_DESC(d) = OLC_OBJ(d)->ex_description;
|
||
oedit_disp_extradesc_menu(d);
|
||
break;
|
||
case 'm': case 'M':
|
||
write_to_output(d, "Enter new minimum level: ");
|
||
OLC_MODE(d) = OEDIT_LEVEL;
|
||
break;
|
||
case 'p': case 'P':
|
||
oedit_disp_perm_menu(d);
|
||
OLC_MODE(d) = OEDIT_PERM;
|
||
break;
|
||
case 's': case 'S':
|
||
OLC_SCRIPT_EDIT_MODE(d) = SCRIPT_MAIN_MENU;
|
||
OLC_MODE(d) = OLC_SCRIPT_EDIT;
|
||
dg_script_menu(d);
|
||
return;
|
||
case 'V': case 'v':
|
||
oedit_disp_values_menu(d);
|
||
return;
|
||
case 'w': case 'W':
|
||
write_to_output(d, "Copy what object (vnum or 0 to cancel): ");
|
||
OLC_MODE(d) = OEDIT_COPY;
|
||
break;
|
||
case 'x': case 'X':
|
||
write_to_output(d, "Are you sure you want to delete this object? ");
|
||
OLC_MODE(d) = OEDIT_DELETE;
|
||
break;
|
||
default:
|
||
oedit_disp_menu(d);
|
||
break;
|
||
}
|
||
return;
|
||
|
||
case OLC_SCRIPT_EDIT:
|
||
{
|
||
/* Optional: clean, immediate quit without extra DG reprint */
|
||
if (arg && (arg[0] == 'q' || arg[0] == 'Q') && arg[1] == '\0') {
|
||
OLC_MODE(d) = OEDIT_MAIN_MENU;
|
||
oedit_disp_menu(d);
|
||
return;
|
||
}
|
||
|
||
/* Let DG handle input first. It returns non-zero to STAY in editor. */
|
||
if (dg_script_edit_parse(d, arg)) {
|
||
/* Still inside DG’s triggers UI (possibly mid-prompt like “pos, vnum”) */
|
||
return;
|
||
}
|
||
|
||
/* Return value 0 means DG editor is finished -> go back to OEDIT menu */
|
||
OLC_MODE(d) = OEDIT_MAIN_MENU;
|
||
oedit_disp_menu(d);
|
||
return;
|
||
}
|
||
|
||
case OEDIT_KEYWORD:
|
||
if (!genolc_checkstring(d, arg)) {
|
||
write_to_output(d, "Invalid keywords. Try again: ");
|
||
return; /* stay in OEDIT_KEYWORD waiting for a valid line */
|
||
}
|
||
if (OLC_OBJ(d)->name)
|
||
free(OLC_OBJ(d)->name);
|
||
OLC_OBJ(d)->name = str_udup(arg);
|
||
OLC_DIRTY(d) = 1;
|
||
OLC_MODE(d) = OEDIT_MAIN_MENU;
|
||
oedit_disp_menu(d);
|
||
return;
|
||
|
||
case OEDIT_SHORTDESC:
|
||
if (!genolc_checkstring(d, arg)) {
|
||
write_to_output(d, "Invalid short desc. Try again: ");
|
||
return; /* stay in OEDIT_SHORTDESC */
|
||
}
|
||
if (OLC_OBJ(d)->short_description)
|
||
free(OLC_OBJ(d)->short_description);
|
||
OLC_OBJ(d)->short_description = str_udup(arg);
|
||
OLC_DIRTY(d) = 1;
|
||
OLC_MODE(d) = OEDIT_MAIN_MENU;
|
||
oedit_disp_menu(d);
|
||
return;
|
||
|
||
case OEDIT_LONGDESC:
|
||
if (!genolc_checkstring(d, arg)) {
|
||
write_to_output(d, "Invalid long desc. Try again: ");
|
||
return; /* stay in OEDIT_LONGDESC */
|
||
}
|
||
if (OLC_OBJ(d)->description)
|
||
free(OLC_OBJ(d)->description);
|
||
OLC_OBJ(d)->description = str_udup(arg);
|
||
OLC_DIRTY(d) = 1;
|
||
OLC_MODE(d) = OEDIT_MAIN_MENU;
|
||
oedit_disp_menu(d);
|
||
return;
|
||
|
||
case OEDIT_MAINDESC:
|
||
/* Multi-line editor is correct here, requires '@' to finish */
|
||
send_editor_help(d);
|
||
write_to_output(d, "Enter action description:\r\n\r\n");
|
||
if (OLC_OBJ(d)->main_description) {
|
||
write_to_output(d, "%s", OLC_OBJ(d)->main_description);
|
||
oldtext = strdup(OLC_OBJ(d)->main_description);
|
||
}
|
||
string_write(d, &OLC_OBJ(d)->main_description, MAX_MESSAGE_LENGTH, 0, oldtext);
|
||
OLC_DIRTY(d) = 1;
|
||
return;
|
||
|
||
case OEDIT_TYPE:
|
||
number = atoi(arg);
|
||
if (number < 0 || number >= NUM_ITEM_TYPES) {
|
||
write_to_output(d, "Invalid choice, try again : ");
|
||
return;
|
||
}
|
||
GET_OBJ_TYPE(OLC_OBJ(d)) = number;
|
||
/* Reset values when type changes */
|
||
for (int i = 0; i < NUM_OBJ_VAL_POSITIONS; i++)
|
||
GET_OBJ_VAL(OLC_OBJ(d), i) = 0;
|
||
|
||
OLC_DIRTY(d) = 1;
|
||
OLC_MODE(d) = OEDIT_MAIN_MENU;
|
||
oedit_disp_menu(d);
|
||
return;
|
||
|
||
case OEDIT_EXTRAS:
|
||
number = atoi(arg);
|
||
if (number < 0 || number > NUM_EXTRA_FLAGS) {
|
||
oedit_disp_extra_menu(d);
|
||
return;
|
||
} else if (number == 0) {
|
||
/* exit extras submenu */
|
||
OLC_MODE(d) = OEDIT_MAIN_MENU;
|
||
oedit_disp_menu(d);
|
||
return;
|
||
} else {
|
||
/* Toggle: user picks 1..N, bit index is 0..N-1 */
|
||
TOGGLE_BIT_AR(GET_OBJ_EXTRA(OLC_OBJ(d)), (number - 1));
|
||
OLC_DIRTY(d) = 1;
|
||
oedit_disp_extra_menu(d);
|
||
return;
|
||
}
|
||
|
||
case OEDIT_WEAR:
|
||
number = atoi(arg);
|
||
if (number < 0 || number > NUM_ITEM_WEARS) {
|
||
write_to_output(d, "That's not a valid choice!\r\n");
|
||
oedit_disp_wear_menu(d);
|
||
return;
|
||
} else if (number == 0) {
|
||
/* exit wear submenu */
|
||
OLC_MODE(d) = OEDIT_MAIN_MENU;
|
||
oedit_disp_menu(d);
|
||
return;
|
||
} else {
|
||
TOGGLE_BIT_AR(GET_OBJ_WEAR(OLC_OBJ(d)), (number - 1));
|
||
OLC_DIRTY(d) = 1;
|
||
oedit_disp_wear_menu(d);
|
||
return;
|
||
}
|
||
|
||
case OEDIT_WEIGHT:
|
||
GET_OBJ_WEIGHT(OLC_OBJ(d)) = LIMIT(atoi(arg), 0, MAX_OBJ_WEIGHT);
|
||
OLC_DIRTY(d) = 1;
|
||
OLC_MODE(d) = OEDIT_MAIN_MENU;
|
||
oedit_disp_menu(d);
|
||
return;
|
||
|
||
case OEDIT_COST:
|
||
GET_OBJ_COST(OLC_OBJ(d)) = LIMIT(atoi(arg), 0, MAX_OBJ_COST);
|
||
OLC_DIRTY(d) = 1;
|
||
OLC_MODE(d) = OEDIT_MAIN_MENU;
|
||
oedit_disp_menu(d);
|
||
return;
|
||
|
||
case OEDIT_COSTPERDAY:
|
||
GET_OBJ_RENT(OLC_OBJ(d)) = LIMIT(atoi(arg), 0, MAX_OBJ_RENT);
|
||
OLC_DIRTY(d) = 1;
|
||
OLC_MODE(d) = OEDIT_MAIN_MENU;
|
||
oedit_disp_menu(d);
|
||
return;
|
||
|
||
case OEDIT_TIMER:
|
||
GET_OBJ_TIMER(OLC_OBJ(d)) = LIMIT(atoi(arg), 0, MAX_OBJ_TIMER);
|
||
OLC_DIRTY(d) = 1;
|
||
OLC_MODE(d) = OEDIT_MAIN_MENU;
|
||
oedit_disp_menu(d);
|
||
return;
|
||
|
||
case OEDIT_LEVEL:
|
||
GET_OBJ_LEVEL(OLC_OBJ(d)) = LIMIT(atoi(arg), 0, LVL_IMPL);
|
||
OLC_DIRTY(d) = 1;
|
||
OLC_MODE(d) = OEDIT_MAIN_MENU;
|
||
oedit_disp_menu(d);
|
||
return;
|
||
|
||
case OEDIT_PERM:
|
||
if ((number = atoi(arg)) == 0) {
|
||
/* exit perm affects submenu */
|
||
OLC_MODE(d) = OEDIT_MAIN_MENU;
|
||
oedit_disp_menu(d);
|
||
return;
|
||
}
|
||
if (number > 0 && number < NUM_AFF_FLAGS) {
|
||
if (number != AFF_CHARM) {
|
||
TOGGLE_BIT_AR(GET_OBJ_AFFECT(OLC_OBJ(d)), number);
|
||
}
|
||
OLC_DIRTY(d) = 1;
|
||
}
|
||
oedit_disp_perm_menu(d);
|
||
return;
|
||
|
||
/* === Values menu unified === */
|
||
case OEDIT_VALUES_MENU:
|
||
if (*arg == 'Q' || *arg == 'q') {
|
||
oedit_disp_menu(d);
|
||
return;
|
||
} else {
|
||
int i = atoi(arg) - 1;
|
||
if (i >= 0 && i < NUM_OBJ_VAL_POSITIONS) {
|
||
/* Prevent editing current_occupants for furniture - it's managed by the game engine */
|
||
if (GET_OBJ_TYPE(OLC_OBJ(d)) == ITEM_FURNITURE && i == 1) {
|
||
write_to_output(d, "The current_occupants field is managed by the game engine and cannot be edited manually.\r\n");
|
||
oedit_disp_values_menu(d);
|
||
return;
|
||
}
|
||
|
||
OLC_VAL_SLOT(d) = i;
|
||
const char **labels = get_val_labels(OLC_OBJ(d));
|
||
|
||
if (GET_OBJ_TYPE(OLC_OBJ(d)) == ITEM_WEAPON && i == 2) {
|
||
oedit_disp_weapon_menu(d);
|
||
OLC_MODE(d) = OEDIT_VALUE_X;
|
||
return;
|
||
}
|
||
if ((GET_OBJ_TYPE(OLC_OBJ(d)) == ITEM_SCROLL ||
|
||
GET_OBJ_TYPE(OLC_OBJ(d)) == ITEM_POTION ||
|
||
GET_OBJ_TYPE(OLC_OBJ(d)) == ITEM_WAND ||
|
||
GET_OBJ_TYPE(OLC_OBJ(d)) == ITEM_STAFF) &&
|
||
(i == 1 || i == 2 || i == 3)) {
|
||
oedit_disp_spells_menu(d);
|
||
OLC_MODE(d) = OEDIT_VALUE_X;
|
||
return;
|
||
}
|
||
if ((GET_OBJ_TYPE(OLC_OBJ(d)) == ITEM_DRINKCON ||
|
||
GET_OBJ_TYPE(OLC_OBJ(d)) == ITEM_FOUNTAIN) &&
|
||
i == 2) {
|
||
oedit_liquid_type(d);
|
||
OLC_MODE(d) = OEDIT_VALUE_X;
|
||
return;
|
||
}
|
||
if (GET_OBJ_TYPE(OLC_OBJ(d)) == ITEM_CONTAINER && i == 1) {
|
||
oedit_disp_container_flags_menu(d);
|
||
OLC_MODE(d) = OEDIT_VALUE_X;
|
||
return;
|
||
}
|
||
|
||
write_to_output(d, "Enter new integer for %s : ", labels[i]);
|
||
OLC_MODE(d) = OEDIT_VALUE_X;
|
||
} else {
|
||
write_to_output(d, "Invalid choice.\r\n");
|
||
oedit_disp_values_menu(d);
|
||
}
|
||
}
|
||
break;
|
||
|
||
case OEDIT_VALUE_X:
|
||
{
|
||
int i = OLC_VAL_SLOT(d);
|
||
int number = atoi(arg);
|
||
|
||
/* --- Armor-specific semantics --- */
|
||
if (GET_OBJ_TYPE(OLC_OBJ(d)) == ITEM_ARMOR) {
|
||
if (i == VAL_ARMOR_STEALTH_DISADV /* 3 */) {
|
||
GET_OBJ_VAL(OLC_OBJ(d), i) = (number != 0) ? 1 : 0;
|
||
OLC_DIRTY(d) = 1;
|
||
oedit_disp_values_menu(d);
|
||
return;
|
||
}
|
||
if (i == VAL_ARMOR_STR_REQ /* 5 */) {
|
||
/* 0 disables the requirement; otherwise accept a sane STR range */
|
||
if (number < 0 || number > 25) {
|
||
write_to_output(d, "Enter STR requirement (0 disables, 3..25 typical): ");
|
||
return; /* stay in OEDIT_VALUE_X for a valid number */
|
||
}
|
||
GET_OBJ_VAL(OLC_OBJ(d), i) = number;
|
||
OLC_DIRTY(d) = 1;
|
||
oedit_disp_values_menu(d);
|
||
return;
|
||
}
|
||
}
|
||
|
||
/* --- Existing special cases (weapon/liquid/spells/container) remain here --- */
|
||
if (GET_OBJ_TYPE(OLC_OBJ(d)) == ITEM_WEAPON && i == 2) {
|
||
if (number < 0 || number >= NUM_ATTACK_TYPES) {
|
||
oedit_disp_weapon_menu(d);
|
||
return;
|
||
}
|
||
GET_OBJ_VAL(OLC_OBJ(d), i) = number;
|
||
OLC_DIRTY(d) = 1;
|
||
oedit_disp_values_menu(d);
|
||
return;
|
||
}
|
||
else if ((GET_OBJ_TYPE(OLC_OBJ(d)) == ITEM_SCROLL ||
|
||
GET_OBJ_TYPE(OLC_OBJ(d)) == ITEM_POTION ||
|
||
GET_OBJ_TYPE(OLC_OBJ(d)) == ITEM_WAND ||
|
||
GET_OBJ_TYPE(OLC_OBJ(d)) == ITEM_STAFF) &&
|
||
(i == 1 || i == 2 || i == 3)) {
|
||
if (number < 0 || number >= NUM_SPELLS) {
|
||
oedit_disp_spells_menu(d);
|
||
return;
|
||
}
|
||
GET_OBJ_VAL(OLC_OBJ(d), i) = number;
|
||
OLC_DIRTY(d) = 1;
|
||
oedit_disp_values_menu(d);
|
||
return;
|
||
}
|
||
else if ((GET_OBJ_TYPE(OLC_OBJ(d)) == ITEM_DRINKCON ||
|
||
GET_OBJ_TYPE(OLC_OBJ(d)) == ITEM_FOUNTAIN) &&
|
||
i == 2) {
|
||
if (number < 0 || number >= NUM_LIQ_TYPES) {
|
||
oedit_liquid_type(d);
|
||
return;
|
||
}
|
||
GET_OBJ_VAL(OLC_OBJ(d), i) = number;
|
||
OLC_DIRTY(d) = 1;
|
||
oedit_disp_values_menu(d);
|
||
return;
|
||
}
|
||
else if (GET_OBJ_TYPE(OLC_OBJ(d)) == ITEM_CONTAINER && i == 1) {
|
||
extern const int NUM_CONTAINER_FLAGS;
|
||
if (number < 0 || number >= NUM_CONTAINER_FLAGS) {
|
||
oedit_disp_container_flags_menu(d);
|
||
return;
|
||
}
|
||
TOGGLE_BIT(GET_OBJ_VAL(OLC_OBJ(d), i), 1 << number);
|
||
OLC_DIRTY(d) = 1;
|
||
oedit_disp_values_menu(d);
|
||
return;
|
||
}
|
||
|
||
/* --- Default assignment for other slots/types --- */
|
||
GET_OBJ_VAL(OLC_OBJ(d), i) = number;
|
||
OLC_DIRTY(d) = 1;
|
||
oedit_disp_values_menu(d);
|
||
return;
|
||
}
|
||
|
||
/* === Apply editing === */
|
||
case OEDIT_PROMPT_APPLY:
|
||
if ((number = atoi(arg)) == 0) break;
|
||
else if (number < 0 || number > MAX_OBJ_AFFECT) {
|
||
oedit_disp_prompt_apply_menu(d);
|
||
return;
|
||
}
|
||
OLC_VAL(d) = number - 1;
|
||
OLC_MODE(d) = OEDIT_APPLY;
|
||
oedit_disp_apply_menu(d);
|
||
return;
|
||
|
||
case OEDIT_APPLY:
|
||
if (((number = atoi(arg)) == 0) || ((number = atoi(arg)) == 1)) {
|
||
OLC_OBJ(d)->affected[OLC_VAL(d)].location = 0;
|
||
OLC_OBJ(d)->affected[OLC_VAL(d)].modifier = 0;
|
||
oedit_disp_prompt_apply_menu(d);
|
||
} else if (number < 0 || number > NUM_APPLIES)
|
||
oedit_disp_apply_menu(d);
|
||
else {
|
||
int counter;
|
||
if (GET_LEVEL(d->character) < LVL_IMPL) {
|
||
for (counter = 0; counter < MAX_OBJ_AFFECT; counter++) {
|
||
if (OLC_OBJ(d)->affected[counter].location == number) {
|
||
write_to_output(d, "Object already has that apply.");
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
OLC_OBJ(d)->affected[OLC_VAL(d)].location = number - 1;
|
||
write_to_output(d, "Modifier : ");
|
||
OLC_DIRTY(d) = 1;
|
||
OLC_MODE(d) = OEDIT_APPLYMOD;
|
||
}
|
||
return;
|
||
|
||
case OEDIT_APPLYMOD:
|
||
OLC_OBJ(d)->affected[OLC_VAL(d)].modifier = atoi(arg);
|
||
OLC_DIRTY(d) = 1;
|
||
oedit_disp_prompt_apply_menu(d);
|
||
return;
|
||
|
||
/* === Extra descriptions === */
|
||
case OEDIT_EXTRADESC_KEY:
|
||
if (genolc_checkstring(d, arg)) {
|
||
if (OLC_DESC(d)->keyword) free(OLC_DESC(d)->keyword);
|
||
OLC_DESC(d)->keyword = str_udup(arg);
|
||
}
|
||
oedit_disp_extradesc_menu(d);
|
||
return;
|
||
|
||
case OEDIT_EXTRADESC_MENU:
|
||
switch ((number = atoi(arg))) {
|
||
case 0:
|
||
if (!OLC_DESC(d)->keyword || !OLC_DESC(d)->description) {
|
||
struct extra_descr_data *temp;
|
||
if (OLC_DESC(d)->keyword) free(OLC_DESC(d)->keyword);
|
||
if (OLC_DESC(d)->description) free(OLC_DESC(d)->description);
|
||
REMOVE_FROM_LIST(OLC_DESC(d), OLC_OBJ(d)->ex_description, next);
|
||
free(OLC_DESC(d));
|
||
OLC_DESC(d) = NULL;
|
||
OLC_DIRTY(d) = 1;
|
||
}
|
||
break;
|
||
case 1:
|
||
OLC_MODE(d) = OEDIT_EXTRADESC_KEY;
|
||
write_to_output(d, "Enter keywords, separated by spaces :-\r\n| ");
|
||
return;
|
||
case 2:
|
||
OLC_MODE(d) = OEDIT_EXTRADESC_DESCRIPTION;
|
||
send_editor_help(d);
|
||
write_to_output(d, "Enter the extra description:\r\n\r\n");
|
||
if (OLC_DESC(d)->description) {
|
||
write_to_output(d, "%s", OLC_DESC(d)->description);
|
||
oldtext = strdup(OLC_DESC(d)->description);
|
||
}
|
||
string_write(d, &OLC_DESC(d)->description, MAX_MESSAGE_LENGTH, 0, oldtext);
|
||
OLC_DIRTY(d) = 1;
|
||
return;
|
||
case 3:
|
||
if (OLC_DESC(d)->keyword && OLC_DESC(d)->description) {
|
||
struct extra_descr_data *new_extra;
|
||
if (OLC_DESC(d)->next)
|
||
OLC_DESC(d) = OLC_DESC(d)->next;
|
||
else {
|
||
CREATE(new_extra, struct extra_descr_data, 1);
|
||
OLC_DESC(d)->next = new_extra;
|
||
OLC_DESC(d) = OLC_DESC(d)->next;
|
||
}
|
||
}
|
||
default:
|
||
oedit_disp_extradesc_menu(d);
|
||
return;
|
||
}
|
||
break;
|
||
|
||
/* === Copy object === */
|
||
case OEDIT_COPY:
|
||
{
|
||
/* Trim leading spaces if you have a helper; otherwise simple checks below handle it */
|
||
/* skip_spaces(&arg); */
|
||
|
||
/* Treat empty input as cancel */
|
||
if (!arg || *arg == '\0') {
|
||
write_to_output(d, "Copy cancelled.\r\n");
|
||
OLC_MODE(d) = OEDIT_MAIN_MENU;
|
||
oedit_disp_menu(d);
|
||
return;
|
||
}
|
||
|
||
/* Allow 0 or q/Q to cancel */
|
||
if ((arg[0] == '0' && arg[1] == '\0') ||
|
||
(arg[0] == 'q' && arg[1] == '\0') ||
|
||
(arg[0] == 'Q' && arg[1] == '\0')) {
|
||
write_to_output(d, "Copy cancelled.\r\n");
|
||
OLC_MODE(d) = OEDIT_MAIN_MENU;
|
||
oedit_disp_menu(d);
|
||
return;
|
||
}
|
||
|
||
/* Require a number */
|
||
if (!is_number(arg)) {
|
||
write_to_output(d, "Please enter a vnum or 0 to cancel: ");
|
||
return; /* stay in OEDIT_COPY */
|
||
}
|
||
|
||
int vnum = atoi(arg);
|
||
if (vnum <= 0) {
|
||
write_to_output(d, "Copy cancelled.\r\n");
|
||
OLC_MODE(d) = OEDIT_MAIN_MENU;
|
||
oedit_disp_menu(d);
|
||
return;
|
||
}
|
||
|
||
int rnum = real_object(vnum);
|
||
if (rnum == NOTHING) {
|
||
write_to_output(d, "That object does not exist. Enter vnum or 0 to cancel: ");
|
||
return; /* stay in OEDIT_COPY */
|
||
}
|
||
|
||
/* Success: clone into editor */
|
||
oedit_setup_existing(d, rnum);
|
||
OLC_MODE(d) = OEDIT_MAIN_MENU;
|
||
oedit_disp_menu(d);
|
||
return;
|
||
}
|
||
|
||
/* === Delete object === */
|
||
case OEDIT_DELETE:
|
||
if (*arg == 'y' || *arg == 'Y') {
|
||
if (delete_object(GET_OBJ_RNUM(OLC_OBJ(d))) != NOTHING)
|
||
write_to_output(d, "Object deleted.\r\n");
|
||
else
|
||
write_to_output(d, "Couldn't delete the object!\r\n");
|
||
cleanup_olc(d, CLEANUP_ALL);
|
||
} else if (*arg == 'n' || *arg == 'N') {
|
||
oedit_disp_menu(d);
|
||
OLC_MODE(d) = OEDIT_MAIN_MENU;
|
||
} else
|
||
write_to_output(d, "Please answer 'Y' or 'N': ");
|
||
return;
|
||
|
||
default:
|
||
mudlog(BRF, LVL_BUILDER, TRUE,
|
||
"SYSERR: OLC: Reached default case in oedit_parse()!");
|
||
write_to_output(d, "Oops...\r\n");
|
||
break;
|
||
}
|
||
|
||
/* Only redisplay main menu if we are in main menu mode */
|
||
if (OLC_MODE(d) == OEDIT_MAIN_MENU) {
|
||
oedit_disp_menu(d);
|
||
}
|
||
}
|
||
|
||
void oedit_string_cleanup(struct descriptor_data *d, int terminator)
|
||
{
|
||
switch (OLC_MODE(d)) {
|
||
case OEDIT_MAINDESC:
|
||
OLC_DIRTY(d) = 1;
|
||
oedit_disp_menu(d);
|
||
break;
|
||
case OEDIT_EXTRADESC_DESCRIPTION:
|
||
OLC_DIRTY(d) = 1;
|
||
oedit_disp_extradesc_menu(d);
|
||
break;
|
||
}
|
||
}
|