#include #include #include #include "structs.h" #include "interpreter.h" #include "comm.h" #include "spells.h" #include "utils.h" #include "db.h" #include "boards.h" #include "olc.h" #include "screen.h" #include "shop.h" /* external variables */ extern CHAR_DATA *mob_proto; extern int top_of_mobt; extern struct index_data *mob_index; extern struct zone_data *zone_table; extern int top_of_zone_table; extern CHAR_DATA *character_list; extern char *position_types[]; extern char *genders[]; extern char *action_bits[]; extern char *affected_bits[]; extern char *immunity_bits[]; extern char *disease_names[]; extern struct title_type titles[NUM_CLASSES][LVL_IMPL + 1]; extern int mini_mud; extern struct hp_type mob_default_hitpoints[]; extern int sorted_race[]; extern const char *special_attacks[]; extern struct shop_data *shop_index; extern int top_shop; extern void init_text (DESCRIPTOR * d); extern struct attack_hit_type attack_hit_text[]; extern struct spell_info_type spell_info[]; extern char *spells[]; extern int uvfprintf (FILE * stream, const char *format,...); static void medit_disp_pos_menu (DESCRIPTOR * d); static void medit_resist_menu (DESCRIPTOR * d); void medit_race_menu (DESCRIPTOR * d); static void medit_disp_action_menu (DESCRIPTOR * d); static void medit_disp_extended_menu (DESCRIPTOR * d); static void medit_disp_affect_menu (DESCRIPTOR * d); static void medit_list_mobspells (DESCRIPTOR * d); void write_zone_mobs (int zone); int get_class_thaco (int class, int level); #define DMOB d->edit_mob void calc_mob_ac (CHAR_DATA * mob) { mob->points.armor = GET_LEVEL (mob) * 8; if (mob->mob_specials.medit_data[2]) { mob->points.armor -= (mob->mob_specials.medit_data[2] - 5); } } void calc_mob_hitroll (CHAR_DATA * mob) { mob->points.hitroll = get_class_thaco (CLASS_CLERIC, GET_LEVEL (mob)); if (mob->mob_specials.medit_data[3]) { mob->points.hitroll += mob->mob_specials.medit_data[3]; } } void calc_mob_exp (CHAR_DATA * mob) { int i; int factor = 0; int level = MIN (59, MAX (1, GET_LEVEL (mob))); int def = (titles[CLASS_WARRIOR][level + 1].exp - titles[CLASS_WARRIOR][level].exp) / (180 * level / 50 + 5 + (level + 4) * (level + 4) / 25) * 2; for (i = 0; i < 5; i++) { if (!mob->mob_specials.medit_data[i]) { factor += 5; } else { factor += mob->mob_specials.medit_data[i]; } } mob->points.exp = (factor * def / 25); } void calc_mob_hp (CHAR_DATA * mob) { mob->points.hit = mob_default_hitpoints[GET_LEVEL (mob)].numdice; mob->points.mana = mob_default_hitpoints[GET_LEVEL (mob)].sizedice; mob->points.move = mob_default_hitpoints[GET_LEVEL (mob)].diceadd; if (mob->mob_specials.medit_data[0]) { mob->points.mana += (mob->mob_specials.medit_data[0] - 5); } } void calc_mob_dam (CHAR_DATA * mob) { mob->mob_specials.damnodice = 1; mob->mob_specials.damsizedice = 5 + GET_LEVEL (mob) / 10; mob->mob_specials.damadd = GET_LEVEL (mob) * 3 / 2; if (mob->mob_specials.medit_data[1]) { if (GET_LEVEL (mob) < 10) { mob->mob_specials.damadd += ((mob->mob_specials.medit_data[1] - 5) / 2); } else if (GET_LEVEL (mob) < 20) { mob->mob_specials.damadd += (mob->mob_specials.medit_data[1] - 5); } else if (GET_LEVEL (mob) < 30) { mob->mob_specials.damadd += (mob->mob_specials.medit_data[1] - 5) + ((mob->mob_specials.medit_data[1] - 5) / 2); } else if (GET_LEVEL (mob) < 40) { mob->mob_specials.damadd += 2 * (mob->mob_specials.medit_data[1] - 5); } else { mob->mob_specials.damadd += 2 * (mob->mob_specials.medit_data[1] - 5) + ((mob->mob_specials.medit_data[1] - 5) / 2); } } } void calc_mob_treasure (CHAR_DATA * mob) { mob->points.gold = GET_LEVEL (mob) / 2; if (mob->mob_specials.medit_data[4]) { mob->points.gold += mob->mob_specials.medit_data[4] - 5; } mob->points.gold = MAX (0, MIN (25, mob->points.gold)); } /************************************************************************** Menu functions **************************************************************************/ static void medit_attack_menu (DESCRIPTOR * d) { int i; for (i = 0; i < 8; i++) { send_to_char (DCH, "%s%2d%s) %20.20s ", HLMAG (DCH), i, CCNRM (DCH), spells[i + TYPE_MOB_HIT]); if (i % 2 == 1) { send_to_char (DCH, "\r\n"); } } send_to_char (DCH, "\r\n");; send_to_char (DCH, "Enter attack type (this is a toggle):\r\n"); } static void medit_special_attack_menu (DESCRIPTOR * d) { int i; for (i = 0; i < NUM_SPEC_ATTACKS; i++) { send_to_char (DCH, "%s%2d%s) %20.20s ", HLMAG (DCH), i, CCNRM (DCH), special_attacks[i]); if (i % 2 == 1) { send_to_char (DCH, "\r\n"); } } send_to_char (DCH, "\r\n"); send_to_char (DCH, "Enter special attack:"); } static void medit_disp_combat_menu (DESCRIPTOR * d) { send_to_char (DCH, ""); send_to_char (DCH, "Combat statistics for %s (%d)\r\n", DMOB->player.short_descr, d->edit_number); send_to_char (DCH, "%s1%s) Hit points : %s%dd%d+%d%s\r\n", HLMAG (DCH), CCNRM (DCH), HLCYN (DCH), DMOB->points.hit, DMOB->points.mana, DMOB->points.move, CCNRM (DCH)); send_to_char (DCH, "%s2%s) AC : %s%d%s\r\n", HLMAG (DCH), CCNRM (DCH), HLCYN (DCH), DMOB->points.armor, CCNRM (DCH)); if (DMOB->mob_specials.attack_type == 0 || DMOB->mob_specials.attack_type == TYPE_HIT) { strcpy (buf2, "punch"); } else { sprintbit (DMOB->mob_specials.attack_type, spells + TYPE_MOB_HIT, buf2); } send_to_char (DCH, "%s3%s) AttackType : %s%s%s\r\n", HLMAG (DCH), CCNRM (DCH), HLCYN (DCH), buf2, CCNRM (DCH)); if (DMOB->mob_specials.special_attack_type == 0 || DMOB->mob_specials.special_attack_type == TYPE_NPC_SPEC_NONE) { strcpy (buf2, "none"); } else { strcpy (buf2, special_attacks[DMOB->mob_specials.special_attack_type]); } send_to_char (DCH, "%s4%s) Special Attack: %s%s%s\r\n", HLMAG (DCH), CCNRM (DCH), HLCYN (DCH), buf2, CCNRM (DCH)); send_to_char (DCH, "%s5%s) # Attacks/rd : %s%d%s\r\n", HLMAG (DCH), CCNRM (DCH), HLCYN (DCH), DMOB->mob_specials.num_attacks, CCNRM (DCH)); send_to_char (DCH, "%s6%s) Hitroll : %s%d%s\r\n", HLMAG (DCH), CCNRM (DCH), HLCYN (DCH), DMOB->points.hitroll, CCNRM (DCH)); send_to_char (DCH, "%s7%s) Damage : %s%dd%d+%d%s\r\n", HLMAG (DCH), CCNRM (DCH), HLCYN (DCH), DMOB->mob_specials.damnodice, DMOB->mob_specials.damsizedice, DMOB->mob_specials.damadd, CCNRM (DCH)); send_to_char (DCH, "%s8%s) Treasure : %s%d%s\r\n", HLMAG (DCH), CCNRM (DCH), HLCYN (DCH), DMOB->points.gold, CCNRM (DCH)); if (ADVANCED_BUILDER (DCH)) { send_to_char (DCH, "%s9%s) Experience : %s%ld%s\r\n", HLMAG (DCH), CCNRM (DCH), HLCYN (DCH), DMOB->points.exp, CCNRM (DCH)); } send_to_char (DCH, "%sq%s) Back to main menu\r\n", HLMAG (DCH), CCNRM (DCH)); send_to_char (DCH, "Enter your choice:\r\n"); } char medit_pos_mapping[] = { 4, /* sleeping */ 5, /* resting */ 6, /* sitting */ 8 /* standing */ }; char medit_pos_valid[] = {false, false, false, false, true, true, true, false, true, false}; static void medit_disp_pos_menu (DESCRIPTOR * d) { int i, j = 1; for (i = 0; i < NUM_MOB_POSITIONS; i++) { if (medit_pos_valid[i]) { sprintf (buf, "%s%2d%s) %20.20s ", HLMAG (DCH), j - 1, CCNRM (DCH), position_types[i]); j++; send_to_char (DCH, buf); if (j % 2 == 1) { send_to_char (DCH, "\r\n"); } } } send_to_char (DCH, "\r\n"); send_to_char (DCH, "Select position:"); } static void medit_resist_menu (DESCRIPTOR * d) { int i; send_to_char (DCH, ""); send_to_char (DCH, "Resistances for %s (%d)\r\n", DMOB->player.short_descr, d->edit_number); for (i = 0; i < 30; i++) { send_to_char (DCH, "%s%2d%s) %20.20s ", HLMAG (DCH), i + 1, CCNRM (DCH), immunity_bits[i]); if (i % 2 == 1) { send_to_char (DCH, "\r\n"); } } send_to_char (DCH, "\r\n");; sprintbit (IMMUNITIES (DMOB), immunity_bits, buf2); send_to_char (DCH, "Resistances/Immunities: %s%s%s\r\n", HLCYN (DCH), buf2, CCNRM (DCH)); send_to_char (DCH, "Enter resistances or 0 to quit:\r\n"); } static void medit_disease_menu (DESCRIPTOR * d) { int i; send_to_char (DCH, ""); send_to_char (DCH, "Diseases for %s (%d)\r\n", DMOB->player.short_descr, d->edit_number); for (i = 0; i < MAX_DISEASES; i++) { send_to_char (DCH, "%s%2d%s) %20.20s ", HLMAG (DCH), i + 1, CCNRM (DCH), disease_names[i]); if (i % 2 == 1) { send_to_char (DCH, "\r\n"); } } send_to_char (DCH, "\r\n");; sprintbit (DISEASES (DMOB), disease_names, buf2); send_to_char (DCH, "Diseases: %s%s%s\r\n", HLCYN (DCH), buf2, CCNRM (DCH)); send_to_char (DCH, "Enter diseases or 0 to quit:\r\n"); } /* display race menu */ void medit_race_menu (DESCRIPTOR * d) { int i; send_to_char (DCH, ""); if (DMOB) { send_to_char (DCH, "Race for %s (%d)\r\n", DMOB->player.short_descr, d->edit_number); } for (i = 0; i < NUM_MOB_RACES; i++) { send_to_char (DCH, "%s%2d%s) %20.20s ", HLMAG (DCH), i, CCNRM (DCH), mob_races[sorted_race[i]].race_name); if (i % 2 == 1) { send_to_char (DCH, "\r\n"); } } send_to_char (DCH, "\r\n"); } /* display action menu */ char medit_action_mapping[] = { 0, 1, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 23, 26, 27, 28 }; char medit_action_valid[] = {false, true, true, false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, false, false, false, false, true, false, false, true, true, true}; static void medit_disp_action_menu (DESCRIPTOR * d) { int i, j = 1; send_to_char (DCH, ""); send_to_char (DCH, "Actions for %s (%d)\r\n", DMOB->player.short_descr, d->edit_number); for (i = 0; i < NUM_MOB_ACTIONS; i++) { if (medit_action_valid[i]) { sprintf (buf, "%s%2d%s) %20.20s ", HLMAG (DCH), j, CCNRM (DCH), action_bits[i]); j++; send_to_char (DCH, buf); if (j % 2 == 1) { send_to_char (DCH, "\r\n"); } } } send_to_char (DCH, "\r\n");; sprintbit (DMOB->mob_specials.mob, action_bits, buf1); send_to_char (DCH, "Action Flags: %s%s%s\r\n", HLCYN (DCH), buf1, CCNRM (DCH)); send_to_char (DCH, "Enter action flags, or 0 to quit:\r\n"); d->edit_mode = MEDIT_ACTIONS; } /* display EXTENDED information menu */ static void medit_disp_extended_menu (DESCRIPTOR * d) { send_to_char (DCH, ""); send_to_char (DCH, "Extended information for %s (%d)\r\n", DMOB->player.short_descr, d->edit_number); sprintbit (IMMUNITIES (DMOB), immunity_bits, buf2); send_to_char (DCH, "%s1%s) Res/Imm : %s%s%s\r\n", HLMAG (DCH), CCNRM (DCH), HLCYN (DCH), buf2, CCNRM (DCH)); send_to_char (DCH, "%s2%s) Magic Res : %s%d%s\r\n", HLMAG (DCH), CCNRM (DCH), HLCYN (DCH), GET_MAGIC_RES (DMOB), CCNRM (DCH)); sprintbit (DISEASES (DMOB), disease_names, buf2); send_to_char (DCH, "%s3%s) Diseases : %s%s%s\r\n", HLMAG (DCH), CCNRM (DCH), HLCYN (DCH), buf2, CCNRM (DCH)); send_to_char (DCH, "%sq%s) Back to main menu\r\n", HLMAG (DCH), CCNRM (DCH)); send_to_char (DCH, "Enter your choice:\r\n"); } /* display affect menu */ static void medit_disp_affect_menu (DESCRIPTOR * d) { int i, j = 0; send_to_char (DCH, ""); send_to_char (DCH, "Mobspells for %s (%d)\r\n", DMOB->player.short_descr, d->edit_number); medit_list_mobspells (d); send_to_char (DCH, "\r\n"); for (i = 1; i < TYPE_SUFFERING; i++) { /* For personal items: only show spells which are - TAR_CHAR_ROOM or TAR_SELF_ONLY, and - not MAG_DAMAGE and not MAG_POINTS (mag_points are all the healing spells) and not MAG_MANUAL and not MAG_UNAFFECTS. Whew! Violent things are NOT ruled out, to make life interesting. this should rule out all stupidity */ if (is_personal_spell (i)) { send_to_char (DCH, "%s%3d%s) %20.20s ", HLMAG (DCH), i, CCNRM (DCH), spells[i]); j++; } if (j == 3) { j = 0; send_to_char (DCH, "\r\n"); } } send_to_char (DCH, "\r\n"); send_to_char (DCH, "Enter a spell number to add or delete from the list (Q to quit):\r\n"); d->edit_mode = MEDIT_AFFECTS; } /* lists the mobspells the mob has (in d->mob_spells) */ static void medit_list_mobspells (DESCRIPTOR * d) { struct mob_spell *mob_spell; if (!d->mob_spells) { send_to_char (DCH, "This mob has no mobspells yet.\r\n"); } else { send_to_char (DCH, "This mob has the following mobspells:\r\n"); buf[0] = '\0'; for (mob_spell = d->mob_spells; mob_spell; mob_spell = mob_spell->next) { sprintf (buf, "%s %s\n", buf, spells[mob_spell->spell_num]); } send_to_char (DCH, buf); } } /*************************************************************************** main loop (of sorts).. basically interpreter throws all input to here ***************************************************************************/ /* display main menu */ void medit_disp_menu (DESCRIPTOR * d) { send_to_char (DCH, ""); send_to_char (DCH, "%s1%s) Namelist : %s%s%s\r\n", HLMAG (DCH), CCNRM (DCH), HLCYN (DCH), DMOB->player.name, CCNRM (DCH)); send_to_char (DCH, "%s2%s) Short desc : %s%s%s\r\n", HLMAG (DCH), CCNRM (DCH), HLCYN (DCH), DMOB->player.short_descr, CCNRM (DCH)); send_to_char (DCH, "%s3%s) Long desc :\r\n%s%s%s\r\n", HLMAG (DCH), CCNRM (DCH), HLCYN (DCH), DMOB->player.long_descr, CCNRM (DCH)); send_to_char (DCH, "%s4%s) Description :\r\n%s%s%s\r\n", HLMAG (DCH), CCNRM (DCH), HLCYN (DCH), DMOB->player.description, CCNRM (DCH)); sprintbit (DMOB->mob_specials.mob, action_bits, buf2); send_to_char (DCH, "%s5%s) Action flags : %s%s%s\r\n", HLMAG (DCH), CCNRM (DCH), HLCYN (DCH), buf2, CCNRM (DCH)); sprintbit (DMOB->char_specials.saved.affected_by, affected_bits, buf2); send_to_char (DCH, "%s6%s) Spells\r\n", HLMAG (DCH), CCNRM (DCH)); send_to_char (DCH, "%s7%s) Alignment : %s%d%s\r\n", HLMAG (DCH), CCNRM (DCH), HLCYN (DCH), DMOB->char_specials.saved.alignment, CCNRM (DCH)); send_to_char (DCH, "%s8%s) Level : %s%d%s\r\n", HLMAG (DCH), CCNRM (DCH), HLCYN (DCH), DMOB->player.level, CCNRM (DCH)); send_to_char (DCH, "%s9%s) Default pos : %s%s%s\r\n", HLMAG (DCH), CCNRM (DCH), HLCYN (DCH), position_types[(int) DMOB->mob_specials.default_pos], CCNRM (DCH)); send_to_char (DCH, "%sa%s) Sex : %s%s%s\r\n", HLMAG (DCH), CCNRM (DCH), HLCYN (DCH), genders[(int) DMOB->player.sex], CCNRM (DCH)); send_to_char (DCH, "%sb%s) Race : %s%s%s\r\n", HLMAG (DCH), CCNRM (DCH), HLCYN (DCH), mob_races[(int) DMOB->mob_specials.mob_race].race_name, CCNRM (DCH)); send_to_char (DCH, "%sc%s) Combat statistics\r\n", HLMAG (DCH), CCNRM (DCH)); send_to_char (DCH, "%sd%s) Extended information\r\n", HLMAG (DCH), CCNRM (DCH)); send_to_char (DCH, "%sq%s) Quit\r\n", HLMAG (DCH), CCNRM (DCH)); send_to_char (DCH, "Enter your choice:\r\n"); d->edit_mode = MEDIT_MAIN_MENU; return; } void medit_parse (DESCRIPTOR * d, char *arg) { int i, j; int mob_number; struct mob_spell *mob_spell, *new_mob_spell, *next_mob_spell; switch (d->edit_mode) { case MEDIT_CONFIRM_EDIT: /* if player hits 'Y' then edit obj */ switch (*arg) { case 'y': case 'Y': medit_disp_menu (d); break; case 'n': case 'N': sprintf (buf, "%s has exited medit.", GET_NAME (DCH)); mudlog (buf, CMP, MAX (LVL_GOD, GET_INVIS_LEV (DCH)), true); STATE (d) = CON_PLAYING; /* free up the editing object */ if (DMOB) { /* free char here is OK */ free_char (DMOB); /* Free descriptor mob spells */ for (mob_spell = d->mob_spells; mob_spell; mob_spell = next_mob_spell) { next_mob_spell = mob_spell->next; free (mob_spell); } d->mob_spells = null; } DMOB = null; d->edit_number = 0; REMOVE_BIT (PLR_FLAGS (DCH), PLR_EDITING); break; default: send_to_char (DCH, "That's not a valid choice!\r\n"); send_to_char (DCH, "Do you wish to edit it?\r\n"); break; } break; /* end of MEDIT_CONFIRM_EDIT */ case MEDIT_CONFIRM_SAVESTRING: switch (*arg) { case 'y': case 'Y': { /* stupid. Update aff/real abils */ DMOB->real_abils = DMOB->aff_abils; /* write to internal tables */ mob_number = real_mobile_regardless (d->edit_number); if (mob_number >= 0) { CHAR_DATA *i; extern CHAR_DATA *character_list; int deleted = MOB_DELETED (mob_number); for (i = character_list; i; i = i->next) { if (!IS_NPC (i)) { continue; } if (i->nr == mob_number) { i->player.name = DMOB->player.name; i->player.title = DMOB->player.title; i->player.short_descr = DMOB->player.short_descr; i->player.long_descr = DMOB->player.long_descr; i->player.description = DMOB->player.description; } } /* free all stringies in the prototype table */ if (mob_proto[mob_number].player.name) { free (mob_proto[mob_number].player.name); } if (mob_proto[mob_number].player.title) { free (mob_proto[mob_number].player.title); } if (mob_proto[mob_number].player.short_descr) { free (mob_proto[mob_number].player.short_descr); } if (mob_proto[mob_number].player.long_descr) { free (mob_proto[mob_number].player.long_descr); } if (mob_proto[mob_number].player.description) { free (mob_proto[mob_number].player.description); } for (mob_spell = mob_proto[mob_number].mob_specials.mob_spells; mob_spell; mob_spell = next_mob_spell) { next_mob_spell = mob_spell->next; free (mob_spell); } /* copy over the mob prototype */ mob_proto[mob_number] = *DMOB; mob_proto[mob_number].nr = mob_number; DMOB->nr = mob_number; mob_proto[mob_number].mob_specials.mob_spells = null; /* Create a new mobspell list in the prototype */ for (mob_spell = d->mob_spells; mob_spell; mob_spell = mob_spell->next) { new_mob_spell = (struct mob_spell *) malloc (sizeof (struct mob_spell)); new_mob_spell->spell_num = mob_spell->spell_num; new_mob_spell->next = mob_proto[mob_number].mob_specials.mob_spells; mob_proto[mob_number].mob_specials.mob_spells = new_mob_spell; } if (deleted) { mob_index[mob_number].deleted = false; mob_index[mob_number].virtual = d->edit_number; mob_index[mob_number].number = 0; /* It is also necessary to mark DMOB's number so that when it gets freed it doesn't take the mob_proto table out with it */ DMOB->nr = mob_number; /* and to prototype as well */ mob_proto[mob_number].nr = mob_number; } } else { /* * uhoh.. need to make a new place in the mob * prototype table */ int found = false; CHAR_DATA *new_mob_proto; struct index_data *new_mob_index; CHAR_DATA *temp_mob; /* + 2.. strange but true */ CREATE (new_mob_index, struct index_data, top_of_mobt + 2); CREATE (new_mob_proto, CHAR_DATA, top_of_mobt + 2); /* start counting through both tables */ for (i = 0; i < top_of_mobt + 1; i++) { /* if we haven't found it */ if (!found) { /* * check if current virtual is bigger than our * virtual */ if (mob_index[i].virtual > d->edit_number) { /* * eureka. insert now */ /*---------*/ new_mob_index[i].virtual = d->edit_number; new_mob_index[i].number = 0; new_mob_index[i].func = null; /*---------*/ new_mob_proto[i] = *(DMOB); new_mob_proto[i].in_room = NOWHERE; /* Create a new mobspell list in the prototype */ new_mob_proto[i].mob_specials.mob_spells = null; for (mob_spell = d->mob_spells; mob_spell; mob_spell = mob_spell->next) { new_mob_spell = (struct mob_spell *) malloc (sizeof (struct mob_spell)); new_mob_spell->spell_num = mob_spell->spell_num; new_mob_spell->next = new_mob_proto[i].mob_specials.mob_spells; new_mob_proto[i].mob_specials.mob_spells = new_mob_spell; } /* * it is now safe (and necessary!) to * assign real number to the edit_mob, * which has been -1 all this time */ DMOB->nr = i; /* * and assign to prototype as well */ new_mob_proto[i].nr = i; found = true; /* * insert the other proto at this point */ new_mob_index[i + 1] = mob_index[i]; new_mob_proto[i + 1] = mob_proto[i]; new_mob_proto[i + 1].nr = i + 1; } else { /* * just copy from old to new, no num * change */ new_mob_proto[i] = mob_proto[i]; new_mob_index[i] = mob_index[i]; } } else { /* * we HAVE already found it.. therefore copy * to mobect + 1 */ new_mob_index[i + 1] = mob_index[i]; new_mob_proto[i + 1] = mob_proto[i]; new_mob_proto[i + 1].nr = i + 1; } } /* * if we STILL haven't found it, means the mob was > * than all the other mobs.. so insert at end */ if (!found) { new_mob_index[top_of_mobt + 1].virtual = d->edit_number; new_mob_index[top_of_mobt + 1].number = 0; new_mob_index[top_of_mobt + 1].func = null; clear_char (new_mob_proto + top_of_mobt + 1); new_mob_proto[top_of_mobt + 1] = *(DMOB); new_mob_proto[top_of_mobt + 1].in_room = NOWHERE; new_mob_proto[top_of_mobt + 1].nr = top_of_mobt + 1; new_mob_proto[top_of_mobt + 1].mob_specials.mob_spells = null; /* Create a new mobspell list in the prototype */ for (mob_spell = d->mob_spells; mob_spell; mob_spell = mob_spell->next) { new_mob_spell = (struct mob_spell *) malloc (sizeof (struct mob_spell)); new_mob_spell->spell_num = mob_spell->spell_num; new_mob_spell->next = new_mob_proto[top_of_mobt + 1].mob_specials.mob_spells; new_mob_proto[top_of_mobt + 1].mob_specials.mob_spells = new_mob_spell; } /* it is now safe (and necessary!) to * assign real number to the edit_mob, * which has been -1 all this time */ DMOB->nr = top_of_mobt + 1; } top_of_mobt++; /* renumber all mobs in the world */ for (temp_mob = character_list; temp_mob; temp_mob = temp_mob->next) /* we have no way of accessing * vnums/rnums.. so we do a increment * if after insertion point */ { if (!IS_MOB (temp_mob)) { continue; } if (GET_MOB_RNUM (temp_mob) >= DMOB->nr) { GET_MOB_RNUM (temp_mob)++; } } /* Fix the creeping shops problem */ if (!mini_mud) { for (i = 0; i <= top_shop; i++) { if (shop_index[i].keeper >= DMOB->nr) { shop_index[i].keeper++; } } } /* free and replace old tables */ free (mob_proto); free (mob_index); mob_proto = new_mob_proto; mob_index = new_mob_index; /* renumber mobs in zone table */ for (i = 0; i <= top_of_zone_table; i++) for (j = 0; zone_table[i].cmd[j].command != 'S'; j++) switch (zone_table[i].cmd[j].command) { case 'M': case 'm': case 'r': zone_table[i].cmd[j].arg1 = (zone_table[i].cmd[j].arg1 >= DMOB->nr ? zone_table[i].cmd[j].arg1 + 1 : zone_table[i].cmd[j].arg1); break; } } } send_to_char (DCH, "Writing mobile to disk.."); write_zone_mobs (d->edit_zone); if (DMOB) { /* free char here is NOT okay. */ /* why not??? - should be fine by now (oct 15) */ free_char (DMOB); } DMOB = null; for (mob_spell = d->mob_spells; mob_spell; mob_spell = next_mob_spell) { next_mob_spell = mob_spell->next; free (mob_spell); } d->mob_spells = null; sprintf (buf, "%s has exited medit.", GET_NAME (DCH)); mudlog (buf, CMP, MAX (LVL_GOD, GET_INVIS_LEV (DCH)), true); STATE (d) = CON_PLAYING; REMOVE_BIT (PLR_FLAGS (DCH), PLR_EDITING); send_to_char (DCH, "Done.\r\n"); break; case 'n': case 'N': send_to_char (DCH, "Mobile not saved, aborting.\r\n"); sprintf (buf, "%s has exited medit.", GET_NAME (DCH)); mudlog (buf, CMP, MAX (LVL_GOD, GET_INVIS_LEV (DCH)), true); STATE (d) = CON_PLAYING; /* free up the editing mob */ if (DMOB) { /* free char here is definitely OK */ free_char (DMOB); } for (mob_spell = d->mob_spells; mob_spell; mob_spell = next_mob_spell) { next_mob_spell = mob_spell->next; free (mob_spell); } d->mob_spells = null; DMOB = null; d->edit_number = 0; REMOVE_BIT (PLR_FLAGS (DCH), PLR_EDITING); break; default: send_to_char (DCH, "Invalid choice!\r\n"); send_to_char (DCH, "Do you wish to save this mobile?\r\n"); break; } break; /* end of MEDIT_CONFIRM_SAVESTRING */ case MEDIT_COMBAT_MENU: switch (*arg) { case 'q': case 'Q': if (!ADVANCED_BUILDER (DCH)) { calc_mob_exp (DMOB); } medit_disp_menu (d); d->edit_mode = MEDIT_MAIN_MENU; break; case '6': if (ADVANCED_BUILDER (DCH)) { d->edit_mode = MEDIT_THAC0; DMOB->mob_specials.medit_data[3] = 0; calc_mob_hitroll (DMOB); send_to_char (DCH, "Enter mob hitroll (average: %d): ", DMOB->points.hitroll); } else { d->edit_mode = MEDIT_THAC0; send_to_char (DCH, "Enter the quality modifier on the mob's hitroll (1 to 9):\r\n"); } break; case '2': d->edit_mode = MEDIT_ARMOR; if (ADVANCED_BUILDER (DCH)) { DMOB->mob_specials.medit_data[2] = 0; calc_mob_ac (DMOB); send_to_char (DCH, "Enter mob AC (average: %d): ", DMOB->points.armor); } else { send_to_char (DCH, "Enter the quality modifier on armor (1 to 9):\r\n"); } break; case '1': if (ADVANCED_BUILDER (DCH)) { d->edit_mode = MEDIT_HIT_NUMDICE; DMOB->mob_specials.medit_data[0] = 0; calc_mob_hp (DMOB); send_to_char (DCH, "Enter number of hit dice (average: %d): ", DMOB->points.hit); } else { d->edit_mode = MEDIT_HIT_NUMDICE; send_to_char (DCH, "Enter the quality modifier on this mobile's hit points (1 to 9):\r\n"); } break; case '7': if (ADVANCED_BUILDER (DCH)) { d->edit_mode = MEDIT_DAM_NUMDICE; DMOB->mob_specials.medit_data[1] = 0; calc_mob_dam (DMOB); send_to_char (DCH, "Enter number of damage dice (average: %d): ", DMOB->mob_specials.damnodice); } else { d->edit_mode = MEDIT_DAM_NUMDICE; send_to_char (DCH, "Enter the quality modifier on the mob's damage (1 to 9):\r\n"); } break; case '9': if (ADVANCED_BUILDER (DCH)) { int level = MIN (59, MAX (1, GET_LEVEL (DMOB))); d->edit_mode = MEDIT_EXP; send_to_char (DCH, "Enter mob experience points (average: %ld): ", (titles[CLASS_WARRIOR][level + 1].exp - titles[CLASS_WARRIOR][level].exp) / (180 * level / 50 + 5 + (level + 4) * (level + 4) / 25) * 2); } else { medit_disp_combat_menu (d); } break; case '8': if (ADVANCED_BUILDER (DCH)) { d->edit_mode = MEDIT_GOLD; DMOB->mob_specials.medit_data[4] = 0; calc_mob_treasure (DMOB); send_to_char (DCH, "Enter mob treasure code (average: %d): ", DMOB->points.gold); } else { d->edit_mode = MEDIT_GOLD; send_to_char (DCH, "Enter the quality modifier on the treasure (1 to 9):\r\n"); } break; case '5': d->edit_mode = MEDIT_NUM_ATTACKS; send_to_char (DCH, "Enter number of mob attacks per round [1-7] (average: %d): ", (GET_LEVEL (DMOB) + 14) / 15); break; case '3': d->edit_mode = MEDIT_ATTACK_TYPE; medit_attack_menu (d); break; case '4': d->edit_mode = MEDIT_SPECIAL_ATTACK_TYPE; medit_special_attack_menu (d); break; default: medit_disp_combat_menu (d); break; } break; case MEDIT_MAIN_MENU: /* throw us out to whichever edit mode based on user input */ switch (*arg) { case 'q': case 'Q': send_to_char (DCH, "Do you wish to save this mobile?\r\n"); d->edit_mode = MEDIT_CONFIRM_SAVESTRING; break; case '1': send_to_char (DCH, "Enter namelist:"); d->edit_mode = MEDIT_NAMELIST; break; case '2': send_to_char (DCH, "Enter short desc:"); d->edit_mode = MEDIT_SHORTDESC; break; case '3': send_to_char (DCH, "Enter long desc:"); d->edit_mode = MEDIT_LONGDESC; break; case '4': send_to_char (DCH, "Enter description:\r\n"); d->edit_mode = MEDIT_DESC; d->str = (char **) malloc (sizeof (char *)); if (DMOB->player.description) { *(d->str) = strdup (DMOB->player.description); init_text (d); } else { *(d->str) = null; } d->max_str = MAX_MESSAGE_LENGTH; d->mail_to = 0; break; case '5': d->edit_mode = MEDIT_ACTIONS; medit_disp_action_menu (d); break; case '6': d->edit_mode = MEDIT_AFFECTS; medit_disp_affect_menu (d); break; case '7': d->edit_mode = MEDIT_ALIGN; send_to_char (DCH, "Enter mob alignment:"); break; case '8': d->edit_mode = MEDIT_LEVEL; send_to_char (DCH, "Enter mob level:"); break; case '9': medit_disp_pos_menu (d); d->edit_mode = MEDIT_DEF_POS; break; case 'a': case 'A': d->edit_mode = MEDIT_SEX; send_to_char (DCH, "Enter mob sex (n/m/f):"); break; case 'b': case 'B': medit_race_menu (d); send_to_char (DCH, "Select race:"); d->edit_mode = MEDIT_RACE; break; case 'c': case 'C': medit_disp_combat_menu (d); d->edit_mode = MEDIT_COMBAT_MENU; break; case 'd': case 'D': medit_disp_extended_menu (d); d->edit_mode = MEDIT_EXTENDED_PROMPT; break; default: medit_disp_menu (d); break; } break; case MEDIT_NAMELIST: if (!*arg) { send_to_char (DCH, "Invalid namelist!\r\nEnter namelist:"); return; } if (DMOB->player.name) { free (DMOB->player.name); } DMOB->player.name = strdup (arg); medit_disp_menu (d); break; case MEDIT_SHORTDESC: if (!*arg) { send_to_char (DCH, "Invalid short desc!\r\nEnter short desc:"); return; } if (DMOB->player.short_descr) { free (DMOB->player.short_descr); } DMOB->player.short_descr = strdup (arg); medit_disp_menu (d); break; case MEDIT_LONGDESC: if (!*arg) { send_to_char (DCH, "Invalid long desc!\r\nEnter long desc:"); return; } if (DMOB->player.long_descr) { free (DMOB->player.long_descr); } /* THIS IS STUPID. However, I have to add \r\n. Don't ask me why it's so brain damaged. (You don't need to do this for objects) */ sprintf (buf, "%s\r\n", arg); DMOB->player.long_descr = strdup (buf); medit_disp_menu (d); break; case MEDIT_DESC: /* we should never get here */ break; case MEDIT_ACTIONS: i = atoi (arg); if ((i < 0) || (i > 21)) { send_to_char (DCH, "That's not a valid choice!\r\n"); medit_disp_action_menu (d); } else { /* if 0, quit */ if (i == 0) { medit_disp_menu (d); break; } i = medit_action_mapping[i]; TOGGLE_BIT (DMOB->mob_specials.mob, 1 << i); medit_disp_action_menu (d); } break; case MEDIT_AFFECTS: if (UPPER (arg[0]) == 'Q') { medit_disp_menu (d); return; } i = atoi (arg); if (!is_personal_spell (i)) { send_to_char (DCH, "That's not a valid choice!\r\n"); medit_disp_affect_menu (d); } else { struct mob_spell *new_mob_spell, *mob_spell, *temp; /* check if we already have this number; if so, remove and free */ for (mob_spell = d->mob_spells; mob_spell; mob_spell = mob_spell->next) { if (mob_spell->spell_num == i) { REMOVE_FROM_LIST (mob_spell, d->mob_spells, next); free (mob_spell); medit_disp_affect_menu (d); return; } } /* nope, don't have this number. Add */ new_mob_spell = (struct mob_spell *) malloc (sizeof (struct mob_spell)); new_mob_spell->spell_num = i; new_mob_spell->next = d->mob_spells; d->mob_spells = new_mob_spell; medit_disp_affect_menu (d); return; } break; case MEDIT_ALIGN: i = atoi (arg); if ((i < -1000) || (i > 1000)) { send_to_char (DCH, "Align must be between -1000 and 1000!\r\n"); send_to_char (DCH, "Enter mob alignment:\r\n"); } else { DMOB->char_specials.saved.alignment = i; medit_disp_menu (d); } break; case MEDIT_LEVEL: i = atoi (arg); if (i < 0 || i > 60) { send_to_char ( DCH, "Invalid level! Must be between 0 and 60.\r\n"); send_to_char (DCH, "Enter mob level:"); return; } i = atoi (arg); DMOB->player.level = i; /* normalize mob based on level */ calc_mob_hitroll (DMOB); calc_mob_hp (DMOB); calc_mob_ac (DMOB); calc_mob_dam (DMOB); calc_mob_exp (DMOB); calc_mob_treasure (DMOB); medit_disp_menu (d); break; case MEDIT_THAC0: i = atoi (arg); if (ADVANCED_BUILDER (DCH)) { DMOB->points.hitroll = i; } else { if (i < 1 || i > 9) { send_to_char (DCH, "Invalid choice!\r\nEnter the quality modifier on this stat (1 to 9):\r\n"); return; } DMOB->mob_specials.medit_data[3] = (byte) i; calc_mob_hitroll (DMOB); } medit_disp_combat_menu (d); d->edit_mode = MEDIT_COMBAT_MENU; break; case MEDIT_ARMOR: i = atoi (arg); if (ADVANCED_BUILDER (DCH)) { DMOB->points.armor = i; } else { if (i < 1 || i > 9) { send_to_char (DCH, "Invalid choice!\r\nEnter the quality modifier on this stat (1 to 9):\r\n"); return; } DMOB->mob_specials.medit_data[2] = (byte) i; calc_mob_ac (DMOB); } medit_disp_combat_menu (d); d->edit_mode = MEDIT_COMBAT_MENU; break; case MEDIT_HIT_NUMDICE: i = atoi (arg); if (ADVANCED_BUILDER (DCH)) { DMOB->points.hit = i; send_to_char (DCH, "Enter size of hit dice (average: %d): ", DMOB->points.mana); d->edit_mode = MEDIT_HIT_SIZEDICE; } else { if (i < 1 || i > 9) { send_to_char (DCH, "Invalid choice!\r\nEnter the quality modifier on this stat (1 to 9):\r\n"); return; } DMOB->mob_specials.medit_data[0] = (byte) i; calc_mob_hp (DMOB); medit_disp_combat_menu (d); d->edit_mode = MEDIT_COMBAT_MENU; } break; case MEDIT_HIT_SIZEDICE: i = atoi (arg); DMOB->points.mana = i; send_to_char (DCH, "Enter hit point modifier (average: %d): ", DMOB->points.move); d->edit_mode = MEDIT_HIT_ADD; break; case MEDIT_HIT_ADD: i = atoi (arg); DMOB->points.move = i; medit_disp_combat_menu (d); d->edit_mode = MEDIT_COMBAT_MENU; break; case MEDIT_DAM_NUMDICE: i = atoi (arg); if (ADVANCED_BUILDER (DCH)) { DMOB->mob_specials.damnodice = i; send_to_char (DCH, "Enter size of damage dice (average: %d): ", DMOB->mob_specials.damsizedice); d->edit_mode = MEDIT_DAM_SIZEDICE; DMOB->mob_specials.medit_data[1] = 0; } else { if (i < 1 || i > 9) { send_to_char (DCH, "Invalid choice!\r\nEnter the quality modifier on this stat (1 to 9):\r\n"); return; } DMOB->mob_specials.medit_data[1] = (byte) i; calc_mob_dam (DMOB); medit_disp_combat_menu (d); d->edit_mode = MEDIT_COMBAT_MENU; } break; case MEDIT_DAM_SIZEDICE: i = atoi (arg); DMOB->mob_specials.damsizedice = i; send_to_char (DCH, "Enter damage modifier (average: %d): ", DMOB->mob_specials.damadd); d->edit_mode = MEDIT_DAM_ADD; break; case MEDIT_DAM_ADD: i = atoi (arg); DMOB->mob_specials.damadd = i; medit_disp_combat_menu (d); d->edit_mode = MEDIT_COMBAT_MENU; break; case MEDIT_GOLD: i = atoi (arg); if (ADVANCED_BUILDER (DCH)) { DMOB->points.gold = i; } else { if (i < 1 || i > 9) { send_to_char (DCH, "Invalid choice!\r\nEnter the quality modifier on this stat (1 to 9):\r\n"); return; } DMOB->mob_specials.medit_data[4] = (byte) i; calc_mob_treasure (DMOB); } medit_disp_combat_menu (d); d->edit_mode = MEDIT_COMBAT_MENU; break; case MEDIT_EXP: i = atoi (arg); DMOB->points.exp = i; medit_disp_combat_menu (d); d->edit_mode = MEDIT_COMBAT_MENU; break; case MEDIT_ATTACK_TYPE: i = atoi (arg); if (i < 0 || i > 7) { send_to_char (DCH, "Invalid choice!\r\nEnter damage type:"); return; } else { TOGGLE_BIT (DMOB->mob_specials.attack_type, (1 << i)); medit_disp_combat_menu (d); d->edit_mode = MEDIT_COMBAT_MENU; } break; case MEDIT_SPECIAL_ATTACK_TYPE: i = atoi (arg); if (i < 0 || i >= NUM_SPEC_ATTACKS) { send_to_char (DCH, "Invalid choice!\r\nEnter special attack:"); return; } else { DMOB->mob_specials.special_attack_type = i; medit_disp_combat_menu (d); d->edit_mode = MEDIT_COMBAT_MENU; } break; case MEDIT_NUM_ATTACKS: i = atoi (arg); if (i < 0 || i > 7) { send_to_char (DCH, "# of attacks must be at least 1 and less than 7!\r\n"); send_to_char (DCH, "Enter i of mob attacks per round:\r\n"); } else { DMOB->mob_specials.num_attacks = i; medit_disp_combat_menu (d); d->edit_mode = MEDIT_COMBAT_MENU; } break; case MEDIT_DEF_POS: i = atoi (arg); if (i < 0 || i >= NUM_MOB_POSITIONS) { send_to_char (DCH, "Invalid choice!\r\n"); medit_disp_pos_menu (d); } else { DMOB->mob_specials.default_pos = medit_pos_mapping[i]; medit_disp_menu (d); } break; case MEDIT_SEX: switch (*arg) { case 'n': case 'N': DMOB->player.sex = SEX_NEUTRAL; medit_disp_menu (d); break; case 'm': case 'M': DMOB->player.sex = SEX_MALE; medit_disp_menu (d); break; case 'f': case 'F': DMOB->player.sex = SEX_FEMALE; medit_disp_menu (d); break; default: send_to_char (DCH, "Invalid choice!\r\n"); send_to_char (DCH, "Enter mob sex (n/m/f):"); break; } break; case MEDIT_EXTENDED_PROMPT: i = atoi (arg); #ifdef undef if ((ADVANCED_BUILDER (DCH) && (i < 0 || i > 12)) || (!ADVANCED_BUILDER (DCH) && (i < 0 || i > 3))) #endif if ((i < 0 || i > 3)) { send_to_char (DCH, "Invalid choice!\r\n"); medit_disp_extended_menu (d); d->edit_mode = MEDIT_EXTENDED_PROMPT; return; } d->edit_number2 = i; switch (d->edit_number2) { #ifdef undef case 4: send_to_char (DCH, "Enter mob strength:"); break; case 5: send_to_char (DCH, "Enter mob strength modifier (useful only if strength = 18):"); break; case 6: send_to_char (DCH, "Enter mob intelligence:"); break; case 7: send_to_char (DCH, "Enter mob power:"); break; case 8: send_to_char (DCH, "Enter mob dexterity:"); break; case 9: send_to_char (DCH, "Enter mob mind:"); break; case 10: send_to_char (DCH, "Enter mob charisma:"); break; #endif case 1: medit_resist_menu (d); break; case 2: send_to_char (DCH, "Enter mob magic resistance (%):"); break; case 3: medit_disease_menu (d); break; } if (d->edit_number2 > 0) { d->edit_mode = MEDIT_EXTENDED_VAL; } else { medit_disp_menu (d); } break; case MEDIT_EXTENDED_VAL: i = atoi (arg); switch (d->edit_number2) { case 1: if ((i < 0) || (i > 29)) { send_to_char (DCH, "That's not a valid choice!\r\n"); medit_resist_menu (d); d->edit_mode = MEDIT_EXTENDED_VAL; return; } if (i == 0) { medit_disp_extended_menu (d); d->edit_mode = MEDIT_EXTENDED_PROMPT; return; } if (IS_SET (DMOB->char_specials.saved.d_immunities, 1 << (i - 1))) { REMOVE_BIT (DMOB->char_specials.saved.d_immunities, 1 << (i - 1)); } else { SET_BIT (DMOB->char_specials.saved.d_immunities, 1 << (i - 1)); } medit_resist_menu (d); d->edit_mode = MEDIT_EXTENDED_VAL; return; break; case 2: if ((i < 0) || (i > 100)) { send_to_char ( DCH, "Invalid choice!\r\nEnter mob resistance (%):"); return; } else { GET_MAGIC_RES (DMOB) = i; } break; case 3: if ((i < 0) || (i >= MAX_DISEASES)) { send_to_char (DCH, "That's not a valid choice!\r\n"); medit_disease_menu (d); d->edit_mode = MEDIT_EXTENDED_VAL; return; } if (i == 0) { medit_disp_extended_menu (d); d->edit_mode = MEDIT_EXTENDED_PROMPT; return; } /* i-1 should be i since the menu already offsets the bit */ if (IS_SET (DMOB->char_specials.saved.diseased_by, 1 << (i - 1))) { REMOVE_BIT (DMOB->char_specials.saved.diseased_by, 1 << (i - 1)); } else { SET_BIT (DMOB->char_specials.saved.diseased_by, 1 << (i - 1)); } medit_disease_menu (d); d->edit_mode = MEDIT_EXTENDED_VAL; return; break; default: break; } medit_disp_extended_menu (d); d->edit_mode = MEDIT_EXTENDED_PROMPT; break; case MEDIT_RACE: i = atoi (arg); if (i < 0 || i >= NUM_MOB_RACES) { send_to_char (DCH, "Invalid choice!\r\n"); send_to_char (DCH, "Enter mob race:\r\n"); return; } else { GET_MOB_RACE (DMOB) = sorted_race[i]; } medit_disp_menu (d); break; } } void write_zone_mobs (int zone) { int i, j; FILE *fp, *fp2; CHAR_DATA *mob; struct mob_spell *mob_spell; CREATE (mob, CHAR_DATA, 1); sprintf (buf, "%s/%d.mob.bak", MOB_PREFIX, zone_table[zone].number); fp = fopen (buf, "w+"); sprintf (buf, "%s/%d.mob.ept", MOB_PREFIX, zone_table[zone].number); fp2 = fopen (buf, "w+"); /* * start running through all mobs in this zone */ for (i = zone_table[zone].number * 100; i <= zone_table[zone].top; i++) { /* write object to disk */ j = real_mobile (i); if (j >= 0 && !MOB_DELETED (j)) { int extend_flag = false; *mob = mob_proto[j]; uvfprintf(fp2, "StartMobile\n"); uvfprintf(fp2, " StartCharacter\n"); uvfprintf(fp2, " StartEntity\n"); uvfprintf(fp2, " Name %s\n", mob->player.short_descr); uvfprintf(fp2, " Description\n%s~\n", mob->player.description); uvfprintf(fp2, " EndEntity\n"); uvfprintf(fp2, " Level %d\n", MIN(30, MAX(1,(mob->player.level + 1)/ 2))); uvfprintf(fp2, " Gender %s\n", mob->player.sex == SEX_MALE ? "male" : (mob->player.sex == SEX_FEMALE ? "female" : "neutral")); uvfprintf(fp2, " EndCharacter\n"); uvfprintf(fp2, " ID %d\n", i); uvfprintf(fp2, " ShortDescription %s", mob->player.long_descr); if (mob->player.long_descr[strlen(mob->player.long_descr) - 1] != '\n') uvfprintf(fp2, "\n"); uvfprintf(fp2, " Aliases %s\n", mob->player.name); uvfprintf(fp2, " Race %s\n", mob_races[mob->mob_specials.mob_race].race_name); if (mob->mob_specials.medit_data[0]) uvfprintf(fp2, " HealthQuality %d\n", mob->mob_specials.medit_data[0]); if (mob->mob_specials.medit_data[3]) uvfprintf(fp2, " HitrollQuality %d\n", mob->mob_specials.medit_data[3]); if (mob->mob_specials.medit_data[2]) uvfprintf(fp2, " ArmorQuality %d\n", mob->mob_specials.medit_data[2]); if (mob->mob_specials.medit_data[1]) uvfprintf(fp2, " DamageQuality %d\n", mob->mob_specials.medit_data[1]); // Don't check if positive: we want zero treasure qualities uvfprintf(fp2, " TreasureQuality %d\n", mob->mob_specials.medit_data[4]); if (GET_MAGIC_RES (mob) != 0) { uvfprintf(fp2, " MagicResistance %d\n", GET_MAGIC_RES(mob)); } uvfprintf(fp2, " NumberAttacks %d\n", mob->mob_specials.num_attacks); uvfprintf(fp2, " Behaviours "); uvfprintf(fp2, "%c", MOB_FLAGGED(mob, MOB_SENTINEL) ? '1' : '0'); uvfprintf(fp2, "%c", MOB_FLAGGED(mob, MOB_SCAVENGER) ? '1' : '0'); uvfprintf(fp2, "%c", MOB_FLAGGED(mob, MOB_EQUIPPER) ? '1' : '0'); uvfprintf(fp2, "%c", MOB_FLAGGED(mob, MOB_AWARE) ? '1' : '0'); uvfprintf(fp2, "%c", MOB_FLAGGED(mob, MOB_STAY_ZONE) ? '1' : '0'); uvfprintf(fp2, "%c", MOB_FLAGGED(mob, MOB_WIMPY) ? '1' : '0'); uvfprintf(fp2, "%c", MOB_FLAGGED(mob, MOB_AGGRESSIVE) ? '1' : '0'); uvfprintf(fp2, "%c", MOB_FLAGGED(mob, MOB_MEMORY) ? '1' : '0'); uvfprintf(fp2, "%c", MOB_FLAGGED(mob, MOB_HUNT) ? '1' : '0'); uvfprintf(fp2, "%c", MOB_FLAGGED(mob, MOB_LIGHTSLEEP) ? '1' : '0'); // no equivalent for warrior uvfprintf(fp2, "0"); uvfprintf(fp2, "%c", MOB_FLAGGED(mob, MOB_THIEF) ? '1' : '0'); uvfprintf(fp2, "%c", MOB_FLAGGED(mob, MOB_MAGE) ? '1' : '0'); uvfprintf(fp2, "%c", MOB_FLAGGED(mob, MOB_CLERIC) ? '1' : '0'); uvfprintf(fp2, "%c", MOB_FLAGGED(mob, MOB_SWIM) ? '1' : '0'); uvfprintf(fp2, "%c", MOB_FLAGGED(mob, MOB_MOUNTABLE) ? '1' : '0'); uvfprintf(fp2, "%c", MOB_FLAGGED(mob, MOB_SUMMONED) ? '1' : '0'); uvfprintf(fp2, "%c", MOB_FLAGGED(mob, MOB_HELPER) ? '1' : '0'); uvfprintf(fp2, "%c", MOB_FLAGGED(mob, MOB_PSIONICIST) ? '1' : '0'); // check train spec proc? { SPECIAL(guild); if (GET_MOB_SPEC (mob) == guild) { uvfprintf(fp2, "1"); } else { uvfprintf(fp2, "0"); } } { SPECIAL(postmaster); if (GET_MOB_SPEC (mob) == postmaster) { uvfprintf(fp2, "1"); } else { uvfprintf(fp2, "0"); } } { SPECIAL(teller); if (GET_MOB_SPEC (mob) == teller) { uvfprintf(fp2, "1"); } else { uvfprintf(fp2, "0"); } } uvfprintf(fp2, "\n"); uvfprintf(fp2, " Resistances "); uvfprintf(fp2, "0"); uvfprintf(fp2, "%c", IS_IMMUNE(mob, (1 << 0)) ? '1' : '0'); uvfprintf(fp2, "%c", IS_IMMUNE(mob, (1 << 1)) ? '1' : '0'); uvfprintf(fp2, "%c", IS_IMMUNE(mob, (1 << 2)) ? '1' : '0'); uvfprintf(fp2, "%c", IS_IMMUNE(mob, (1 << 3)) ? '1' : '0'); uvfprintf(fp2, "%c", IS_IMMUNE(mob, (1 << 4)) ? '1' : '0'); uvfprintf(fp2, "%c", IS_IMMUNE(mob, (1 << 5)) ? '1' : '0'); uvfprintf(fp2, "%c", IS_IMMUNE(mob, (1 << 6)) ? '1' : '0'); uvfprintf(fp2, "%c", IS_IMMUNE(mob, (1 << 7)) ? '1' : '0'); uvfprintf(fp2, "%c", IS_IMMUNE(mob, (1 << 8)) ? '1' : '0'); uvfprintf(fp2, "%c", IS_IMMUNE(mob, (1 << 9)) ? '1' : '0'); uvfprintf(fp2, "%c", IS_IMMUNE(mob, (1 << 10)) ? '1' : '0'); uvfprintf(fp2, "%c", IS_IMMUNE(mob, (1 << 11)) ? '1' : '0'); uvfprintf(fp2, "%c", IS_IMMUNE(mob, (1 << 12)) ? '1' : '0'); uvfprintf(fp2, "%c", IS_IMMUNE(mob, (1 << 13)) ? '1' : '0'); uvfprintf(fp2, "%c", IS_IMMUNE(mob, (1 << 14)) ? '1' : '0'); uvfprintf(fp2, "\n"); uvfprintf(fp2, " Immunities "); uvfprintf(fp2, "0"); uvfprintf(fp2, "%c", IS_IMMUNE(mob, (1 << 15)) ? '1' : '0'); uvfprintf(fp2, "%c", IS_IMMUNE(mob, (1 << 16)) ? '1' : '0'); uvfprintf(fp2, "%c", IS_IMMUNE(mob, (1 << 17)) ? '1' : '0'); uvfprintf(fp2, "%c", IS_IMMUNE(mob, (1 << 18)) ? '1' : '0'); uvfprintf(fp2, "%c", IS_IMMUNE(mob, (1 << 19)) ? '1' : '0'); uvfprintf(fp2, "%c", IS_IMMUNE(mob, (1 << 20)) ? '1' : '0'); uvfprintf(fp2, "%c", IS_IMMUNE(mob, (1 << 21)) ? '1' : '0'); uvfprintf(fp2, "%c", IS_IMMUNE(mob, (1 << 22)) ? '1' : '0'); uvfprintf(fp2, "%c", IS_IMMUNE(mob, (1 << 23)) ? '1' : '0'); uvfprintf(fp2, "%c", IS_IMMUNE(mob, (1 << 24)) ? '1' : '0'); uvfprintf(fp2, "%c", IS_IMMUNE(mob, (1 << 25)) ? '1' : '0'); uvfprintf(fp2, "%c", IS_IMMUNE(mob, (1 << 26)) ? '1' : '0'); uvfprintf(fp2, "%c", IS_IMMUNE(mob, (1 << 27)) ? '1' : '0'); uvfprintf(fp2, "%c", IS_IMMUNE(mob, (1 << 28)) ? '1' : '0'); uvfprintf(fp2, "%c", IS_IMMUNE(mob, (1 << 29)) ? '1' : '0'); uvfprintf(fp2, "\n"); if (mob->mob_specials.attack_type != 0) { if (IS_SET(mob->mob_specials.attack_type, (1 << 1))) uvfprintf(fp2, "NormalAttack claw\n"); if (IS_SET(mob->mob_specials.attack_type, (1 << 2))) uvfprintf(fp2, "NormalAttack bite\n"); if (IS_SET(mob->mob_specials.attack_type, (1 << 3))) uvfprintf(fp2, "NormalAttack sting\n"); if (IS_SET(mob->mob_specials.attack_type, (1 << 4))) uvfprintf(fp2, "NormalAttack tail slap\n"); if (IS_SET(mob->mob_specials.attack_type, (1 << 5))) uvfprintf(fp2, "NormalAttack tentacle\n"); if (IS_SET(mob->mob_specials.attack_type, (1 << 6))) uvfprintf(fp2, "NormalAttack peck\n"); if (IS_SET(mob->mob_specials.attack_type, (1 << 7))) uvfprintf(fp2, "NormalAttack kick\n"); } if (mob->mob_specials.special_attack_type != 0 && mob->mob_specials.special_attack_type != TYPE_NPC_SPEC_NONE) { switch (mob->mob_specials.special_attack_type + TYPE_NPC_SPEC_NONE) { case TYPE_NPC_SPEC_BREATHE_FIRE: uvfprintf(fp2, "SpecialAttack breathe fire\n"); break; case TYPE_NPC_SPEC_BREATHE_GAS: uvfprintf(fp2, "SpecialAttack breathe gas\n"); break; case TYPE_NPC_SPEC_BREATHE_FROST: uvfprintf(fp2, "SpecialAttack breathe frost\n"); break; case TYPE_NPC_SPEC_BREATHE_ACID: uvfprintf(fp2, "SpecialAttack breathe acid\n"); break; case TYPE_NPC_SPEC_BREATHE_LIGHT: uvfprintf(fp2, "SpecialAttack breathe lightning\n"); break; case TYPE_NPC_SPEC_MANADRAIN: uvfprintf(fp2, "SpecialAttack mana drain\n"); break; case TYPE_NPC_SPEC_STAMINADRAIN: uvfprintf(fp2, "SpecialAttack stamina drain\n"); break; case TYPE_NPC_SPEC_HPDRAIN: uvfprintf(fp2, "SpecialAttack health drain\n"); break; case TYPE_NPC_SPEC_PETRIFY: uvfprintf(fp2, "SpecialAttack petrify\n"); break; } } fprintf (fp, "#%d\n", GET_MOB_VNUM (mob)); fprintf (fp, "%s~\n", mob->player.name ? mob->player.name : ""); fprintf (fp, "%s~\n", mob->player.short_descr ? mob->player.short_descr : ""); uvfprintf (fp, "%s~\n", mob->player.long_descr ? mob->player.long_descr : ""); uvfprintf (fp, "%s~\n", mob->player.description ? mob->player.description : ""); if (mob->mob_specials.attack_type != 0 || mob->char_specials.saved.d_immunities != 0 || mob->char_specials.saved.diseased_by != 0 || mob->mob_specials.num_attacks > 1 || mob->mob_specials.mob_spells || mob->mob_specials.medit_data[0] != 0 || mob->mob_specials.medit_data[1] != 0 || mob->mob_specials.medit_data[2] != 0 || mob->mob_specials.medit_data[3] != 0 || mob->mob_specials.medit_data[4] != 0 || GET_MAGIC_RES (mob) != 0) { extend_flag = true; } fprintf (fp, "R %ld %ld %d %d %c\n", mob->mob_specials.mob, mob->char_specials.saved.affected_by, mob->char_specials.saved.alignment, mob->mob_specials.mob_race, extend_flag ? 'E' : 'S'); fprintf (fp, "%d %d %d %dd%d+%d %dd%d+%d\n", mob->player.level, mob->points.hitroll, mob->points.armor, mob->points.hit, mob->points.mana, mob->points.move, mob->mob_specials.damnodice, mob->mob_specials.damsizedice, mob->mob_specials.damadd); fprintf (fp, "%d %ld\n", mob->points.gold, mob->points.exp); fprintf (fp, "%d %d %d\n", mob->char_specials.position, mob->mob_specials.default_pos, mob->player.sex); if (extend_flag) { if (mob->mob_specials.attack_type != 0) { fprintf (fp, "NewBareHandAttack: %d\n", mob->mob_specials.attack_type); } if (mob->mob_specials.special_attack_type != 0 && mob->mob_specials.special_attack_type != TYPE_NPC_SPEC_NONE) { fprintf (fp, "SpecialAttack: %d\n", mob->mob_specials.special_attack_type); } if (mob->char_specials.saved.d_immunities != 0) { fprintf (fp, "Resistances: %ld\n", mob->char_specials.saved.d_immunities); } if (mob->char_specials.saved.diseased_by != 0) { fprintf (fp, "Disease: %ld\n", mob->char_specials.saved.diseased_by); } if (mob->mob_specials.num_attacks > 1) { fprintf (fp, "APR: %d\n", mob->mob_specials.num_attacks); } if (GET_MAGIC_RES (mob) != 0) { fprintf (fp, "Magic resistance: %d\n", GET_MAGIC_RES (mob)); uvfprintf(fp2, "MagicResistance %d\n", GET_MAGIC_RES(mob)); } for (mob_spell = mob->mob_specials.mob_spells; mob_spell; mob_spell = mob_spell->next) { fprintf (fp, "Spell: %d\n", mob_spell->spell_num); uvfprintf(fp2, "Spell %s\n", spells[mob_spell->spell_num]); } if (mob->mob_specials.medit_data[0] != 0) { fprintf (fp, "HPT Quality: %d\n", mob->mob_specials.medit_data[0]); } if (mob->mob_specials.medit_data[1] != 0) { fprintf (fp, "DAM Quality: %d\n", mob->mob_specials.medit_data[1]); } if (mob->mob_specials.medit_data[2] != 0) { fprintf (fp, "AC Quality: %d\n", mob->mob_specials.medit_data[2]); } if (mob->mob_specials.medit_data[3] != 0) { fprintf (fp, "THAC0 Quality: %d\n", mob->mob_specials.medit_data[3]); } if (mob->mob_specials.medit_data[4] != 0) { fprintf (fp, "GOLD Quality: %d\n", mob->mob_specials.medit_data[4]); } fprintf (fp, "E\n"); } uvfprintf(fp2, "EndMobile\n"); } } /* free up temp */ free (mob); /* write final line, close */ fprintf (fp, "$~\n"); fclose (fp); fclose(fp2); }