mirror of
https://github.com/tbamud/tbamud.git
synced 2026-03-19 10:46:33 +01:00
1587 lines
43 KiB
C
1587 lines
43 KiB
C
/**************************************************************************
|
|
* File: medit.c Part of tbaMUD *
|
|
* Usage: Oasis OLC - Mobiles. *
|
|
* *
|
|
* Copyright 1996 Harvey Gilpin. 1997-2001 George Greer. *
|
|
**************************************************************************/
|
|
|
|
#include "conf.h"
|
|
#include "sysdep.h"
|
|
#include "structs.h"
|
|
#include "utils.h"
|
|
#include "interpreter.h"
|
|
#include "comm.h"
|
|
#include "spells.h"
|
|
#include "class.h"
|
|
#include "species.h"
|
|
#include "db.h"
|
|
#include "shop.h"
|
|
#include "genolc.h"
|
|
#include "genmob.h"
|
|
#include "genzon.h"
|
|
#include "genshp.h"
|
|
#include "oasis.h"
|
|
#include "handler.h"
|
|
#include "constants.h"
|
|
#include "improved-edit.h"
|
|
#include "dg_olc.h"
|
|
#include "screen.h"
|
|
#include "fight.h"
|
|
#include "modify.h" /* for smash_tilde */
|
|
|
|
/* local functions */
|
|
static void medit_setup_new(struct descriptor_data *d);
|
|
void init_mobile(struct char_data *mob);
|
|
static void medit_save_to_disk(zone_vnum zone_num);
|
|
static void medit_disp_positions(struct descriptor_data *d);
|
|
static void medit_disp_sex(struct descriptor_data *d);
|
|
static void medit_disp_attack_types(struct descriptor_data *d);
|
|
static bool medit_illegal_mob_flag(int fl);
|
|
static int medit_get_mob_flag_by_number(int num);
|
|
static void medit_disp_mob_flags(struct descriptor_data *d);
|
|
static void medit_disp_aff_flags(struct descriptor_data *d);
|
|
static void medit_disp_menu(struct descriptor_data *d);
|
|
static void medit_disp_class_menu(struct descriptor_data *d);
|
|
static void medit_disp_species_menu(struct descriptor_data *d);
|
|
static int roll_stat_for_cap(int cap);
|
|
static int autoroll_species_stat(struct char_data *mob, int ability);
|
|
|
|
/* utility functions */
|
|
ACMD(do_oasis_medit)
|
|
{
|
|
int number = NOBODY, 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 (!*buf1) {
|
|
send_to_char(ch, "Specify a mobile 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 (like a room number), get it. */
|
|
if (number == NOBODY)
|
|
number = atoi(buf1);
|
|
|
|
if (number < IDXTYPE_MIN || number > IDXTYPE_MAX) {
|
|
send_to_char(ch, "That mobile 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_MEDIT) {
|
|
if (d->olc && OLC_NUM(d) == number) {
|
|
send_to_char(ch, "That mobile is currently being edited by %s.\r\n",
|
|
GET_NAME(d->character));
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
d = ch->desc;
|
|
|
|
/* Give descriptor an OLC structure. */
|
|
if (d->olc) {
|
|
mudlog(BRF, LVL_IMMORT, TRUE,
|
|
"SYSERR: do_oasis_medit: Player already had olc structure.");
|
|
free(d->olc);
|
|
}
|
|
|
|
CREATE(d->olc, struct oasis_olc_data, 1);
|
|
d->olc->skin_yields = NULL;
|
|
|
|
/* 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(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 save is TRUE, save the mobiles. */
|
|
if (save) {
|
|
send_to_char(ch, "Saving all mobiles in zone %d.\r\n",
|
|
zone_table[OLC_ZNUM(d)].number);
|
|
mudlog(CMP, MAX(LVL_BUILDER, GET_INVIS_LEV(ch)), TRUE,
|
|
"OLC: %s saves mobile info for zone %d.",
|
|
GET_NAME(ch), zone_table[OLC_ZNUM(d)].number);
|
|
|
|
/* Save the mobiles. */
|
|
save_mobiles(OLC_ZNUM(d));
|
|
|
|
/* Free the olc structure stored in the descriptor. */
|
|
free(d->olc);
|
|
d->olc = NULL;
|
|
return;
|
|
}
|
|
|
|
OLC_NUM(d) = number;
|
|
|
|
/* If this is a new mobile, setup a new one, otherwise, setup the
|
|
existing mobile. */
|
|
if ((real_num = real_mobile(number)) == NOBODY)
|
|
medit_setup_new(d);
|
|
else
|
|
medit_setup_existing(d, real_num);
|
|
|
|
medit_disp_menu(d);
|
|
STATE(d) = CON_MEDIT;
|
|
|
|
/* Display the OLC messages to the players in the same room as the
|
|
builder and also log it. */
|
|
act("$n starts using OLC.", TRUE, d->character, 0, 0, TO_ROOM);
|
|
SET_BIT_AR(PLR_FLAGS(ch), PLR_WRITING);
|
|
|
|
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 medit_save_to_disk(zone_vnum foo)
|
|
{
|
|
save_mobiles(real_zone(foo));
|
|
}
|
|
|
|
static void medit_setup_new(struct descriptor_data *d)
|
|
{
|
|
struct char_data *mob;
|
|
|
|
/* Allocate a scratch mobile structure. */
|
|
CREATE(mob, struct char_data, 1);
|
|
|
|
init_mobile(mob);
|
|
|
|
GET_MOB_RNUM(mob) = NOBODY;
|
|
/* Set up some default strings. */
|
|
GET_NAME(mob) = strdup("NPC");
|
|
GET_KEYWORDS(mob) = strdup("unfinished npc");
|
|
GET_SDESC(mob) = strdup("the unfinished npc");
|
|
GET_LDESC(mob) = strdup("An unfinished npc stands here.\r\n");
|
|
GET_DDESC(mob) = strdup("It looks unfinished.\r\n");
|
|
GET_BACKGROUND(mob) = strdup("No background has been recorded.\r\n");
|
|
SCRIPT(mob) = NULL;
|
|
mob->proto_script = OLC_SCRIPT(d) = NULL;
|
|
|
|
OLC_MOB(d) = mob;
|
|
/* Has changed flag. (It hasn't so far, we just made it.) */
|
|
OLC_VAL(d) = FALSE;
|
|
OLC_ITEM_TYPE(d) = MOB_TRIGGER;
|
|
}
|
|
|
|
void medit_setup_existing(struct descriptor_data *d, int rmob_num)
|
|
{
|
|
struct char_data *mob;
|
|
|
|
/* Allocate a scratch mobile structure. */
|
|
CREATE(mob, struct char_data, 1);
|
|
|
|
copy_mobile(mob, mob_proto + rmob_num);
|
|
|
|
OLC_MOB(d) = mob;
|
|
OLC_ITEM_TYPE(d) = MOB_TRIGGER;
|
|
dg_olc_script_copy(d);
|
|
/*
|
|
* The edited mob must not have a script.
|
|
* It will be assigned to the updated mob later, after editing.
|
|
*/
|
|
SCRIPT(mob) = NULL;
|
|
OLC_MOB(d)->proto_script = NULL;
|
|
|
|
/* Copy skinning yields from the prototype index into OLC working storage. */
|
|
d->olc->skin_yields = copy_skin_yields(mob_index[rmob_num].skin_yields);
|
|
}
|
|
|
|
/* Ideally, this function should be in db.c, but I'll put it here for portability. */
|
|
void init_mobile(struct char_data *mob)
|
|
{
|
|
int i;
|
|
clear_char(mob);
|
|
|
|
GET_HIT(mob) = GET_MANA(mob) = 1;
|
|
GET_MAX_MANA(mob) = GET_MAX_STAMINA(mob) = 100;
|
|
GET_WEIGHT(mob) = 200;
|
|
GET_HEIGHT(mob) = 198;
|
|
mob->player.time.birth = time(0);
|
|
mob->player.roleplay_age = MIN_CHAR_AGE;
|
|
mob->player.roleplay_age_year = time_info.year;
|
|
|
|
/* Only assign defaults if the individual stat is unset (zero) */
|
|
if (!mob->real_abils.str) mob->real_abils.str = 11;
|
|
if (!mob->real_abils.intel) mob->real_abils.intel = 11;
|
|
if (!mob->real_abils.wis) mob->real_abils.wis = 11;
|
|
if (!mob->real_abils.dex) mob->real_abils.dex = 11;
|
|
if (!mob->real_abils.con) mob->real_abils.con = 11;
|
|
if (!mob->real_abils.cha) mob->real_abils.cha = 11;
|
|
|
|
mob->aff_abils = mob->real_abils;
|
|
|
|
for (i = 0; i < NUM_ABILITIES; i++)
|
|
GET_SAVE(mob, i) = 0;
|
|
|
|
SET_BIT_AR(MOB_FLAGS(mob), MOB_ISNPC);
|
|
mob->player_specials = &dummy_mob;
|
|
}
|
|
|
|
/* Save new/edited mob to memory. */
|
|
void medit_save_internally(struct descriptor_data *d)
|
|
{
|
|
int i;
|
|
mob_rnum new_rnum;
|
|
struct descriptor_data *dsc;
|
|
struct char_data *mob;
|
|
|
|
i = (real_mobile(OLC_NUM(d)) == NOBODY);
|
|
|
|
if ((new_rnum = add_mobile(OLC_MOB(d), OLC_NUM(d))) == NOBODY) {
|
|
log("medit_save_internally: add_mobile failed.");
|
|
return;
|
|
}
|
|
|
|
/* Update triggers and free old proto list */
|
|
if (mob_proto[new_rnum].proto_script &&
|
|
mob_proto[new_rnum].proto_script != OLC_SCRIPT(d))
|
|
free_proto_script(&mob_proto[new_rnum], MOB_TRIGGER);
|
|
|
|
mob_proto[new_rnum].proto_script = OLC_SCRIPT(d);
|
|
|
|
/* this takes care of the mobs currently in-game */
|
|
for (mob = character_list; mob; mob = mob->next) {
|
|
if (GET_MOB_RNUM(mob) != new_rnum)
|
|
continue;
|
|
|
|
/* remove any old scripts */
|
|
if (SCRIPT(mob))
|
|
extract_script(mob, MOB_TRIGGER);
|
|
|
|
free_proto_script(mob, MOB_TRIGGER);
|
|
copy_proto_script(&mob_proto[new_rnum], mob, MOB_TRIGGER);
|
|
assign_triggers(mob, MOB_TRIGGER);
|
|
}
|
|
/* end trigger update */
|
|
|
|
if (!i) /* Only renumber on new mobiles. */
|
|
return;
|
|
|
|
/* Update keepers in shops being edited and other mobs being edited. */
|
|
for (dsc = descriptor_list; dsc; dsc = dsc->next) {
|
|
if (STATE(dsc) == CON_SEDIT)
|
|
S_KEEPER(OLC_SHOP(dsc)) += (S_KEEPER(OLC_SHOP(dsc)) != NOTHING && S_KEEPER(OLC_SHOP(dsc)) >= new_rnum);
|
|
else if (STATE(dsc) == CON_MEDIT)
|
|
GET_MOB_RNUM(OLC_MOB(dsc)) += (GET_MOB_RNUM(OLC_MOB(dsc)) != NOTHING && GET_MOB_RNUM(OLC_MOB(dsc)) >= new_rnum);
|
|
}
|
|
|
|
/* 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++)
|
|
if (OLC_ZONE(dsc)->cmd[i].command == 'M')
|
|
if (OLC_ZONE(dsc)->cmd[i].arg1 >= new_rnum)
|
|
OLC_ZONE(dsc)->cmd[i].arg1++;
|
|
}
|
|
|
|
/* Menu functions
|
|
Display positions. (sitting, standing, etc) */
|
|
static void medit_disp_positions(struct descriptor_data *d)
|
|
{
|
|
get_char_colors(d->character);
|
|
clear_screen(d);
|
|
column_list(d->character, 0, position_types, NUM_POSITIONS, TRUE);
|
|
write_to_output(d, "Enter position number : ");
|
|
}
|
|
|
|
/* Display the gender of the mobile. */
|
|
static void medit_disp_sex(struct descriptor_data *d)
|
|
{
|
|
get_char_colors(d->character);
|
|
clear_screen(d);
|
|
column_list(d->character, 0, genders, NUM_GENDERS, TRUE);
|
|
write_to_output(d, "Enter gender number : ");
|
|
}
|
|
|
|
/* Display attack types menu. */
|
|
static void medit_disp_attack_types(struct descriptor_data *d)
|
|
{
|
|
int i;
|
|
|
|
get_char_colors(d->character);
|
|
clear_screen(d);
|
|
|
|
for (i = 0; i < NUM_ATTACK_TYPES; i++) {
|
|
write_to_output(d, "%s%2d%s) %s\r\n", grn, i, nrm, attack_hit_text[i].singular);
|
|
}
|
|
write_to_output(d, "Enter attack type : ");
|
|
}
|
|
|
|
/* Find mob flags that shouldn't be set by builders */
|
|
static bool medit_illegal_mob_flag(int fl)
|
|
{
|
|
int i;
|
|
|
|
/* add any other flags you dont want them setting */
|
|
const int illegal_flags[] = {
|
|
MOB_ISNPC,
|
|
MOB_NOTDEADYET,
|
|
};
|
|
|
|
const int num_illegal_flags = sizeof(illegal_flags)/sizeof(int);
|
|
|
|
|
|
for (i=0; i < num_illegal_flags;i++)
|
|
if (fl == illegal_flags[i])
|
|
return (TRUE);
|
|
|
|
return (FALSE);
|
|
|
|
}
|
|
|
|
/* Due to illegal mob flags not showing in the mob flags list,
|
|
we need this to convert the list number back to flag value */
|
|
static int medit_get_mob_flag_by_number(int num)
|
|
{
|
|
int i, count = 0;
|
|
for (i = 0; i < NUM_MOB_FLAGS; i++) {
|
|
if (medit_illegal_mob_flag(i)) continue;
|
|
if ((++count) == num) return i;
|
|
}
|
|
/* Return 'illegal flag' value */
|
|
return -1;
|
|
}
|
|
|
|
/* Display mob-flags menu. */
|
|
static void medit_disp_mob_flags(struct descriptor_data *d)
|
|
{
|
|
int i, count = 0, columns = 0;
|
|
char flags[MAX_STRING_LENGTH];
|
|
|
|
get_char_colors(d->character);
|
|
clear_screen(d);
|
|
|
|
/* Mob flags has special handling to remove illegal flags from the list */
|
|
for (i = 0; i < NUM_MOB_FLAGS; i++) {
|
|
if (medit_illegal_mob_flag(i)) continue;
|
|
write_to_output(d, "%s%2d%s) %-20.20s %s", grn, ++count, nrm, action_bits[i],
|
|
!(++columns % 2) ? "\r\n" : "");
|
|
}
|
|
|
|
sprintbitarray(MOB_FLAGS(OLC_MOB(d)), action_bits, AF_ARRAY_MAX, flags);
|
|
write_to_output(d, "\r\nCurrent flags : %s%s%s\r\nEnter mob flags (0 to quit) : ", cyn, flags, nrm);
|
|
}
|
|
|
|
/* Display affection flags menu. */
|
|
static void medit_disp_aff_flags(struct descriptor_data *d)
|
|
{
|
|
char flags[MAX_STRING_LENGTH];
|
|
|
|
get_char_colors(d->character);
|
|
clear_screen(d);
|
|
/* +1/-1 antics needed because AFF_FLAGS doesn't start at 0. */
|
|
column_list(d->character, 0, affected_bits + 1, NUM_AFF_FLAGS - 1, TRUE);
|
|
sprintbitarray(AFF_FLAGS(OLC_MOB(d)), affected_bits, AF_ARRAY_MAX, flags);
|
|
write_to_output(d, "\r\nCurrent flags : %s%s%s\r\nEnter aff flags (0 to quit) : ",
|
|
cyn, flags, nrm);
|
|
}
|
|
|
|
/* Display main menu. */
|
|
static void medit_disp_menu(struct descriptor_data *d)
|
|
{
|
|
struct char_data *mob;
|
|
char flags[MAX_STRING_LENGTH], flag2[MAX_STRING_LENGTH];
|
|
const char *classname, *speciesname;
|
|
|
|
mob = OLC_MOB(d);
|
|
get_char_colors(d->character);
|
|
clear_screen(d);
|
|
classname = HAS_VALID_CLASS(mob) ? pc_class_types[GET_CLASS(mob)] : "Unassigned";
|
|
speciesname = HAS_VALID_SPECIES(mob) ? species_types[GET_SPECIES(mob)] : "Unassigned";
|
|
|
|
write_to_output(d,
|
|
"-- Mob Number: [%s%d%s]\r\n"
|
|
"%s1%s) Name: %s%s\r\n"
|
|
"%s2%s) Keywords: %s%s\r\n"
|
|
"%s3%s) Sex: %s%-7.7s%s\r\n"
|
|
"%sG%s) Age: %s%d%s\r\n"
|
|
"%s4%s) S-Desc: %s%s\r\n"
|
|
"%s5%s) L-Desc:-\r\n%s%s\r\n"
|
|
"%s6%s) D-Desc:-\r\n%s%s\r\n",
|
|
|
|
cyn, OLC_NUM(d), nrm,
|
|
grn, nrm, yel, GET_NAME(mob),
|
|
grn, nrm, yel, GET_KEYWORDS(mob),
|
|
grn, nrm, yel, genders[(int)GET_SEX(mob)], nrm,
|
|
grn, nrm, yel, GET_ROLEPLAY_AGE(mob), nrm,
|
|
grn, nrm, yel, GET_SDESC(mob),
|
|
grn, nrm, yel, GET_LDESC(mob),
|
|
grn, nrm, yel, GET_DDESC(mob)
|
|
);
|
|
|
|
sprintbitarray(MOB_FLAGS(mob), action_bits, AF_ARRAY_MAX, flags);
|
|
sprintbitarray(AFF_FLAGS(mob), affected_bits, AF_ARRAY_MAX, flag2);
|
|
write_to_output(d,
|
|
"%s7%s) Position : %s%s\r\n"
|
|
"%s8%s) Default : %s%s\r\n"
|
|
"%s9%s) Attack : %s%s\r\n"
|
|
"%sD%s) Class : %s%s\r\n"
|
|
"%sE%s) Species : %s%s\r\n"
|
|
"%sK%s) Skinning Menu...\r\n"
|
|
"%s0%s) Stats Menu...\r\n"
|
|
"%s-%s) Skills Menu...\r\n"
|
|
"%sA%s) NPC Flags : %s%s\r\n"
|
|
"%sB%s) AFF Flags : %s%s\r\n"
|
|
"%sC%s) Background...\r\n"
|
|
"%sS%s) Script : %s%s\r\n"
|
|
"%sW%s) Copy mob\r\n"
|
|
"%sX%s) Delete mob\r\n"
|
|
"%sQ%s) Quit\r\n"
|
|
"Enter choice : ",
|
|
|
|
grn, nrm, yel, position_types[(int)GET_POS(mob)],
|
|
grn, nrm, yel, position_types[(int)GET_DEFAULT_POS(mob)],
|
|
grn, nrm, yel, attack_hit_text[(int)GET_ATTACK(mob)].singular,
|
|
grn, nrm, yel, classname,
|
|
grn, nrm, yel, speciesname,
|
|
grn, nrm,
|
|
grn, nrm,
|
|
grn, nrm,
|
|
grn, nrm, cyn, flags,
|
|
grn, nrm, cyn, flag2,
|
|
grn, nrm,
|
|
grn, nrm, cyn, OLC_SCRIPT(d) ?"Set.":"Not Set.",
|
|
grn, nrm,
|
|
grn, nrm,
|
|
grn, nrm
|
|
);
|
|
|
|
OLC_MODE(d) = MEDIT_MAIN_MENU;
|
|
}
|
|
|
|
static void medit_disp_class_menu(struct descriptor_data *d)
|
|
{
|
|
struct char_data *mob = OLC_MOB(d);
|
|
const char *current = HAS_VALID_CLASS(mob) ? pc_class_types[GET_CLASS(mob)] : "Unassigned";
|
|
|
|
get_char_colors(d->character);
|
|
clear_screen(d);
|
|
|
|
write_to_output(d,
|
|
"-- Mob Number: %s[%s%d%s]%s\r\n"
|
|
"Class selection for %s%s%s\r\n\r\n",
|
|
cyn, yel, OLC_NUM(d), cyn, nrm,
|
|
yel, GET_SDESC(mob), nrm);
|
|
|
|
for (int i = 0; i < NUM_CLASSES; i++) {
|
|
bool selected = HAS_VALID_CLASS(mob) && (GET_CLASS(mob) == i);
|
|
write_to_output(d, "%s%2d%s) %s%-12s%s%s\r\n",
|
|
cyn, i + 1, nrm,
|
|
selected ? grn : yel,
|
|
pc_class_types[i],
|
|
nrm,
|
|
selected ? " (current)" : "");
|
|
}
|
|
|
|
write_to_output(d, "%s%2d%s) %sUnassigned%s%s\r\n",
|
|
cyn, NUM_CLASSES + 1, nrm,
|
|
!HAS_VALID_CLASS(mob) ? grn : yel,
|
|
nrm,
|
|
!HAS_VALID_CLASS(mob) ? " (current)" : "");
|
|
|
|
write_to_output(d,
|
|
"\r\nCurrent choice: %s%s%s\r\n"
|
|
"%s0%s) Return to main menu\r\n"
|
|
"Enter choice : ",
|
|
cyn, current, nrm,
|
|
cyn, nrm);
|
|
|
|
OLC_MODE(d) = MEDIT_CLASS_MENU;
|
|
}
|
|
|
|
static void medit_disp_species_menu(struct descriptor_data *d)
|
|
{
|
|
struct char_data *mob = OLC_MOB(d);
|
|
const char *current = HAS_VALID_SPECIES(mob) ? species_types[GET_SPECIES(mob)] : "Unassigned";
|
|
|
|
get_char_colors(d->character);
|
|
clear_screen(d);
|
|
|
|
write_to_output(d,
|
|
"-- Mob Number: %s[%s%d%s]%s\r\n"
|
|
"Species selection for %s%s%s\r\n\r\n",
|
|
cyn, yel, OLC_NUM(d), cyn, nrm,
|
|
yel, GET_SDESC(mob), nrm);
|
|
|
|
for (int i = 0; i < NUM_SPECIES; i++) {
|
|
bool selected = HAS_VALID_SPECIES(mob) && (GET_SPECIES(mob) == i);
|
|
write_to_output(d, "%s%2d%s) %s%-12s%s%s\r\n",
|
|
cyn, i + 1, nrm,
|
|
selected ? grn : yel,
|
|
species_types[i],
|
|
nrm,
|
|
selected ? " (current)" : "");
|
|
}
|
|
|
|
write_to_output(d, "%s%2d%s) %sUnassigned%s%s\r\n",
|
|
cyn, NUM_SPECIES + 1, nrm,
|
|
!HAS_VALID_SPECIES(mob) ? grn : yel,
|
|
nrm,
|
|
!HAS_VALID_SPECIES(mob) ? " (current)" : "");
|
|
|
|
write_to_output(d,
|
|
"\r\nCurrent choice: %s%s%s\r\n"
|
|
"%s0%s) Return to main menu\r\n"
|
|
"Enter choice : ",
|
|
cyn, current, nrm,
|
|
cyn, nrm);
|
|
|
|
OLC_MODE(d) = MEDIT_SPECIES_MENU;
|
|
}
|
|
|
|
/* Display main menu. */
|
|
static void medit_disp_stats_menu(struct descriptor_data *d)
|
|
{
|
|
struct char_data *mob;
|
|
char buf[MAX_STRING_LENGTH];
|
|
|
|
mob = OLC_MOB(d);
|
|
get_char_colors(d->character);
|
|
clear_screen(d);
|
|
|
|
/* Color codes have to be used here, for count_color_codes to work */
|
|
sprintf(buf, "(range \ty%d\tn to \ty%d\tn)", GET_HIT(mob) + GET_STAMINA(mob),
|
|
(GET_HIT(mob) * GET_MANA(mob)) + GET_STAMINA(mob));
|
|
|
|
/* Top section - standard stats */
|
|
write_to_output(d,
|
|
"-- Mob Number: %s[%s%d%s]%s\r\n"
|
|
"(%s1%s) %sAuto Set Stats (species range)%s\r\n\r\n"
|
|
"Hit Points (xdy+z):\r\n"
|
|
"(%s2%s) HP NumDice: %s[%s%5d%s]%s\r\n"
|
|
"(%s3%s) HP SizeDice: %s[%s%5d%s]%s\r\n"
|
|
"(%s4%s) HP Addition: %s[%s%5d%s]%s\r\n\r\n",
|
|
cyn, yel, OLC_NUM(d), cyn, nrm,
|
|
cyn, nrm, cyn, nrm,
|
|
cyn, nrm, cyn, yel, GET_HIT(mob), cyn, nrm,
|
|
cyn, nrm, cyn, yel, GET_MANA(mob), cyn, nrm,
|
|
cyn, nrm, cyn, yel, GET_STAMINA(mob), cyn, nrm
|
|
);
|
|
|
|
if (CONFIG_MEDIT_ADVANCED) {
|
|
/* Bottom section - non-standard stats, togglable in cedit */
|
|
write_to_output(d,
|
|
"%sAttributes Saving Throw bonus\r\n"
|
|
"(%sF%s) Str: %s[%s%3d%s]%s (%sR%s) Save STR %s[%s%3d%s]%s\r\n"
|
|
"(%sG%s) Dex: %s[%s%3d%s]%s (%sS%s) Save DEX %s[%s%3d%s]%s\r\n"
|
|
"(%sH%s) Con: %s[%s%3d%s]%s (%sT%s) Save CON %s[%s%3d%s]%s\r\n"
|
|
"(%sI%s) Int: %s[%s%3d%s]%s (%sU%s) Save INT %s[%s%3d%s]%s\r\n"
|
|
"(%sJ%s) Wis: %s[%s%3d%s]%s (%sV%s) Save WIS %s[%s%3d%s]%s\r\n"
|
|
"(%sK%s) Cha: %s[%s%3d%s]%s (%sW%s) Save CHA %s[%s%3d%s]%s\r\n\r\n",
|
|
nrm,
|
|
cyn, nrm, cyn, yel, GET_STR(mob), cyn, nrm,
|
|
cyn, nrm, cyn, yel, GET_SAVE(mob, ABIL_STR), cyn, nrm,
|
|
|
|
cyn, nrm, cyn, yel, GET_DEX(mob), cyn, nrm,
|
|
cyn, nrm, cyn, yel, GET_SAVE(mob, ABIL_DEX), cyn, nrm,
|
|
|
|
cyn, nrm, cyn, yel, GET_CON(mob), cyn, nrm,
|
|
cyn, nrm, cyn, yel, GET_SAVE(mob, ABIL_CON), cyn, nrm,
|
|
|
|
cyn, nrm, cyn, yel, GET_INT(mob), cyn, nrm,
|
|
cyn, nrm, cyn, yel, GET_SAVE(mob, ABIL_INT), cyn, nrm,
|
|
|
|
cyn, nrm, cyn, yel, GET_WIS(mob), cyn, nrm,
|
|
cyn, nrm, cyn, yel, GET_SAVE(mob, ABIL_WIS), cyn, nrm,
|
|
|
|
cyn, nrm, cyn, yel, GET_CHA(mob), cyn, nrm,
|
|
cyn, nrm, cyn, yel, GET_SAVE(mob, ABIL_CHA), cyn, nrm
|
|
);
|
|
}
|
|
|
|
/* Quit to previous menu option */
|
|
write_to_output(d, "(%sQ%s) Quit to main menu\r\nEnter choice : ", cyn, nrm);
|
|
|
|
OLC_MODE(d) = MEDIT_STATS_MENU;
|
|
}
|
|
|
|
static void medit_disp_skill_menu(struct descriptor_data *d)
|
|
{
|
|
struct char_data *mob = OLC_MOB(d);
|
|
int count = 0;
|
|
|
|
clear_screen(d);
|
|
write_to_output(d, "-- %sSkill Editor%s for %s%s%s\r\n",
|
|
cyn, nrm, yel, GET_SDESC(mob), nrm);
|
|
|
|
/* List all skills that exist (non-zero entries only) */
|
|
for (int i = 0; i < MAX_SKILLS; i++) {
|
|
if (mob->mob_specials.skills[i] > 0) {
|
|
write_to_output(d, "%3d) %-25s : %3d%%\r\n",
|
|
i, spell_info[i].name, mob->mob_specials.skills[i]);
|
|
count++;
|
|
}
|
|
}
|
|
|
|
if (count == 0)
|
|
write_to_output(d, "No skills set.\r\n");
|
|
|
|
write_to_output(d, "\r\n"
|
|
"%sA%s) Add / modify skill\r\n"
|
|
"%sD%s) Delete skill\r\n"
|
|
"%sQ%s) Return to main menu\r\n"
|
|
"Enter choice : ",
|
|
grn, nrm, grn, nrm, grn, nrm);
|
|
|
|
OLC_MODE(d) = MEDIT_SKILL_MENU;
|
|
}
|
|
|
|
static void medit_disp_skin_menu(struct descriptor_data *d)
|
|
{
|
|
struct skin_yield_entry *e;
|
|
int n = 1;
|
|
|
|
write_to_output(d, "\r\n-- Skinning Yields --\r\n");
|
|
|
|
if (!d->olc->skin_yields) {
|
|
write_to_output(d, " <none>\r\n");
|
|
} else {
|
|
for (e = d->olc->skin_yields; e; e = e->next)
|
|
write_to_output(d, "%2d) obj %d dc %d\r\n", n++, e->obj_vnum, e->dc);
|
|
}
|
|
|
|
write_to_output(d,
|
|
"\r\nA) Add yield\r\n"
|
|
"D) Delete yield\r\n"
|
|
"Q) Quit to main menu\r\n"
|
|
"Enter choice: ");
|
|
}
|
|
|
|
void medit_parse(struct descriptor_data *d, char *arg)
|
|
{
|
|
int i = -1, j;
|
|
char *oldtext = NULL;
|
|
|
|
if (OLC_MODE(d) > MEDIT_NUMERICAL_RESPONSE) {
|
|
i = atoi(arg);
|
|
if (!*arg || (!isdigit(arg[0]) && ((*arg == '-') && !isdigit(arg[1])))) {
|
|
write_to_output(d, "Try again : ");
|
|
return;
|
|
}
|
|
} else { /* String response. */
|
|
if (!genolc_checkstring(d, arg))
|
|
return;
|
|
}
|
|
switch (OLC_MODE(d)) {
|
|
case MEDIT_CONFIRM_SAVESTRING:
|
|
/* Ensure mob has MOB_ISNPC set. */
|
|
SET_BIT_AR(MOB_FLAGS(OLC_MOB(d)), MOB_ISNPC);
|
|
switch (*arg) {
|
|
case 'y':
|
|
case 'Y':
|
|
/* Commit skinning yields from OLC working copy into the prototype index. */
|
|
{
|
|
mob_rnum rmob = real_mobile(OLC_NUM(d));
|
|
if (rmob != NOBODY) {
|
|
free_skin_yields(mob_index[rmob].skin_yields);
|
|
mob_index[rmob].skin_yields = copy_skin_yields(d->olc->skin_yields);
|
|
}
|
|
}
|
|
/* Save the mob in memory and to disk. */
|
|
medit_save_internally(d);
|
|
mudlog(CMP, MAX(LVL_BUILDER, GET_INVIS_LEV(d->character)), TRUE, "OLC: %s edits mob %d", GET_NAME(d->character), OLC_NUM(d));
|
|
if (CONFIG_OLC_SAVE) {
|
|
medit_save_to_disk(zone_table[real_zone_by_thing(OLC_NUM(d))].number);
|
|
write_to_output(d, "Mobile saved to disk.\r\n");
|
|
} else
|
|
write_to_output(d, "Mobile saved to memory.\r\n");
|
|
cleanup_olc(d, CLEANUP_ALL);
|
|
return;
|
|
case 'n':
|
|
case 'N':
|
|
/* If not saving, we must free the script_proto list. We do so by
|
|
* assigning it to the edited mob and letting free_mobile in
|
|
* cleanup_olc handle it. */
|
|
OLC_MOB(d)->proto_script = OLC_SCRIPT(d);
|
|
cleanup_olc(d, CLEANUP_ALL);
|
|
return;
|
|
default:
|
|
write_to_output(d, "Invalid choice!\r\n");
|
|
write_to_output(d, "Do you wish to save your changes? : ");
|
|
return;
|
|
}
|
|
|
|
case MEDIT_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 your changes? : ");
|
|
OLC_MODE(d) = MEDIT_CONFIRM_SAVESTRING;
|
|
} else
|
|
cleanup_olc(d, CLEANUP_ALL);
|
|
return;
|
|
case '1':
|
|
OLC_MODE(d) = MEDIT_NAME;
|
|
i--;
|
|
break;
|
|
case '2':
|
|
OLC_MODE(d) = MEDIT_KEYWORD;
|
|
i--;
|
|
break;
|
|
case '3':
|
|
OLC_MODE(d) = MEDIT_SEX;
|
|
medit_disp_sex(d);
|
|
return;
|
|
case 'g':
|
|
case 'G':
|
|
OLC_MODE(d) = MEDIT_AGE;
|
|
write_to_output(d, "Enter age (%d-%d): ", MIN_CHAR_AGE, MAX_CHAR_AGE);
|
|
return;
|
|
case '4':
|
|
OLC_MODE(d) = MEDIT_S_DESC;
|
|
i--;
|
|
break;
|
|
case '5':
|
|
OLC_MODE(d) = MEDIT_L_DESC;
|
|
i--;
|
|
break;
|
|
case '6':
|
|
OLC_MODE(d) = MEDIT_D_DESC;
|
|
send_editor_help(d);
|
|
write_to_output(d, "Enter mob description:\r\n\r\n");
|
|
if (OLC_MOB(d)->player.description) {
|
|
write_to_output(d, "%s", OLC_MOB(d)->player.description);
|
|
oldtext = strdup(OLC_MOB(d)->player.description);
|
|
}
|
|
string_write(d, &OLC_MOB(d)->player.description, MAX_MOB_DESC, 0, oldtext);
|
|
OLC_VAL(d) = 1;
|
|
return;
|
|
case '7':
|
|
OLC_MODE(d) = MEDIT_POS;
|
|
medit_disp_positions(d);
|
|
return;
|
|
case '8':
|
|
OLC_MODE(d) = MEDIT_DEFAULT_POS;
|
|
medit_disp_positions(d);
|
|
return;
|
|
case '9':
|
|
OLC_MODE(d) = MEDIT_ATTACK;
|
|
medit_disp_attack_types(d);
|
|
return;
|
|
case 'd':
|
|
case 'D':
|
|
medit_disp_class_menu(d);
|
|
return;
|
|
case 'e':
|
|
case 'E':
|
|
medit_disp_species_menu(d);
|
|
return;
|
|
case '0':
|
|
OLC_MODE(d) = MEDIT_STATS_MENU;
|
|
medit_disp_stats_menu(d);
|
|
return;
|
|
case '-': /* Enter skill sub-menu */
|
|
OLC_MODE(d) = MEDIT_SKILL_MENU;
|
|
medit_disp_skill_menu(d);
|
|
return;
|
|
case 'a':
|
|
case 'A':
|
|
OLC_MODE(d) = MEDIT_NPC_FLAGS;
|
|
medit_disp_mob_flags(d);
|
|
return;
|
|
case 'b':
|
|
case 'B':
|
|
OLC_MODE(d) = MEDIT_AFF_FLAGS;
|
|
medit_disp_aff_flags(d);
|
|
return;
|
|
case 'c':
|
|
case 'C':
|
|
OLC_MODE(d) = MEDIT_BACKGROUND;
|
|
send_editor_help(d);
|
|
write_to_output(d, "Enter mob background:\r\n\r\n");
|
|
if (OLC_MOB(d)->player.background) {
|
|
write_to_output(d, "%s", OLC_MOB(d)->player.background);
|
|
oldtext = strdup(OLC_MOB(d)->player.background);
|
|
}
|
|
string_write(d, &OLC_MOB(d)->player.background, MAX_MOB_DESC, 0, oldtext);
|
|
OLC_VAL(d) = 1;
|
|
return;
|
|
case 'k':
|
|
case 'K':
|
|
medit_disp_skin_menu(d);
|
|
OLC_MODE(d) = MEDIT_SKIN_MENU;
|
|
return;
|
|
case 'w':
|
|
case 'W':
|
|
write_to_output(d, "Copy what mob? ");
|
|
OLC_MODE(d) = MEDIT_COPY;
|
|
return;
|
|
case 'x':
|
|
case 'X':
|
|
write_to_output(d, "Are you sure you want to delete this mobile? ");
|
|
OLC_MODE(d) = MEDIT_DELETE;
|
|
return;
|
|
case 's':
|
|
case 'S':
|
|
OLC_SCRIPT_EDIT_MODE(d) = SCRIPT_MAIN_MENU;
|
|
dg_script_menu(d);
|
|
return;
|
|
default:
|
|
medit_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;
|
|
|
|
case MEDIT_SKIN_MENU:
|
|
switch (UPPER(*arg)) {
|
|
case 'A':
|
|
write_to_output(d, "Enter object vnum: ");
|
|
OLC_MODE(d) = MEDIT_SKIN_ADD_VNUM;
|
|
return;
|
|
|
|
case 'D':
|
|
write_to_output(d, "Delete which entry number? ");
|
|
OLC_MODE(d) = MEDIT_SKIN_DELETE;
|
|
return;
|
|
|
|
case 'Q':
|
|
medit_disp_menu(d);
|
|
OLC_MODE(d) = MEDIT_MAIN_MENU;
|
|
return;
|
|
|
|
default:
|
|
medit_disp_skin_menu(d);
|
|
return;
|
|
}
|
|
/* not reached */
|
|
|
|
case MEDIT_SKIN_ADD_VNUM: {
|
|
obj_vnum ovnum = (obj_vnum)atoi(arg);
|
|
|
|
if (ovnum <= 0) {
|
|
write_to_output(d, "Invalid object vnum. Enter object vnum: ");
|
|
return;
|
|
}
|
|
|
|
OLC_VAL(d) = (int)ovnum; /* stash temporarily (note: OLC_VAL is also your dirty flag) */
|
|
write_to_output(d, "Enter DC required: ");
|
|
OLC_MODE(d) = MEDIT_SKIN_ADD_DC;
|
|
return;
|
|
}
|
|
|
|
case MEDIT_SKIN_ADD_DC: {
|
|
int dc = atoi(arg);
|
|
struct skin_yield_entry *e;
|
|
|
|
CREATE(e, struct skin_yield_entry, 1);
|
|
e->mob_vnum = OLC_NUM(d); /* mob vnum being edited */
|
|
e->obj_vnum = (obj_vnum)OLC_VAL(d); /* vnum captured in prior step */
|
|
e->dc = MAX(0, dc);
|
|
e->next = d->olc->skin_yields;
|
|
d->olc->skin_yields = e;
|
|
|
|
/* Mark the mob as changed */
|
|
OLC_VAL(d) = TRUE;
|
|
|
|
medit_disp_skin_menu(d);
|
|
OLC_MODE(d) = MEDIT_SKIN_MENU;
|
|
return;
|
|
}
|
|
|
|
case MEDIT_SKIN_DELETE: {
|
|
int target = atoi(arg);
|
|
struct skin_yield_entry *e, *prev = NULL;
|
|
int n = 1;
|
|
|
|
if (target < 1) {
|
|
medit_disp_skin_menu(d);
|
|
OLC_MODE(d) = MEDIT_SKIN_MENU;
|
|
return;
|
|
}
|
|
|
|
for (e = d->olc->skin_yields; e; prev = e, e = e->next, n++) {
|
|
if (n == target) {
|
|
if (prev)
|
|
prev->next = e->next;
|
|
else
|
|
d->olc->skin_yields = e->next;
|
|
free(e);
|
|
|
|
/* Mark the mob as changed */
|
|
OLC_VAL(d) = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
medit_disp_skin_menu(d);
|
|
OLC_MODE(d) = MEDIT_SKIN_MENU;
|
|
return;
|
|
}
|
|
|
|
case MEDIT_STATS_MENU:
|
|
i=0;
|
|
switch(*arg) {
|
|
case 'q':
|
|
case 'Q':
|
|
medit_disp_menu(d);
|
|
return;
|
|
case '1': /* Autoroll stats */
|
|
medit_autoroll_stats(d);
|
|
medit_disp_stats_menu(d);
|
|
OLC_VAL(d) = TRUE;
|
|
return;
|
|
case '2':
|
|
OLC_MODE(d) = MEDIT_NUM_HP_DICE;
|
|
i++;
|
|
break;
|
|
case '3':
|
|
OLC_MODE(d) = MEDIT_SIZE_HP_DICE;
|
|
i++;
|
|
break;
|
|
case '4':
|
|
OLC_MODE(d) = MEDIT_ADD_HP;
|
|
i++;
|
|
break;
|
|
case 'f':
|
|
case 'F':
|
|
if (!CONFIG_MEDIT_ADVANCED) {
|
|
write_to_output(d, "Invalid Choice!\r\nEnter Choice : ");
|
|
return;
|
|
}
|
|
OLC_MODE(d) = MEDIT_STR;
|
|
i++;
|
|
break;
|
|
case 'g':
|
|
case 'G':
|
|
if (!CONFIG_MEDIT_ADVANCED) {
|
|
write_to_output(d, "Invalid Choice!\r\nEnter Choice : ");
|
|
return;
|
|
}
|
|
OLC_MODE(d) = MEDIT_DEX;
|
|
i++;
|
|
break;
|
|
case 'h':
|
|
case 'H':
|
|
if (!CONFIG_MEDIT_ADVANCED) {
|
|
write_to_output(d, "Invalid Choice!\r\nEnter Choice : ");
|
|
return;
|
|
}
|
|
OLC_MODE(d) = MEDIT_CON;
|
|
i++;
|
|
break;
|
|
case 'i':
|
|
case 'I':
|
|
if (!CONFIG_MEDIT_ADVANCED) {
|
|
write_to_output(d, "Invalid Choice!\r\nEnter Choice : ");
|
|
return;
|
|
}
|
|
OLC_MODE(d) = MEDIT_INT;
|
|
i++;
|
|
break;
|
|
case 'j':
|
|
case 'J':
|
|
if (!CONFIG_MEDIT_ADVANCED) {
|
|
write_to_output(d, "Invalid Choice!\r\nEnter Choice : ");
|
|
return;
|
|
}
|
|
OLC_MODE(d) = MEDIT_WIS;
|
|
i++;
|
|
break;
|
|
case 'k':
|
|
case 'K':
|
|
if (!CONFIG_MEDIT_ADVANCED) {
|
|
write_to_output(d, "Invalid Choice!\r\nEnter Choice : ");
|
|
return;
|
|
}
|
|
OLC_MODE(d) = MEDIT_CHA;
|
|
i++;
|
|
break;
|
|
case 'l':
|
|
case 'L':
|
|
if (!CONFIG_MEDIT_ADVANCED) {
|
|
write_to_output(d, "Invalid Choice!\r\nEnter Choice : ");
|
|
return;
|
|
}
|
|
case 'r':
|
|
case 'R':
|
|
if (!CONFIG_MEDIT_ADVANCED) {
|
|
write_to_output(d, "Invalid Choice!\r\nEnter Choice : ");
|
|
return;
|
|
}
|
|
OLC_MODE(d) = MEDIT_SAVE_STR;
|
|
i++;
|
|
break;
|
|
|
|
case 's':
|
|
case 'S':
|
|
if (!CONFIG_MEDIT_ADVANCED) {
|
|
write_to_output(d, "Invalid Choice!\r\nEnter Choice : ");
|
|
return;
|
|
}
|
|
OLC_MODE(d) = MEDIT_SAVE_DEX;
|
|
i++;
|
|
break;
|
|
|
|
case 't':
|
|
case 'T':
|
|
if (!CONFIG_MEDIT_ADVANCED) {
|
|
write_to_output(d, "Invalid Choice!\r\nEnter Choice : ");
|
|
return;
|
|
}
|
|
OLC_MODE(d) = MEDIT_SAVE_CON;
|
|
i++;
|
|
break;
|
|
|
|
case 'u':
|
|
case 'U':
|
|
if (!CONFIG_MEDIT_ADVANCED) {
|
|
write_to_output(d, "Invalid Choice!\r\nEnter Choice : ");
|
|
return;
|
|
}
|
|
OLC_MODE(d) = MEDIT_SAVE_INT;
|
|
i++;
|
|
break;
|
|
|
|
case 'v':
|
|
case 'V':
|
|
if (!CONFIG_MEDIT_ADVANCED) {
|
|
write_to_output(d, "Invalid Choice!\r\nEnter Choice : ");
|
|
return;
|
|
}
|
|
OLC_MODE(d) = MEDIT_SAVE_WIS;
|
|
i++;
|
|
break;
|
|
|
|
case 'w':
|
|
case 'W':
|
|
if (!CONFIG_MEDIT_ADVANCED) {
|
|
write_to_output(d, "Invalid Choice!\r\nEnter Choice : ");
|
|
return;
|
|
}
|
|
OLC_MODE(d) = MEDIT_SAVE_CHA;
|
|
i++;
|
|
break;
|
|
|
|
default:
|
|
medit_disp_stats_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;
|
|
|
|
case MEDIT_SKILL_MENU:
|
|
switch (*arg) {
|
|
case 'q':
|
|
case 'Q':
|
|
medit_disp_menu(d);
|
|
return;
|
|
case 'a':
|
|
case 'A':
|
|
write_to_output(d, "Enter skill name to add or modify: ");
|
|
OLC_MODE(d) = MEDIT_SKILL_EDIT;
|
|
return;
|
|
case 'd':
|
|
case 'D':
|
|
write_to_output(d, "Enter skill name to delete: ");
|
|
OLC_MODE(d) = MEDIT_SKILL_EDIT;
|
|
OLC_VAL(d) = 1; /* delete mode */
|
|
return;
|
|
default:
|
|
medit_disp_skill_menu(d);
|
|
return;
|
|
}
|
|
break;
|
|
|
|
case MEDIT_SKILL_EDIT: {
|
|
char skillname[MAX_INPUT_LENGTH];
|
|
int snum;
|
|
|
|
skip_spaces(&arg);
|
|
strlcpy(skillname, arg, sizeof(skillname));
|
|
snum = find_skill_num(skillname);
|
|
|
|
if (snum <= 0 || snum >= MAX_SKILLS) {
|
|
write_to_output(d, "Invalid skill.\r\n");
|
|
medit_disp_skill_menu(d);
|
|
return;
|
|
}
|
|
|
|
/* Delete mode */
|
|
if (OLC_VAL(d) == 1) {
|
|
OLC_MOB(d)->mob_specials.skills[snum] = 0;
|
|
write_to_output(d, "Removed %s.\r\n", spell_info[snum].name);
|
|
OLC_VAL(d) = 0;
|
|
medit_disp_skill_menu(d);
|
|
return;
|
|
}
|
|
|
|
write_to_output(d, "Enter skill value (0-100): ");
|
|
OLC_VAL(d) = snum;
|
|
OLC_MODE(d) = MEDIT_SKILL_VALUE;
|
|
return;
|
|
}
|
|
break;
|
|
|
|
case MEDIT_SKILL_VALUE: {
|
|
int val = atoi(arg);
|
|
int snum = OLC_VAL(d);
|
|
|
|
val = MAX(0, MIN(100, val));
|
|
OLC_MOB(d)->mob_specials.skills[snum] = (byte)val;
|
|
|
|
write_to_output(d, "%s set to %d%%.\r\n", spell_info[snum].name, val);
|
|
medit_disp_skill_menu(d);
|
|
return;
|
|
}
|
|
break;
|
|
|
|
case MEDIT_CLASS_MENU:
|
|
i = atoi(arg);
|
|
if (i == 0) {
|
|
medit_disp_menu(d);
|
|
return;
|
|
}
|
|
if (i == NUM_CLASSES + 1) {
|
|
GET_CLASS(OLC_MOB(d)) = CLASS_UNDEFINED;
|
|
grant_class_skills(OLC_MOB(d), TRUE);
|
|
OLC_VAL(d) = TRUE;
|
|
write_to_output(d, "Class cleared.\r\n");
|
|
medit_disp_menu(d);
|
|
return;
|
|
}
|
|
if (i < 1 || i > NUM_CLASSES + 1) {
|
|
write_to_output(d, "Invalid choice!\r\n");
|
|
medit_disp_class_menu(d);
|
|
return;
|
|
}
|
|
GET_CLASS(OLC_MOB(d)) = i - 1;
|
|
grant_class_skills(OLC_MOB(d), TRUE);
|
|
OLC_VAL(d) = TRUE;
|
|
write_to_output(d, "Class set to %s.\r\n", pc_class_types[GET_CLASS(OLC_MOB(d))]);
|
|
medit_disp_menu(d);
|
|
return;
|
|
|
|
case MEDIT_SPECIES_MENU:
|
|
i = atoi(arg);
|
|
if (i == 0) {
|
|
medit_disp_menu(d);
|
|
return;
|
|
}
|
|
if (i == NUM_SPECIES + 1) {
|
|
GET_SPECIES(OLC_MOB(d)) = SPECIES_UNDEFINED;
|
|
OLC_VAL(d) = TRUE;
|
|
write_to_output(d, "Species cleared.\r\n");
|
|
medit_disp_menu(d);
|
|
return;
|
|
}
|
|
if (i < 1 || i > NUM_SPECIES + 1) {
|
|
write_to_output(d, "Invalid choice!\r\n");
|
|
medit_disp_species_menu(d);
|
|
return;
|
|
}
|
|
GET_SPECIES(OLC_MOB(d)) = i - 1;
|
|
OLC_VAL(d) = TRUE;
|
|
write_to_output(d, "Species set to %s.\r\n", species_types[GET_SPECIES(OLC_MOB(d))]);
|
|
medit_disp_menu(d);
|
|
return;
|
|
|
|
case OLC_SCRIPT_EDIT:
|
|
if (dg_script_edit_parse(d, arg)) return;
|
|
break;
|
|
|
|
case MEDIT_NAME:
|
|
smash_tilde(arg);
|
|
if (GET_NAME(OLC_MOB(d)))
|
|
free(GET_NAME(OLC_MOB(d)));
|
|
GET_NAME(OLC_MOB(d)) = str_udup(arg);
|
|
break;
|
|
|
|
case MEDIT_KEYWORD:
|
|
smash_tilde(arg);
|
|
if (GET_KEYWORDS(OLC_MOB(d)))
|
|
free(GET_KEYWORDS(OLC_MOB(d)));
|
|
GET_KEYWORDS(OLC_MOB(d)) = str_udup(arg);
|
|
break;
|
|
|
|
case MEDIT_S_DESC:
|
|
smash_tilde(arg);
|
|
if (GET_SDESC(OLC_MOB(d)))
|
|
free(GET_SDESC(OLC_MOB(d)));
|
|
GET_SDESC(OLC_MOB(d)) = str_udup(arg);
|
|
break;
|
|
|
|
case MEDIT_L_DESC:
|
|
smash_tilde(arg);
|
|
if (GET_LDESC(OLC_MOB(d)))
|
|
free(GET_LDESC(OLC_MOB(d)));
|
|
if (arg && *arg) {
|
|
char buf[MAX_INPUT_LENGTH];
|
|
snprintf(buf, sizeof(buf), "%s\r\n", arg);
|
|
GET_LDESC(OLC_MOB(d)) = strdup(buf);
|
|
} else
|
|
GET_LDESC(OLC_MOB(d)) = strdup("undefined");
|
|
|
|
break;
|
|
|
|
case MEDIT_D_DESC:
|
|
cleanup_olc(d, CLEANUP_ALL);
|
|
mudlog(BRF, LVL_BUILDER, TRUE, "SYSERR: OLC: medit_parse(): Reached D_DESC case!");
|
|
write_to_output(d, "Oops...\r\n");
|
|
break;
|
|
case MEDIT_BACKGROUND:
|
|
cleanup_olc(d, CLEANUP_ALL);
|
|
mudlog(BRF, LVL_BUILDER, TRUE, "SYSERR: OLC: medit_parse(): Reached BACKGROUND case!");
|
|
write_to_output(d, "Oops...\r\n");
|
|
break;
|
|
|
|
case MEDIT_NPC_FLAGS:
|
|
if ((i = atoi(arg)) <= 0)
|
|
break;
|
|
else if ( (j = medit_get_mob_flag_by_number(i)) == -1) {
|
|
write_to_output(d, "Invalid choice!\r\n");
|
|
write_to_output(d, "Enter mob flags (0 to quit) :");
|
|
return;
|
|
} else if (j <= NUM_MOB_FLAGS) {
|
|
TOGGLE_BIT_AR(MOB_FLAGS(OLC_MOB(d)), (j));
|
|
}
|
|
medit_disp_mob_flags(d);
|
|
return;
|
|
|
|
case MEDIT_AFF_FLAGS:
|
|
if ((i = atoi(arg)) <= 0)
|
|
break;
|
|
else if (i < NUM_AFF_FLAGS)
|
|
TOGGLE_BIT_AR(AFF_FLAGS(OLC_MOB(d)), i);
|
|
|
|
/* Remove unwanted bits right away. */
|
|
REMOVE_BIT_AR(AFF_FLAGS(OLC_MOB(d)), AFF_CHARM);
|
|
REMOVE_BIT_AR(AFF_FLAGS(OLC_MOB(d)), AFF_POISON);
|
|
REMOVE_BIT_AR(AFF_FLAGS(OLC_MOB(d)), AFF_SLEEP);
|
|
medit_disp_aff_flags(d);
|
|
return;
|
|
|
|
/* Numerical responses. */
|
|
|
|
case MEDIT_SEX:
|
|
GET_SEX(OLC_MOB(d)) = LIMIT(i - 1, 0, NUM_GENDERS - 1);
|
|
break;
|
|
|
|
case MEDIT_AGE:
|
|
if (i < MIN_CHAR_AGE || i > MAX_CHAR_AGE) {
|
|
write_to_output(d, "Age must be between %d and %d.\r\n",
|
|
MIN_CHAR_AGE, MAX_CHAR_AGE);
|
|
write_to_output(d, "Enter age (%d-%d): ", MIN_CHAR_AGE, MAX_CHAR_AGE);
|
|
return;
|
|
}
|
|
GET_ROLEPLAY_AGE(OLC_MOB(d)) = i;
|
|
GET_ROLEPLAY_AGE_YEAR(OLC_MOB(d)) = time_info.year;
|
|
OLC_VAL(d) = TRUE;
|
|
medit_disp_menu(d);
|
|
return;
|
|
|
|
case MEDIT_NUM_HP_DICE:
|
|
GET_HIT(OLC_MOB(d)) = LIMIT(i, 0, 30);
|
|
OLC_VAL(d) = TRUE;
|
|
medit_disp_stats_menu(d);
|
|
return;
|
|
|
|
case MEDIT_SIZE_HP_DICE:
|
|
GET_MANA(OLC_MOB(d)) = LIMIT(i, 0, 1000);
|
|
OLC_VAL(d) = TRUE;
|
|
medit_disp_stats_menu(d);
|
|
return;
|
|
|
|
case MEDIT_ADD_HP:
|
|
GET_STAMINA(OLC_MOB(d)) = LIMIT(i, 0, 30000);
|
|
OLC_VAL(d) = TRUE;
|
|
medit_disp_stats_menu(d);
|
|
return;
|
|
|
|
case MEDIT_STR:
|
|
GET_STR(OLC_MOB(d)) = LIMIT(i, 1, 25);
|
|
OLC_VAL(d) = TRUE;
|
|
medit_disp_stats_menu(d);
|
|
return;
|
|
|
|
case MEDIT_INT:
|
|
GET_INT(OLC_MOB(d)) = LIMIT(i, 1, 25);
|
|
OLC_VAL(d) = TRUE;
|
|
medit_disp_stats_menu(d);
|
|
return;
|
|
|
|
case MEDIT_WIS:
|
|
GET_WIS(OLC_MOB(d)) = LIMIT(i, 1, 25);
|
|
OLC_VAL(d) = TRUE;
|
|
medit_disp_stats_menu(d);
|
|
return;
|
|
|
|
case MEDIT_DEX:
|
|
GET_DEX(OLC_MOB(d)) = LIMIT(i, 1, 25);
|
|
OLC_VAL(d) = TRUE;
|
|
medit_disp_stats_menu(d);
|
|
return;
|
|
|
|
case MEDIT_CON:
|
|
GET_CON(OLC_MOB(d)) = LIMIT(i, 1, 25);
|
|
OLC_VAL(d) = TRUE;
|
|
medit_disp_stats_menu(d);
|
|
return;
|
|
|
|
case MEDIT_CHA:
|
|
GET_CHA(OLC_MOB(d)) = LIMIT(i, 1, 25);
|
|
OLC_VAL(d) = TRUE;
|
|
medit_disp_stats_menu(d);
|
|
return;
|
|
|
|
case MEDIT_SAVE_STR:
|
|
GET_SAVE(OLC_MOB(d), ABIL_STR) = LIMIT(atoi(arg), -20, 20);
|
|
OLC_VAL(d) = TRUE;
|
|
medit_disp_stats_menu(d);
|
|
return;
|
|
|
|
case MEDIT_SAVE_DEX:
|
|
GET_SAVE(OLC_MOB(d), ABIL_DEX) = LIMIT(atoi(arg), -20, 20);
|
|
OLC_VAL(d) = TRUE;
|
|
medit_disp_stats_menu(d);
|
|
return;
|
|
|
|
case MEDIT_SAVE_CON:
|
|
GET_SAVE(OLC_MOB(d), ABIL_CON) = LIMIT(atoi(arg), -20, 20);
|
|
OLC_VAL(d) = TRUE;
|
|
medit_disp_stats_menu(d);
|
|
return;
|
|
|
|
case MEDIT_SAVE_INT:
|
|
GET_SAVE(OLC_MOB(d), ABIL_INT) = LIMIT(atoi(arg), -20, 20);
|
|
OLC_VAL(d) = TRUE;
|
|
medit_disp_stats_menu(d);
|
|
return;
|
|
|
|
case MEDIT_SAVE_WIS:
|
|
GET_SAVE(OLC_MOB(d), ABIL_WIS) = LIMIT(atoi(arg), -20, 20);
|
|
OLC_VAL(d) = TRUE;
|
|
medit_disp_stats_menu(d);
|
|
return;
|
|
|
|
case MEDIT_SAVE_CHA:
|
|
GET_SAVE(OLC_MOB(d), ABIL_CHA) = LIMIT(atoi(arg), -20, 20);
|
|
OLC_VAL(d) = TRUE;
|
|
medit_disp_stats_menu(d);
|
|
return;
|
|
|
|
case MEDIT_POS:
|
|
GET_POS(OLC_MOB(d)) = LIMIT(i - 1, 0, NUM_POSITIONS - 1);
|
|
break;
|
|
|
|
case MEDIT_DEFAULT_POS:
|
|
GET_DEFAULT_POS(OLC_MOB(d)) = LIMIT(i - 1, 0, NUM_POSITIONS - 1);
|
|
break;
|
|
|
|
case MEDIT_ATTACK:
|
|
GET_ATTACK(OLC_MOB(d)) = LIMIT(i, 0, NUM_ATTACK_TYPES - 1);
|
|
break;
|
|
|
|
case MEDIT_LEVEL:
|
|
if (i != 1)
|
|
write_to_output(d, "Mobile levels are locked to 1 in this world; ignoring value.\r\n");
|
|
GET_LEVEL(OLC_MOB(d)) = 1;
|
|
OLC_VAL(d) = TRUE;
|
|
medit_disp_stats_menu(d);
|
|
return;
|
|
|
|
case MEDIT_ALIGNMENT:
|
|
GET_ALIGNMENT(OLC_MOB(d)) = LIMIT(i, -1000, 1000);
|
|
OLC_VAL(d) = TRUE;
|
|
medit_disp_stats_menu(d);
|
|
return;
|
|
|
|
case MEDIT_COPY:
|
|
if ((i = real_mobile(atoi(arg))) != NOWHERE) {
|
|
medit_setup_existing(d, i);
|
|
} else
|
|
write_to_output(d, "That mob does not exist.\r\n");
|
|
break;
|
|
|
|
case MEDIT_DELETE:
|
|
if (*arg == 'y' || *arg == 'Y') {
|
|
if (delete_mobile(GET_MOB_RNUM(OLC_MOB(d))) != NOBODY)
|
|
write_to_output(d, "Mobile deleted.\r\n");
|
|
else
|
|
write_to_output(d, "Couldn't delete the mobile!\r\n");
|
|
|
|
cleanup_olc(d, CLEANUP_ALL);
|
|
return;
|
|
} else if (*arg == 'n' || *arg == 'N') {
|
|
medit_disp_menu(d);
|
|
OLC_MODE(d) = MEDIT_MAIN_MENU;
|
|
return;
|
|
} else
|
|
write_to_output(d, "Please answer 'Y' or 'N': ");
|
|
break;
|
|
|
|
default:
|
|
/* We should never get here. */
|
|
cleanup_olc(d, CLEANUP_ALL);
|
|
mudlog(BRF, LVL_BUILDER, TRUE, "SYSERR: OLC: medit_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) = TRUE;
|
|
medit_disp_menu(d);
|
|
}
|
|
|
|
void medit_string_cleanup(struct descriptor_data *d, int terminator)
|
|
{
|
|
switch (OLC_MODE(d)) {
|
|
|
|
case MEDIT_D_DESC:
|
|
case MEDIT_BACKGROUND:
|
|
default:
|
|
medit_disp_menu(d);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static int roll_stat_for_cap(int cap)
|
|
{
|
|
int total = 0;
|
|
int dice_d4 = 0;
|
|
int remainder = 0;
|
|
|
|
if (cap <= 0)
|
|
return 0;
|
|
|
|
dice_d4 = cap / 4;
|
|
remainder = cap % 4;
|
|
|
|
if (dice_d4 > 0)
|
|
total += dice(dice_d4, 4);
|
|
if (remainder > 0)
|
|
total += dice(1, remainder);
|
|
|
|
return total;
|
|
}
|
|
|
|
static int autoroll_species_stat(struct char_data *mob, int ability)
|
|
{
|
|
int min = 0;
|
|
int cap = 0;
|
|
int mod = 0;
|
|
int roll_cap;
|
|
int total;
|
|
|
|
if (HAS_VALID_SPECIES(mob)) {
|
|
int species = GET_SPECIES(mob);
|
|
int species_min = species_ability_min(species, ability);
|
|
int species_cap = species_ability_cap(species, ability);
|
|
|
|
if (species_min > 0)
|
|
min = species_min;
|
|
if (species_cap > 0)
|
|
cap = species_cap;
|
|
|
|
mod = species_ability_mod(species, ability);
|
|
}
|
|
|
|
if (cap > 0 && min > cap)
|
|
min = cap;
|
|
|
|
roll_cap = (cap > 0) ? (cap - mod) : (18 - mod);
|
|
if (roll_cap < 1)
|
|
roll_cap = 1;
|
|
|
|
total = roll_stat_for_cap(roll_cap) + mod;
|
|
|
|
if (cap > 0 && total > cap)
|
|
total = cap;
|
|
if (min > 0 && total < min)
|
|
total = min;
|
|
|
|
return total;
|
|
}
|
|
|
|
void medit_autoroll_stats(struct descriptor_data *d)
|
|
{
|
|
int mob_lev = GET_LEVEL(OLC_MOB(d));
|
|
|
|
if (mob_lev < 1)
|
|
mob_lev = 1;
|
|
|
|
GET_STAMINA(OLC_MOB(d)) = mob_lev * 10; /* hit point bonus (mobs don't use stamina points) */
|
|
GET_HIT(OLC_MOB(d)) = mob_lev / 5; /* number of hitpoint dice */
|
|
GET_MANA(OLC_MOB(d)) = mob_lev / 5; /* size of hitpoint dice */
|
|
|
|
/* 'Advanced' stats are only rolled if advanced options are enabled */
|
|
if (CONFIG_MEDIT_ADVANCED) {
|
|
GET_STR(OLC_MOB(d)) = autoroll_species_stat(OLC_MOB(d), ABIL_STR);
|
|
GET_INT(OLC_MOB(d)) = autoroll_species_stat(OLC_MOB(d), ABIL_INT);
|
|
GET_WIS(OLC_MOB(d)) = autoroll_species_stat(OLC_MOB(d), ABIL_WIS);
|
|
GET_DEX(OLC_MOB(d)) = autoroll_species_stat(OLC_MOB(d), ABIL_DEX);
|
|
GET_CON(OLC_MOB(d)) = autoroll_species_stat(OLC_MOB(d), ABIL_CON);
|
|
GET_CHA(OLC_MOB(d)) = autoroll_species_stat(OLC_MOB(d), ABIL_CHA);
|
|
|
|
/* New ability-based saving throws: all default to 1/4 of mob level */
|
|
GET_SAVE(OLC_MOB(d), ABIL_STR) = mob_lev / 4;
|
|
GET_SAVE(OLC_MOB(d), ABIL_DEX) = mob_lev / 4;
|
|
GET_SAVE(OLC_MOB(d), ABIL_CON) = mob_lev / 4;
|
|
GET_SAVE(OLC_MOB(d), ABIL_INT) = mob_lev / 4;
|
|
GET_SAVE(OLC_MOB(d), ABIL_WIS) = mob_lev / 4;
|
|
GET_SAVE(OLC_MOB(d), ABIL_CHA) = mob_lev / 4;
|
|
}
|
|
}
|