/************************************************************************
* OasisOLC - medit.c v1.5 *
* Copyright 1996 Harvey Gilpin. *
************************************************************************/
#include "conf.h"
#include "sysdep.h"
#include "structs.h"
#include "comm.h"
#include "spells.h"
#include "utils.h"
#include "db.h"
#include "shop.h"
#include "olc.h"
#include "handler.h"
#include "dg_olc.h"
/*
* Set this to 1 for debugging logs in medit_save_internally.
*/
#if 0
#define DEBUG
#endif
/*
* Set this to 1 as a last resort to save mobiles.
*/
#if 0
#define I_CRASH
#endif
/*-------------------------------------------------------------------*/
/*
* External variable declarations.
*/
extern struct index_data *mob_index;
extern struct char_data *mob_proto;
extern struct char_data *character_list;
extern int top_of_mobt;
extern struct zone_data *zone_table;
extern int top_of_zone_table;
extern struct player_special_data dummy_mob;
extern struct attack_hit_type attack_hit_text[];
extern const char *action_bits[];
extern const char *affected_bits[];
extern const char *position_types[];
extern const char *genders[];
extern int top_shop;
extern struct shop_data *shop_index;
extern struct descriptor_data *descriptor_list;
#if defined(OASIS_MPROG)
extern const char *mobprog_types[];
#endif
/*-------------------------------------------------------------------*/
/*
* Handy internal macros.
*/
#define GET_NDD(mob) ((mob)->mob_specials.damnodice)
#define GET_SDD(mob) ((mob)->mob_specials.damsizedice)
#define GET_ALIAS(mob) ((mob)->player.name)
#define GET_SDESC(mob) ((mob)->player.short_descr)
#define GET_LDESC(mob) ((mob)->player.long_descr)
#define GET_DDESC(mob) ((mob)->player.description)
#define GET_ATTACK(mob) ((mob)->mob_specials.attack_type)
#define GET_NUM_ATTACKS(mob) ((mob)->mob_specials.num_attacks)
#define S_KEEPER(shop) ((shop)->keeper)
#if defined(OASIS_MPROG)
#define GET_MPROG(mob) (mob_index[(mob)->nr].mobprogs)
#define GET_MPROG_TYPE(mob) (mob_index[(mob)->nr].progtypes)
#endif
/*-------------------------------------------------------------------*/
/*
* Function prototypes.
*/
void medit_parse(struct descriptor_data *d, char *arg);
void medit_disp_menu(struct descriptor_data *d);
void medit_setup_new(struct descriptor_data *d);
void medit_setup_existing(struct descriptor_data *d, int rmob_num);
void medit_save_internally(struct descriptor_data *d);
void medit_save_to_disk(int zone_num);
void init_mobile(struct char_data *mob);
void copy_mobile(struct char_data *tmob, struct char_data *fmob);
void medit_disp_positions(struct descriptor_data *d);
void medit_disp_mob_flags(struct descriptor_data *d);
void medit_disp_aff_flags(struct descriptor_data *d);
void medit_disp_attack_types(struct descriptor_data *d);
#if defined(OASIS_MPROG)
void medit_disp_mprog(struct descriptor_data *d);
void medit_change_mprog(struct descriptor_data *d);
const char *medit_get_mprog_type(struct mob_prog_data *mprog);
#endif
/*-------------------------------------------------------------------*\
utility functions
\*-------------------------------------------------------------------*/
/*
* Free a mobile structure that has been edited.
* Take care of existing mobiles and their mob_proto!
*/
void medit_free_mobile(struct char_data *mob)
{
int i;
/*
* Non-prototyped mobile. Also known as new mobiles.
*/
if (!mob)
return;
else if (GET_MOB_RNUM(mob) == -1) {
if (mob->player.name)
free(mob->player.name);
if (mob->player.title)
free(mob->player.title);
if (mob->player.short_descr)
free(mob->player.short_descr);
if (mob->player.long_descr)
free(mob->player.long_descr);
if (mob->player.description)
free(mob->player.description);
} else if ((i = GET_MOB_RNUM(mob)) > -1) { /* Prototyped mobile. */
if (mob->player.name && mob->player.name != mob_proto[i].player.name)
free(mob->player.name);
if (mob->player.title && mob->player.title != mob_proto[i].player.title)
free(mob->player.title);
if (mob->player.short_descr && mob->player.short_descr != mob_proto[i].player.short_descr)
free(mob->player.short_descr);
if (mob->player.long_descr && mob->player.long_descr != mob_proto[i].player.long_descr)
free(mob->player.long_descr);
if (mob->player.description && mob->player.description != mob_proto[i].player.description)
free(mob->player.description);
}
while (mob->affected)
affect_remove(mob, mob->affected);
free(mob);
}
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) = -1;
/*
* Set up some default strings.
*/
GET_ALIAS(mob) = str_dup("mob unfinished");
GET_SDESC(mob) = str_dup("the unfinished mob");
GET_LDESC(mob) = str_dup("An unfinished mob stands here.\r\n");
GET_DDESC(mob) = str_dup("It looks unfinished.\r\n");
#if defined(OASIS_MPROG)
OLC_MPROGL(d) = NULL;
OLC_MPROG(d) = NULL;
#endif
OLC_MOB(d) = mob;
OLC_VAL(d) = 0; /* Has changed flag. (It hasn't so far, we just made it.) */
OLC_ITEM_TYPE(d) = MOB_TRIGGER;
medit_disp_menu(d);
}
/*-------------------------------------------------------------------*/
void medit_setup_existing(struct descriptor_data *d, int rmob_num)
{
struct char_data *mob;
#if defined(OASIS_MPROG)
MPROG_DATA *temp;
MPROG_DATA *head;
#endif
/*
* Allocate a scratch mobile structure.
*/
CREATE(mob, struct char_data, 1);
copy_mobile(mob, mob_proto + rmob_num);
#if defined(OASIS_MPROG)
/*
* I think there needs to be a brace from the if statement to the #endif
* according to the way the original patch was indented. If this crashes,
* try it with the braces and report to greerga@van.ml.org on if that works.
*/
if (GET_MPROG(mob))
CREATE(OLC_MPROGL(d), MPROG_DATA, 1);
head = OLC_MPROGL(d);
for (temp = GET_MPROG(mob); temp;temp = temp->next) {
OLC_MPROGL(d)->type = temp->type;
OLC_MPROGL(d)->arglist = str_dup(temp->arglist);
OLC_MPROGL(d)->comlist = str_dup(temp->comlist);
if (temp->next) {
CREATE(OLC_MPROGL(d)->next, MPROG_DATA, 1);
OLC_MPROGL(d) = OLC_MPROGL(d)->next;
}
}
OLC_MPROGL(d) = head;
OLC_MPROG(d) = OLC_MPROGL(d);
#endif
OLC_MOB(d) = mob;
OLC_ITEM_TYPE(d) = MOB_TRIGGER;
dg_olc_script_copy(d);
medit_disp_menu(d);
}
/*-------------------------------------------------------------------*/
/*
* Copy one mob struct to another.
*/
void copy_mobile(struct char_data *tmob, struct char_data *fmob)
{
struct trig_proto_list *proto, *fproto;
/*
* Free up any used strings.
*/
if (GET_ALIAS(tmob))
free(GET_ALIAS(tmob));
if (GET_SDESC(tmob))
free(GET_SDESC(tmob));
if (GET_LDESC(tmob))
free(GET_LDESC(tmob));
if (GET_DDESC(tmob))
free(GET_DDESC(tmob));
/* delete the old script list */
proto = tmob->proto_script;
while (proto) {
fproto = proto;
proto = proto->next;
free(fproto);
}
/*
* Copy mob over.
*/
*tmob = *fmob;
/*
* Reallocate strings.
*/
GET_ALIAS(tmob) = str_dup((GET_ALIAS(fmob) && *GET_ALIAS(fmob)) ? GET_ALIAS(fmob) : "undefined");
GET_SDESC(tmob) = str_dup((GET_SDESC(fmob) && *GET_SDESC(fmob)) ? GET_SDESC(fmob) : "undefined");
GET_LDESC(tmob) = str_dup((GET_LDESC(fmob) && *GET_LDESC(fmob)) ? GET_LDESC(fmob) : "undefined");
GET_DDESC(tmob) = str_dup((GET_DDESC(fmob) && *GET_DDESC(fmob)) ? GET_DDESC(fmob) : "undefined");
/* copy the new script list */
if (fmob->proto_script) {
fproto = fmob->proto_script;
CREATE(proto, struct trig_proto_list, 1);
tmob->proto_script = proto;
do {
proto->vnum = fproto->vnum;
fproto = fproto->next;
if (fproto) {
CREATE(proto->next, struct trig_proto_list, 1);
proto = proto->next;
}
} while (fproto);
}
}
/*-------------------------------------------------------------------*/
/*
* Ideally, this function should be in db.c, but I'll put it here for
* portability.
*/
void init_mobile(struct char_data *mob)
{
clear_char(mob);
GET_HIT(mob) = GET_MANA(mob) = 1;
GET_MAX_MANA(mob) = GET_MAX_MOVE(mob) = 100;
GET_NDD(mob) = GET_SDD(mob) = 1;
GET_WEIGHT(mob) = 200;
GET_HEIGHT(mob) = 198;
mob->real_abils.str = mob->real_abils.intel = mob->real_abils.wis = 11;
mob->real_abils.dex = mob->real_abils.con = mob->real_abils.cha = 11;
mob->aff_abils = mob->real_abils;
SET_BIT(MOB_FLAGS(mob), MOB_ISNPC);
mob->player_specials = &dummy_mob;
}
/*-------------------------------------------------------------------*/
#define ZCMD zone_table[zone].cmd[cmd_no]
/*
* Save new/edited mob to memory.
*/
void medit_save_internally(struct descriptor_data *d)
{
int rmob_num, found = 0, new_mob_num = 0, zone, cmd_no, shop;
struct char_data *new_proto;
struct index_data *new_index;
struct char_data *live_mob;
struct descriptor_data *dsc;
/* put the script into proper position */
OLC_MOB(d)->proto_script = OLC_SCRIPT(d);
/*
* Mob exists? Just update it.
*/
if ((rmob_num = real_mobile(OLC_NUM(d))) != -1) {
OLC_MOB(d)->proto_script = OLC_SCRIPT(d);
copy_mobile((mob_proto + rmob_num), OLC_MOB(d));
/*
* Update live mobiles.
*/
for (live_mob = character_list; live_mob; live_mob = live_mob->next)
if (IS_MOB(live_mob) && GET_MOB_RNUM(live_mob) == rmob_num) {
/*
* Only really need to update the strings, since these can
* cause protection faults. The rest can wait till a reset/reboot.
*/
GET_ALIAS(live_mob) = GET_ALIAS(mob_proto + rmob_num);
GET_SDESC(live_mob) = GET_SDESC(mob_proto + rmob_num);
GET_LDESC(live_mob) = GET_LDESC(mob_proto + rmob_num);
GET_DDESC(live_mob) = GET_DDESC(mob_proto + rmob_num);
}
}
/*
* Mob does not exist, we have to add it.
*/
else {
#if defined(DEBUG)
fprintf(stderr, "top_of_mobt: %d, new top_of_mobt: %d\n", top_of_mobt, top_of_mobt + 1);
#endif
CREATE(new_proto, struct char_data, top_of_mobt + 2);
CREATE(new_index, struct index_data, top_of_mobt + 2);
for (rmob_num = 0; rmob_num <= top_of_mobt; rmob_num++) {
if (!found) { /* Is this the place? */
/* if ((rmob_num > top_of_mobt) || (mob_index[rmob_num].vnum > OLC_NUM(d))) {*/
if (mob_index[rmob_num].vnum > OLC_NUM(d)) {
/*
* Yep, stick it here.
*/
found = TRUE;
#if defined(DEBUG)
fprintf(stderr, "Inserted: rmob_num: %d\n", rmob_num);
#endif
new_index[rmob_num].vnum = OLC_NUM(d);
new_index[rmob_num].number = 0;
new_index[rmob_num].func = NULL;
new_mob_num = rmob_num;
GET_MOB_RNUM(OLC_MOB(d)) = rmob_num;
copy_mobile((new_proto + rmob_num), OLC_MOB(d));
/*
* Copy the mob that should be here on top.
*/
new_index[rmob_num + 1] = mob_index[rmob_num];
new_proto[rmob_num + 1] = mob_proto[rmob_num];
GET_MOB_RNUM(new_proto + rmob_num + 1) = rmob_num + 1;
} else { /* Nope, copy over as normal. */
new_index[rmob_num] = mob_index[rmob_num];
new_proto[rmob_num] = mob_proto[rmob_num];
}
} else { /* We've already found it, copy the rest over. */
new_index[rmob_num + 1] = mob_index[rmob_num];
new_proto[rmob_num + 1] = mob_proto[rmob_num];
GET_MOB_RNUM(new_proto + rmob_num + 1) = rmob_num + 1;
}
}
#if defined(DEBUG)
fprintf(stderr, "rmob_num: %d, top_of_mobt: %d, array size: 0-%d (%d)\n",
rmob_num, top_of_mobt, top_of_mobt + 1, top_of_mobt + 2);
#endif
if (!found) { /* Still not found, must add it to the top of the table. */
#if defined(DEBUG)
fprintf(stderr, "Append.\n");
#endif
new_index[rmob_num].vnum = OLC_NUM(d);
new_index[rmob_num].number = 0;
new_index[rmob_num].func = NULL;
new_mob_num = rmob_num;
GET_MOB_RNUM(OLC_MOB(d)) = rmob_num;
copy_mobile((new_proto + rmob_num), OLC_MOB(d));
}
/*
* Replace tables.
*/
#if defined(DEBUG)
fprintf(stderr, "Attempted free.\n");
#endif
#if !defined(I_CRASH)
free(mob_index);
free(mob_proto);
#endif
mob_index = new_index;
mob_proto = new_proto;
top_of_mobt++;
#if defined(DEBUG)
fprintf(stderr, "Free ok.\n");
#endif
/*
* Update live mobile rnums.
*/
for (live_mob = character_list; live_mob; live_mob = live_mob->next)
if (GET_MOB_RNUM(live_mob) > new_mob_num)
GET_MOB_RNUM(live_mob)++;
/*
* Update zone table.
*/
for (zone = 0; zone <= top_of_zone_table; zone++)
for (cmd_no = 0; ZCMD.command != 'S'; cmd_no++)
if (ZCMD.command == 'M')
if (ZCMD.arg1 >= new_mob_num)
ZCMD.arg1++;
/*
* Update shop keepers.
*/
if (shop_index)
for (shop = 0; shop <= top_shop; shop++)
if (SHOP_KEEPER(shop) >= new_mob_num)
SHOP_KEEPER(shop)++;
/*
* Update keepers in shops being edited and other mobs being edited.
*/
for (dsc = descriptor_list; dsc; dsc = dsc->next)
if (dsc->connected == CON_SEDIT) {
if (S_KEEPER(OLC_SHOP(dsc)) >= new_mob_num)
S_KEEPER(OLC_SHOP(dsc))++;
} else if (dsc->connected == CON_MEDIT) {
if (GET_MOB_RNUM(OLC_MOB(dsc)) >= new_mob_num)
GET_MOB_RNUM(OLC_MOB(dsc))++;
}
}
#if defined(OASIS_MPROG)
GET_MPROG(OLC_MOB(d)) = OLC_MPROGL(d);
GET_MPROG_TYPE(OLC_MOB(d)) = (OLC_MPROGL(d) ? OLC_MPROGL(d)->type : 0);
while (OLC_MPROGL(d)) {
GET_MPROG_TYPE(OLC_MOB(d)) |= OLC_MPROGL(d)->type;
OLC_MPROGL(d) = OLC_MPROGL(d)->next;
}
#endif
olc_add_to_save_list(zone_table[OLC_ZNUM(d)].number, OLC_SAVE_MOB);
}
/*-------------------------------------------------------------------*/
/*
* Save ALL mobiles for a zone to their .mob file, mobs are all
* saved in Extended format, regardless of whether they have any
* extended fields. Thanks to Sammy for ideas on this bit of code.
*/
void medit_save_to_disk(int zone_num)
{
int i, rmob_num, zone, top;
FILE *mob_file;
char fname[64];
struct char_data *mob;
#if defined(OASIS_MPROG)
MPROG_DATA *mob_prog = NULL;
#endif
zone = zone_table[zone_num].number;
top = zone_table[zone_num].top;
sprintf(fname, "%s/%d.new", MOB_PREFIX, zone);
if (!(mob_file = fopen(fname, "w"))) {
mudlog("SYSERR: OLC: Cannot open mob file!", BRF, LVL_IMMORT, TRUE);
return;
}
/*
* Seach the database for mobs in this zone and save them.
*/
for (i = zone * 100; i <= top; i++) {
if ((rmob_num = real_mobile(i)) != -1) {
if (fprintf(mob_file, "#%d\n", i) < 0) {
mudlog("SYSERR: OLC: Cannot write mob file!\r\n", BRF, LVL_IMMORT, TRUE);
fclose(mob_file);
return;
}
mob = (mob_proto + rmob_num);
/*
* Clean up strings.
*/
strcpy(buf1, (GET_LDESC(mob) && *GET_LDESC(mob)) ? GET_LDESC(mob) : "undefined");
strip_string(buf1);
strcpy(buf2, (GET_DDESC(mob) && *GET_DDESC(mob)) ? GET_DDESC(mob) : "undefined");
strip_string(buf2);
fprintf(mob_file, "%s~\n"
"%s~\n"
"%s~\n"
"%s~\n"
"%ld %ld %d E\n"
"%Ld %d %d %dd%d+%d %dd%d+%d\n"
"%d %Ld\n"
"%d %d %d\n",
(GET_ALIAS(mob) && *GET_ALIAS(mob)) ? GET_ALIAS(mob) : "undefined",
(GET_SDESC(mob) && *GET_SDESC(mob)) ? GET_SDESC(mob) : "undefined",
buf1, buf2, MOB_FLAGS(mob), AFF_FLAGS(mob), GET_ALIGNMENT(mob),
GET_LEVEL(mob), 20 - GET_HITROLL(mob), /* Hitroll -> THAC0 */
GET_AC(mob) / 10, GET_HIT(mob), GET_MANA(mob), GET_MOVE(mob),
GET_NDD(mob), GET_SDD(mob), GET_DAMROLL(mob), GET_GOLD(mob),
GET_EXP(mob), GET_POS(mob), GET_DEFAULT_POS(mob), GET_SEX(mob)
);
/*
* Deal with Extra stats in case they are there.
*/
if (GET_ATTACK(mob) != 0)
fprintf(mob_file, "BareHandAttack: %d\n", GET_ATTACK(mob));
if (GET_NUM_ATTACKS(mob) != 0)
fprintf(mob_file, "NumAttacks: %d\n", GET_NUM_ATTACKS(mob));
if (GET_STR(mob) != 11)
fprintf(mob_file, "Str: %d\n", GET_STR(mob));
if (GET_ADD(mob) != 0)
fprintf(mob_file, "StrAdd: %d\n", GET_ADD(mob));
if (GET_DEX(mob) != 11)
fprintf(mob_file, "Dex: %d\n", GET_DEX(mob));
if (GET_INT(mob) != 11)
fprintf(mob_file, "Int: %d\n", GET_INT(mob));
if (GET_WIS(mob) != 11)
fprintf(mob_file, "Wis: %d\n", GET_WIS(mob));
if (GET_CON(mob) != 11)
fprintf(mob_file, "Con: %d\n", GET_CON(mob));
if (GET_CHA(mob) != 11)
fprintf(mob_file, "Cha: %d\n", GET_CHA(mob));
/*
* XXX: Add E-mob handlers here.
*/
fprintf(mob_file, "E\n");
script_save_to_disk(mob_file, mob, MOB_TRIGGER);
#if defined(OASIS_MPROG)
/*
* Write out the MobProgs.
*/
mob_prog = GET_MPROG(mob);
while(mob_prog) {
strcpy(buf1, mob_prog->arglist);
strip_string(buf1);
strcpy(buf2, mob_prog->comlist);
strip_string(buf2);
fprintf(mob_file, "%s %s~\n%s", medit_get_mprog_type(mob_prog),
buf1, buf2);
mob_prog = mob_prog->next;
fprintf(mob_file, "~\n%s", (!mob_prog ? "|\n" : ""));
}
#endif
}
}
fprintf(mob_file, "$\n");
fclose(mob_file);
sprintf(buf2, "%s/%d.mob", MOB_PREFIX, zone);
/*
* We're fubar'd if we crash between the two lines below.
*/
remove(buf2);
rename(fname, buf2);
olc_remove_from_save_list(zone_table[zone_num].number, OLC_SAVE_MOB);
}
/**************************************************************************
Menu functions
**************************************************************************/
/*
* Display positions. (sitting, standing, etc)
*/
void medit_disp_positions(struct descriptor_data *d)
{
int i;
get_char_cols(d->character);
#if defined(CLEAR_SCREEN)
send_to_char("[H[J", d->character);
#endif
for (i = 0; *position_types[i] != '\n'; i++) {
sprintf(buf, "%s%2d%s) %s\r\n", grn, i, nrm, position_types[i]);
send_to_char(buf, d->character);
}
send_to_char("Enter position number : ", d->character);
}
/*-------------------------------------------------------------------*/
#if defined(OASIS_MPROG)
/*
* Get the type of MobProg.
*/
const char *medit_get_mprog_type(struct mob_prog_data *mprog)
{
switch (mprog->type) {
case IN_FILE_PROG: return ">in_file_prog";
case ACT_PROG: return ">act_prog";
case SPEECH_PROG: return ">speech_prog";
case RAND_PROG: return ">rand_prog";
case FIGHT_PROG: return ">fight_prog";
case HITPRCNT_PROG: return ">hitprcnt_prog";
case DEATH_PROG: return ">death_prog";
case ENTRY_PROG: return ">entry_prog";
case GREET_PROG: return ">greet_prog";
case ALL_GREET_PROG: return ">all_greet_prog";
case GIVE_PROG: return ">give_prog";
case BRIBE_PROG: return ">bribe_prog";
}
return ">ERROR_PROG";
}
/*-------------------------------------------------------------------*/
/*
* Display the MobProgs.
*/
void medit_disp_mprog(struct descriptor_data *d)
{
struct mob_prog_data *mprog = OLC_MPROGL(d);
OLC_MTOTAL(d) = 1;
#if defined(CLEAR_SCREEN)
send_to_char("^[[H^[[J", d->character);
#endif
while (mprog) {
sprintf(buf, "%d) %s %s\r\n", OLC_MTOTAL(d), medit_get_mprog_type(mprog),
(mprog->arglist ? mprog->arglist : "NONE"));
send_to_char(buf, d->character);
OLC_MTOTAL(d)++;
mprog = mprog->next;
}
sprintf(buf, "%d) Create New Mob Prog\r\n"
"%d) Purge Mob Prog\r\n"
"Enter number to edit [0 to exit]: ",
OLC_MTOTAL(d), OLC_MTOTAL(d) + 1);
send_to_char(buf, d->character);
OLC_MODE(d) = MEDIT_MPROG;
}
/*-------------------------------------------------------------------*/
/*
* Change the MobProgs.
*/
void medit_change_mprog(struct descriptor_data *d)
{
#if defined(CLEAR_SCREEN)
send_to_char("^[[H^[[J", d->character);
#endif
sprintf(buf, "1) Type: %s\r\n"
"2) Args: %s\r\n"
"3) Commands:\r\n%s\r\n\r\n"
"Enter number to edit [0 to exit]: ",
medit_get_mprog_type(OLC_MPROG(d)),
(OLC_MPROG(d)->arglist ? OLC_MPROG(d)->arglist: "NONE"),
(OLC_MPROG(d)->comlist ? OLC_MPROG(d)->comlist : "NONE"));
send_to_char(buf, d->character);
OLC_MODE(d) = MEDIT_CHANGE_MPROG;
}
/*-------------------------------------------------------------------*/
/*
* Change the MobProg type.
*/
void medit_disp_mprog_types(struct descriptor_data *d)
{
int i;
get_char_cols(d->character);
#if defined(CLEAR_SCREEN)
send_to_char("^[[H^[[J", d->character);
#endif
for (i = 0; i < NUM_PROGS-1; i++) {
sprintf(buf, "%s%2d%s) %s\r\n", grn, i, nrm, mobprog_types[i]);
send_to_char(buf, d->character);
}
send_to_char("Enter mob prog type : ", d->character);
OLC_MODE(d) = MEDIT_MPROG_TYPE;
}
#endif
/*-------------------------------------------------------------------*/
/*
* Display the gender of the mobile.
*/
void medit_disp_sex(struct descriptor_data *d)
{
int i;
get_char_cols(d->character);
#if defined(CLEAR_SCREEN)
send_to_char("[H[J", d->character);
#endif
for (i = 0; i < NUM_GENDERS; i++) {
sprintf(buf, "%s%2d%s) %s\r\n", grn, i, nrm, genders[i]);
send_to_char(buf, d->character);
}
send_to_char("Enter gender number : ", d->character);
}
/*-------------------------------------------------------------------*/
/*
* Display attack types menu.
*/
void medit_disp_attack_types(struct descriptor_data *d)
{
int i;
get_char_cols(d->character);
#if defined(CLEAR_SCREEN)
send_to_char("[H[J", d->character);
#endif
for (i = 0; i < NUM_ATTACK_TYPES; i++) {
sprintf(buf, "%s%2d%s) %s\r\n", grn, i, nrm, attack_hit_text[i].singular);
send_to_char(buf, d->character);
}
send_to_char("Enter attack type : ", d->character);
}
/*-------------------------------------------------------------------*/
/*
* Display mob-flags menu.
*/
void medit_disp_mob_flags(struct descriptor_data *d)
{
int i, columns = 0;
get_char_cols(d->character);
#if defined(CLEAR_SCREEN)
send_to_char("[H[J", d->character);
#endif
for (i = 0; i < NUM_MOB_FLAGS; i++) {
sprintf(buf, "%s%2d%s) %-20.20s %s", grn, i + 1, nrm, action_bits[i],
!(++columns % 2) ? "\r\n" : "");
send_to_char(buf, d->character);
}
sprintbit(MOB_FLAGS(OLC_MOB(d)), action_bits, buf1);
sprintf(buf, "\r\nCurrent flags : %s%s%s\r\nEnter mob flags (0 to quit) : ",
cyn, buf1, nrm);
send_to_char(buf, d->character);
}
/*-------------------------------------------------------------------*/
/*
* Display affection flags menu.
*/
void medit_disp_aff_flags(struct descriptor_data *d)
{
int i, columns = 0;
get_char_cols(d->character);
#if defined(CLEAR_SCREEN)
send_to_char("[H[J", d->character);
#endif
for (i = 0; i < NUM_AFF_FLAGS; i++) {
sprintf(buf, "%s%2d%s) %-20.20s %s", grn, i + 1, nrm, affected_bits[i],
!(++columns % 2) ? "\r\n" : "");
send_to_char(buf, d->character);
}
sprintbit(AFF_FLAGS(OLC_MOB(d)), affected_bits, buf1);
sprintf(buf, "\r\nCurrent flags : %s%s%s\r\nEnter aff flags (0 to quit) : ",
cyn, buf1, nrm);
send_to_char(buf, d->character);
}
/*-------------------------------------------------------------------*/
/*
* Display main menu.
*/
void medit_disp_menu(struct descriptor_data *d)
{
struct char_data *mob;
mob = OLC_MOB(d);
get_char_cols(d->character);
sprintf(buf,
#if defined(CLEAR_SCREEN)
"[H[J"
#endif
"-- Mob Number: [%s%d%s]\r\n"
"%s1%s) Sex: %s%-7.7s%s %s2%s) Alias: %s%s\r\n"
"%s3%s) S-Desc: %s%s\r\n"
"%s4%s) L-Desc:-\r\n%s%s"
"%s5%s) D-Desc:-\r\n%s%s"
"%s6%s) Level: [%s%9Ld%s], %s7%s) Alignment: [%s%4d%s]\r\n"
"%s8%s) Hitroll: [%s%4d%s], %s9%s) Damroll: [%s%4d%s]\r\n"
"%sA%s) NumDamDice: [%s%4d%s], %sB%s) SizeDamDice: [%s%4d%s]\r\n"
"%sC%s) Num HP Dice: [%s%4d%s], %sD%s) Size HP Dice: [%s%4d%s], %sE%s) HP Bonus: [%s%5d%s]\r\n"
"%sF%s) Armor Class: [%s%4d%s], %sG%s) Exp: [%s%9Ld%s], %sH%s) Gold: [%s%8d%s]\r\n",
cyn, OLC_NUM(d), nrm,
grn, nrm, yel, genders[(int)GET_SEX(mob)], nrm,
grn, nrm, yel, GET_ALIAS(mob),
grn, nrm, yel, GET_SDESC(mob),
grn, nrm, yel, GET_LDESC(mob),
grn, nrm, yel, GET_DDESC(mob),
grn, nrm, cyn, GET_LEVEL(mob), nrm,
grn, nrm, cyn, GET_ALIGNMENT(mob), nrm,
grn, nrm, cyn, GET_HITROLL(mob), nrm,
grn, nrm, cyn, GET_DAMROLL(mob), nrm,
grn, nrm, cyn, GET_NDD(mob), nrm,
grn, nrm, cyn, GET_SDD(mob), nrm,
grn, nrm, cyn, GET_HIT(mob), nrm,
grn, nrm, cyn, GET_MANA(mob), nrm,
grn, nrm, cyn, GET_MOVE(mob), nrm,
grn, nrm, cyn, GET_AC(mob), nrm,
grn, nrm, cyn, GET_EXP(mob), nrm,
grn, nrm, cyn, GET_GOLD(mob), nrm
);
send_to_char(buf, d->character);
sprintbit(MOB_FLAGS(mob), action_bits, buf1);
sprintbit(AFF_FLAGS(mob), affected_bits, buf2);
sprintf(buf,
"%sI%s) Position : %s%s\r\n"
"%sJ%s) Default : %s%s\r\n"
"%sK%s) Attack : %s%s\r\n"
"%sN%s) Num Attks : %s%d\r\n"
"%sO%s) Mobs Ki : %s%4d%s\r\n"
"%sL%s) NPC Flags : %s%s\r\n"
"%sM%s) AFF Flags : %s%s\r\n"
#if defined(OASIS_MPROG)
"%sP%s) Mob Progs : %s%s\r\n"
#endif
"%sS%s) Script : %s%s\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[GET_ATTACK(mob)].singular,
grn, nrm, yel, GET_NUM_ATTACKS(mob),
grn, nrm, cyn, GET_MANA(mob), nrm,
grn, nrm, cyn, buf1,
grn, nrm, cyn, buf2,
#if defined(OASIS_MPROG)
grn, nrm, cyn, (OLC_MPROGL(d) ? "Set." : "Not Set."),
#endif
grn, nrm, cyn, mob->proto_script?"Set.":"Not Set.",
grn, nrm
);
send_to_char(buf, d->character);
OLC_MODE(d) = MEDIT_MAIN_MENU;
}
/************************************************************************
* The GARGANTAUN event handler *
************************************************************************/
void medit_parse(struct descriptor_data *d, char *arg)
{
int i;
if (OLC_MODE(d) > MEDIT_NUMERICAL_RESPONSE) {
if (!*arg || (!isdigit(arg[0]) && ((*arg == '-') && (!isdigit(arg[1]))))) {
send_to_char("Field must be numerical, try again : ", d->character);
return;
}
}
switch (OLC_MODE(d)) {
/*-------------------------------------------------------------------*/
case MEDIT_CONFIRM_SAVESTRING:
/*
* Ensure mob has MOB_ISNPC set or things will go pair shaped.
*/
SET_BIT(MOB_FLAGS(OLC_MOB(d)), MOB_ISNPC);
switch (*arg) {
case 'y':
case 'Y':
/*
* Save the mob in memory and to disk.
*/
send_to_char("Saving mobile to memory.\r\n", d->character);
medit_save_internally(d);
sprintf(buf, "OLC: %s edits mob %d", GET_NAME(d->character), OLC_NUM(d));
mudlog(buf, CMP, MAX(LVL_IMMORT, GET_INVIS_LEV(d->character)), TRUE);
/* FALL THROUGH */
case 'n':
case 'N':
cleanup_olc(d, CLEANUP_ALL);
return;
default:
send_to_char("Invalid choice!\r\n", d->character);
send_to_char("Do you wish to save the mobile? : ", d->character);
return;
}
break;
/*-------------------------------------------------------------------*/
case MEDIT_MAIN_MENU:
i = 0;
switch (*arg) {
case 'q':
case 'Q':
if (OLC_VAL(d)) { /* Anything been changed? */
send_to_char("Do you wish to save the changes to the mobile? (y/n) : ", d->character);
OLC_MODE(d) = MEDIT_CONFIRM_SAVESTRING;
} else
cleanup_olc(d, CLEANUP_ALL);
return;
case '1':
OLC_MODE(d) = MEDIT_SEX;
medit_disp_sex(d);
return;
case '2':
OLC_MODE(d) = MEDIT_ALIAS;
i--;
break;
case '3':
OLC_MODE(d) = MEDIT_S_DESC;
i--;
break;
case '4':
OLC_MODE(d) = MEDIT_L_DESC;
i--;
break;
case '5':
OLC_MODE(d) = MEDIT_D_DESC;
SEND_TO_Q("Enter mob description: (/s saves /h for help)\r\n\r\n", d);
d->backstr = NULL;
if (OLC_MOB(d)->player.description) {
SEND_TO_Q(OLC_MOB(d)->player.description, d);
d->backstr = str_dup(OLC_MOB(d)->player.description);
}
d->str = &OLC_MOB(d)->player.description;
d->max_str = MAX_MOB_DESC;
d->mail_to = 0;
OLC_VAL(d) = 1;
return;
case '6':
OLC_MODE(d) = MEDIT_LEVEL;
i++;
break;
case '7':
OLC_MODE(d) = MEDIT_ALIGNMENT;
i++;
break;
case '8':
OLC_MODE(d) = MEDIT_HITROLL;
i++;
break;
case '9':
OLC_MODE(d) = MEDIT_DAMROLL;
i++;
break;
case 'a':
case 'A':
OLC_MODE(d) = MEDIT_NDD;
i++;
break;
case 'b':
case 'B':
OLC_MODE(d) = MEDIT_SDD;
i++;
break;
case 'c':
case 'C':
OLC_MODE(d) = MEDIT_NUM_HP_DICE;
i++;
break;
case 'o':
case 'O':
OLC_MODE(d) = MEDIT_KI;
i++;
break;
case 'd':
case 'D':
OLC_MODE(d) = MEDIT_SIZE_HP_DICE;
i++;
break;
case 'e':
case 'E':
OLC_MODE(d) = MEDIT_ADD_HP;
i++;
break;
case 'f':
case 'F':
OLC_MODE(d) = MEDIT_AC;
i++;
break;
case 'g':
case 'G':
OLC_MODE(d) = MEDIT_EXP;
i++;
break;
case 'h':
case 'H':
OLC_MODE(d) = MEDIT_GOLD;
i++;
break;
case 'i':
case 'I':
OLC_MODE(d) = MEDIT_POS;
medit_disp_positions(d);
return;
case 'j':
case 'J':
OLC_MODE(d) = MEDIT_DEFAULT_POS;
medit_disp_positions(d);
return;
case 'k':
case 'K':
OLC_MODE(d) = MEDIT_ATTACK;
medit_disp_attack_types(d);
return;
case 'l':
case 'L':
OLC_MODE(d) = MEDIT_NPC_FLAGS;
medit_disp_mob_flags(d);
return;
case 'm':
case 'M':
OLC_MODE(d) = MEDIT_AFF_FLAGS;
medit_disp_aff_flags(d);
return;
case 'n':
case 'N':
OLC_MODE(d) = MEDIT_NUM_ATTACKS;
i++;
break;
#if defined(OASIS_MPROG)
case 'p':
case 'P':
OLC_MODE(d) = MEDIT_MPROG;
medit_disp_mprog(d);
return;
#endif
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) {
send_to_char(i == 1 ? "\r\nEnter new value : " :
i == -1 ? "\r\nEnter new text :\r\n] " :
"\r\nOops...:\r\n", d->character);
return;
}
break;
/*-------------------------------------------------------------------*/
case OLC_SCRIPT_EDIT:
if (dg_script_edit_parse(d, arg)) return;
break;
/*-------------------------------------------------------------------*/
case MEDIT_ALIAS:
if (GET_ALIAS(OLC_MOB(d)))
free(GET_ALIAS(OLC_MOB(d)));
GET_ALIAS(OLC_MOB(d)) = str_dup((arg && *arg) ? arg : "undefined");
break;
/*-------------------------------------------------------------------*/
case MEDIT_S_DESC:
if (GET_SDESC(OLC_MOB(d)))
free(GET_SDESC(OLC_MOB(d)));
GET_SDESC(OLC_MOB(d)) = str_dup((arg && *arg) ? arg : "undefined");
break;
/*-------------------------------------------------------------------*/
case MEDIT_L_DESC:
if (GET_LDESC(OLC_MOB(d)))
free(GET_LDESC(OLC_MOB(d)));
if (arg && *arg) {
strcpy(buf, arg);
strcat(buf, "\r\n");
GET_LDESC(OLC_MOB(d)) = str_dup(buf);
} else
GET_LDESC(OLC_MOB(d)) = str_dup("undefined");
break;
/*-------------------------------------------------------------------*/
case MEDIT_D_DESC:
/*
* We should never get here.
*/
cleanup_olc(d, CLEANUP_ALL);
mudlog("SYSERR: OLC: medit_parse(): Reached D_DESC case!",
BRF, LVL_IMMORT, TRUE);
send_to_char("Oops...\r\n", d->character);
break;
/*-------------------------------------------------------------------*/
#if defined(OASIS_MPROG)
case MEDIT_MPROG_COMLIST:
/*
* We should never get here, but if we do, bail out.
*/
cleanup_olc(d, CLEANUP_ALL);
mudlog("SYSERR: OLC: medit_parse(): Reached MPROG_COMLIST case!",
BRF, LVL_IMMORT, TRUE);
break;
#endif
/*-------------------------------------------------------------------*/
case MEDIT_NPC_FLAGS:
if ((i = atoi(arg)) == 0)
break;
else if (!((i < 0) || (i > NUM_MOB_FLAGS)))
TOGGLE_BIT(MOB_FLAGS(OLC_MOB(d)), 1 << (i - 1));
medit_disp_mob_flags(d);
return;
/*-------------------------------------------------------------------*/
case MEDIT_AFF_FLAGS:
if ((i = atoi(arg)) == 0)
break;
else if (!((i < 0) || (i > NUM_AFF_FLAGS)))
TOGGLE_BIT(AFF_FLAGS(OLC_MOB(d)), 1 << (i - 1));
medit_disp_aff_flags(d);
return;
/*-------------------------------------------------------------------*/
case MEDIT_NUM_ATTACKS:
GET_NUM_ATTACKS(OLC_MOB(d)) = MAX(0, MIN(10, atoi(arg)));
break;
/*-------------------------------------------------------------------*/
#if defined(OASIS_MPROG)
case MEDIT_MPROG:
if ((i = atoi(arg)) == 0)
medit_disp_menu(d);
else if (i == OLC_MTOTAL(d)) {
struct mob_prog_data *temp;
CREATE(temp, struct mob_prog_data, 1);
temp->next = OLC_MPROGL(d);
temp->type = -1;
temp->arglist = NULL;
temp->comlist = NULL;
OLC_MPROG(d) = temp;
OLC_MPROGL(d) = temp;
OLC_MODE(d) = MEDIT_CHANGE_MPROG;
medit_change_mprog (d);
} else if (i < OLC_MTOTAL(d)) {
struct mob_prog_data *temp;
int x = 1;
for (temp = OLC_MPROGL(d); temp && x < i; temp = temp->next)
x++;
OLC_MPROG(d) = temp;
OLC_MODE(d) = MEDIT_CHANGE_MPROG;
medit_change_mprog (d);
} else if (i == OLC_MTOTAL(d) + 1) {
send_to_char("Which mob prog do you want to purge? ", d->character);
OLC_MODE(d) = MEDIT_PURGE_MPROG;
} else
medit_disp_menu(d);
return;
case MEDIT_PURGE_MPROG:
if ((i = atoi(arg)) > 0 && i < OLC_MTOTAL(d)) {
struct mob_prog_data *temp;
int x = 1;
for (temp = OLC_MPROGL(d); temp && x < i; temp = temp->next)
x++;
OLC_MPROG(d) = temp;
REMOVE_FROM_LIST(OLC_MPROG(d), OLC_MPROGL(d), next);
free(OLC_MPROG(d)->arglist);
free(OLC_MPROG(d)->comlist);
free(OLC_MPROG(d));
OLC_MPROG(d) = NULL;
OLC_VAL(d) = 1;
}
medit_disp_mprog(d);
return;
case MEDIT_CHANGE_MPROG: {
if ((i = atoi(arg)) == 1)
medit_disp_mprog_types(d);
else if (i == 2) {
send_to_char ("Enter new arg list: ", d->character);
OLC_MODE(d) = MEDIT_MPROG_ARGS;
} else if (i == 3) {
send_to_char("Enter new mob prog commands:\r\n", d->character);
/*
* Pass control to modify.c for typing.
*/
OLC_MODE(d) = MEDIT_MPROG_COMLIST;
d->backstr = NULL;
if (OLC_MPROG(d)->comlist) {
SEND_TO_Q(OLC_MPROG(d)->comlist, d);
d->backstr = str_dup(OLC_MPROG(d)->comlist);
}
d->str = &OLC_MPROG(d)->comlist;
d->max_str = MAX_STRING_LENGTH;
d->mail_to = 0;
OLC_VAL(d) = 1;
} else
medit_disp_mprog(d);
return;
#endif
/*-------------------------------------------------------------------*/
/*
* Numerical responses.
*/
#if defined(OASIS_MPROG)
/*
David Klasinc suggests for MEDIT_MPROG_TYPE:
switch (atoi(arg)) {
case 0: OLC_MPROG(d)->type = 0; break;
case 1: OLC_MPROG(d)->type = 1; break;
case 2: OLC_MPROG(d)->type = 2; break;
case 3: OLC_MPROG(d)->type = 4; break;
case 4: OLC_MPROG(d)->type = 8; break;
case 5: OLC_MPROG(d)->type = 16; break;
case 6: OLC_MPROG(d)->type = 32; break;
case 7: OLC_MPROG(d)->type = 64; break;
case 8: OLC_MPROG(d)->type = 128; break;
case 9: OLC_MPROG(d)->type = 256; break;
case 10: OLC_MPROG(d)->type = 512; break;
case 11: OLC_MPROG(d)->type = 1024; break;
default: OLC_MPROG(d)->type = -1; break;
}
*/
case MEDIT_MPROG_TYPE:
OLC_MPROG(d)->type = (1 << MAX(0, MIN(atoi(arg), NUM_PROGS - 1)));
OLC_VAL(d) = 1;
medit_change_mprog(d);
return;
case MEDIT_MPROG_ARGS:
OLC_MPROG(d)->arglist = str_dup(arg);
OLC_VAL(d) = 1;
medit_change_mprog(d);
return;
#endif
case MEDIT_SEX:
GET_SEX(OLC_MOB(d)) = MAX(0, MIN(NUM_GENDERS - 1, atoi(arg)));
break;
case MEDIT_HITROLL:
GET_HITROLL(OLC_MOB(d)) = MAX(0, MIN(50, atoi(arg)));
break;
case MEDIT_DAMROLL:
GET_DAMROLL(OLC_MOB(d)) = MAX(0, MIN(10000, atoi(arg)));
break;
case MEDIT_NDD:
GET_NDD(OLC_MOB(d)) = MAX(0, MIN(30, atoi(arg)));
break;
case MEDIT_SDD:
GET_SDD(OLC_MOB(d)) = MAX(0, MIN(127, atoi(arg)));
break;
case MEDIT_NUM_HP_DICE:
GET_HIT(OLC_MOB(d)) = MAX(0, MIN(30, atoi(arg)));
break;
case MEDIT_SIZE_HP_DICE:
GET_MANA(OLC_MOB(d)) = MAX(0, MIN(1000, atoi(arg)));
break;
case MEDIT_ADD_HP:
GET_MOVE(OLC_MOB(d)) = MAX(0, MIN(100000000, atoi(arg)));
break;
case MEDIT_AC:
GET_AC(OLC_MOB(d)) = MAX(-200, MIN(200, atoi(arg)));
break;
case MEDIT_EXP:
GET_EXP(OLC_MOB(d)) = MAX(0, atoi(arg));
break;
case MEDIT_GOLD:
GET_GOLD(OLC_MOB(d)) = MAX(0, atoi(arg));
break;
case MEDIT_POS:
GET_POS(OLC_MOB(d)) = MAX(0, MIN(NUM_POSITIONS - 1, atoi(arg)));
break;
case MEDIT_DEFAULT_POS:
GET_DEFAULT_POS(OLC_MOB(d)) = MAX(0, MIN(NUM_POSITIONS - 1, atoi(arg)));
break;
case MEDIT_ATTACK:
GET_ATTACK(OLC_MOB(d)) = MAX(0, MIN(NUM_ATTACK_TYPES - 1, atoi(arg)));
break;
case MEDIT_LEVEL:
GET_LEVEL(OLC_MOB(d)) = MAX(1, MIN(10000000, atoi(arg)));
break;
case MEDIT_KI:
GET_MAX_MANA(OLC_MOB(d)) = MAX(1, MIN(10000000, atoi(arg)));
break;
case MEDIT_ALIGNMENT:
GET_ALIGNMENT(OLC_MOB(d)) = MAX(-1000, MIN(1000, atoi(arg)));
break;
/*-------------------------------------------------------------------*/
default:
/*
* We should never get here.
*/
cleanup_olc(d, CLEANUP_ALL);
mudlog("SYSERR: OLC: medit_parse(): Reached default case!", BRF, LVL_IMMORT, TRUE);
send_to_char("Oops...\r\n", d->character);
break;
}
/*-------------------------------------------------------------------*/
/*
* END OF CASE
* If we get here, we have probably changed something, and now want to
* return to main menu. Use OLC_VAL as a 'has changed' flag
*/
OLC_VAL(d) = 1;
medit_disp_menu(d);
}
/*
* End of medit_parse(), thank god.
*/