/************************************************************************** * Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, * * Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe. * * * * Merc Diku Mud improvements copyright (C) 1992, 1993 by Michael * * Chastain, Michael Quan, and Mitchell Tse. * * * * In order to use any part of this Merc Diku Mud, you must comply with * * both the original Diku license in 'license.doc' as well the Merc * * license in 'license.txt'. In particular, you may not remove either of * * these copyright notices. * * * * Much time and thought has gone into this software and you are * * benefiting. We hope that you share your changes too. What goes * * around, comes around. * *************************************************************************** * ROM 2.4 is copyright 1993-1998 Russ Taylor * * ROM has been brought to you by the ROM consortium * * Russ Taylor (rtaylor@hypercube.org) * * Gabrielle Taylor (gtaylor@hypercube.org) * * Brian Moore (zump@rom.org) * * By using this code, you have agreed to follow the terms of the * * ROM license, in the file Rom24/doc/rom.license * *************************************************************************** * 1stMUD ROM Derivative (c) 2001-2002 by Ryan Jennings * * http://1stmud.dlmud.com/ <r-jenn@shaw.ca> * ***************************************************************************/ /************************************************************************** * File: olc_save.c * * * * Much time and thought has gone into this software and you are * * benefitting. We hope that you share your changes too. What goes * * around, comes around. * * * * This code was freely distributed with the The Isles 1.1 source code, * * and has been used here for OLC - OLC would not be what it is without * * all the previous coders who released their source code. * * * ***************************************************************************/ /* OLC_SAVE.C * This takes care of saving all the .are information. * Notes: * -If a good syntax checker is used for setting vnum ranges of areas * then it would become possible to just cycle through vnums instead * of using the iHash stuff and checking that the room or reset or * mob etc is part of that area. */ #include <sys/types.h> #include <ctype.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #include "merc.h" #include "tables.h" #include "olc.h" #include "interp.h" #define DIF(a,b) (~((~a)|(b))) /* * Verbose writes reset data in plain english into the comments * section of the resets. It makes areas considerably larger but * may aid in debugging. */ /* #define VERBOSE */ /***************************************************************************** Name: fix_string Purpose: Returns a string without \r and ~. ****************************************************************************/ char *fix_string (const char *str) { static char strfix[MAX_STRING_LENGTH * 2]; int i; int o; if (str == NULL) return '\0'; for (o = i = 0; str[i + o] != '\0'; i++) { if (str[i + o] == '\r' || str[i + o] == '~') o++; strfix[i] = str[i + o]; } strfix[i] = '\0'; return strfix; } /***************************************************************************** Name: save_area_list Purpose: Saves the listing of files to be loaded at startup. Called by: do_asave(olc_save.c). ****************************************************************************/ void save_area_list () { FILE *fp; AREA_DATA *pArea; extern HELP_AREA *had_list; HELP_AREA *ha; if ((fp = file_open ("area.lst", "w")) == NULL) { bug ("Save_area_list: file_open", 0); perror ("area.lst"); } else { /* * Add any help files that need to be loaded at * startup to this section. */ for (ha = had_list; ha; ha = ha->next) if (ha->area == NULL) fprintf (fp, "%s\n", ha->filename); for (pArea = area_first; pArea; pArea = pArea->next) { fprintf (fp, "%s\n", pArea->file_name); } fprintf (fp, "$\n"); file_close (fp); } return; } #define NBUF 5 #define NBITS 52 char *fwrite_flags (flag_t flags) { static int cnt; static char buf[NBUF][NBITS + 1]; int count, pos = 0; cnt = (cnt + 1) % NBUF; for (count = 0; count < NBITS; count++) if (IS_SET (flags, (flag_t) 1 << count)) { if (count < 26) buf[cnt][pos] = 'A' + count; else buf[cnt][pos] = 'a' + (count - 26); pos++; } if (pos == 0) buf[cnt][pos++] = '0'; buf[cnt][pos] = '\0'; return buf[cnt]; } void save_mobprogs (FILE * fp, AREA_DATA * pArea) { MPROG_CODE *pMprog; vnum_t i; fprintf (fp, "#MOBPROGS\n"); for (i = pArea->min_vnum; i <= pArea->max_vnum; i++) { if ((pMprog = get_mprog_index (i)) != NULL) { fprintf (fp, "#%ld\n", i); fprintf (fp, "%s~\n", fix_string (pMprog->code)); } } fprintf (fp, "#0\n\n"); return; } /***************************************************************************** Name: save_mobile Purpose: Save one mobile to file, new format -- Hugin Called by: save_mobiles (below). ****************************************************************************/ void save_mobile (FILE * fp, MOB_INDEX_DATA * pMobIndex) { int race = pMobIndex->race; MPROG_LIST *pMprog; flag_t temp; fprintf (fp, "#%ld\n", pMobIndex->vnum); fprintf (fp, "%s~\n", pMobIndex->player_name); fprintf (fp, "%s~\n", pMobIndex->short_descr); fprintf (fp, "%s~\n", fix_string (pMobIndex->long_descr)); fprintf (fp, "%s~\n", fix_string (pMobIndex->description)); fprintf (fp, "%s~\n", race_table[race].name); fprintf (fp, "%s ", fwrite_flags (pMobIndex->act)); fprintf (fp, "%s ", fwrite_flags (pMobIndex->affected_by)); fprintf (fp, "%d %ld\n", pMobIndex->alignment, pMobIndex->group); fprintf (fp, "%d ", pMobIndex->level); fprintf (fp, "%d ", pMobIndex->hitroll); fprintf (fp, "%dd%d+%d ", pMobIndex->hit[DICE_NUMBER], pMobIndex->hit[DICE_TYPE], pMobIndex->hit[DICE_BONUS]); fprintf (fp, "%dd%d+%d ", pMobIndex->mana[DICE_NUMBER], pMobIndex->mana[DICE_TYPE], pMobIndex->mana[DICE_BONUS]); fprintf (fp, "%dd%d+%d ", pMobIndex->damage[DICE_NUMBER], pMobIndex->damage[DICE_TYPE], pMobIndex->damage[DICE_BONUS]); fprintf (fp, "%s\n", attack_table[pMobIndex->dam_type].name); fprintf (fp, "%d %d %d %d\n", pMobIndex->ac[AC_PIERCE] / 10, pMobIndex->ac[AC_BASH] / 10, pMobIndex->ac[AC_SLASH] / 10, pMobIndex->ac[AC_EXOTIC] / 10); fprintf (fp, "%s ", fwrite_flags (pMobIndex->off_flags)); fprintf (fp, "%s ", fwrite_flags (pMobIndex->imm_flags)); fprintf (fp, "%s ", fwrite_flags (pMobIndex->res_flags)); fprintf (fp, "%s\n", fwrite_flags (pMobIndex->vuln_flags)); fprintf (fp, "%s %s %s %ld\n", position_table[pMobIndex->start_pos].short_name, position_table[pMobIndex->default_pos].short_name, sex_table[pMobIndex->sex].name, pMobIndex->wealth); fprintf (fp, "%s ", fwrite_flags (pMobIndex->form)); fprintf (fp, "%s ", fwrite_flags (pMobIndex->parts)); fprintf (fp, "%s ", size_table[pMobIndex->size].name); fprintf (fp, "%s\n", IS_NULLSTR (pMobIndex-> material) ? pMobIndex->material : "unknown"); if ((temp = DIF (race_table[race].act, pMobIndex->act))) fprintf (fp, "F act %s\n", fwrite_flags (temp)); if ((temp = DIF (race_table[race].aff, pMobIndex->affected_by))) fprintf (fp, "F aff %s\n", fwrite_flags (temp)); if ((temp = DIF (race_table[race].off, pMobIndex->off_flags))) fprintf (fp, "F off %s\n", fwrite_flags (temp)); if ((temp = DIF (race_table[race].imm, pMobIndex->imm_flags))) fprintf (fp, "F imm %s\n", fwrite_flags (temp)); if ((temp = DIF (race_table[race].res, pMobIndex->res_flags))) fprintf (fp, "F res %s\n", fwrite_flags (temp)); if ((temp = DIF (race_table[race].vuln, pMobIndex->vuln_flags))) fprintf (fp, "F vul %s\n", fwrite_flags (temp)); if ((temp = DIF (race_table[race].form, pMobIndex->form))) fprintf (fp, "F for %s\n", fwrite_flags (temp)); if ((temp = DIF (race_table[race].parts, pMobIndex->parts))) fprintf (fp, "F par %s\n", fwrite_flags (temp)); for (pMprog = pMobIndex->mprogs; pMprog; pMprog = pMprog->next) { fprintf (fp, "M %s %ld %s~\n", mprog_type_to_name (pMprog->trig_type), pMprog->vnum, pMprog->trig_phrase); } return; } /***************************************************************************** Name: save_mobiles Purpose: Save #MOBILES secion of an area file. Called by: save_area(olc_save.c). Notes: Changed for ROM OLC. ****************************************************************************/ void save_mobiles (FILE * fp, AREA_DATA * pArea) { vnum_t i; MOB_INDEX_DATA *pMob; fprintf (fp, "#MOBILES\n"); for (i = pArea->min_vnum; i <= pArea->max_vnum; i++) { if ((pMob = get_mob_index (i))) save_mobile (fp, pMob); } fprintf (fp, "#0\n\n\n\n"); return; } /***************************************************************************** Name: save_object Purpose: Save one object to file. new ROM format saving -- Hugin Called by: save_objects (below). ****************************************************************************/ void save_object (FILE * fp, OBJ_INDEX_DATA * pObjIndex) { char letter; AFFECT_DATA *pAf; EXTRA_DESCR_DATA *pEd; fprintf (fp, "#%ld\n", pObjIndex->vnum); fprintf (fp, "%s~\n", pObjIndex->name); fprintf (fp, "%s~\n", pObjIndex->short_descr); fprintf (fp, "%s~\n", fix_string (pObjIndex->description)); fprintf (fp, "%s~\n", pObjIndex->material); fprintf (fp, "%s ", item_name (pObjIndex->item_type)); fprintf (fp, "%s ", fwrite_flags (pObjIndex->extra_flags)); fprintf (fp, "%s\n", fwrite_flags (pObjIndex->wear_flags)); /* * Using fwrite_flag to write most values gives a strange * looking area file, consider making a case for each * item type later. */ switch (pObjIndex->item_type) { default: fprintf (fp, "%s ", fwrite_flags (pObjIndex->value[0])); fprintf (fp, "%s ", fwrite_flags (pObjIndex->value[1])); fprintf (fp, "%s ", fwrite_flags (pObjIndex->value[2])); fprintf (fp, "%s ", fwrite_flags (pObjIndex->value[3])); fprintf (fp, "%s\n", fwrite_flags (pObjIndex->value[4])); break; case ITEM_DRINK_CON: case ITEM_FOUNTAIN: fprintf (fp, "%ld %ld '%s' %ld %ld\n", pObjIndex->value[0], pObjIndex->value[1], liq_table[pObjIndex->value[2]].liq_name, pObjIndex->value[3], pObjIndex->value[4]); break; case ITEM_CONTAINER: fprintf (fp, "%ld %s %ld %ld %ld\n", pObjIndex->value[0], fwrite_flags (pObjIndex->value[1]), pObjIndex->value[2], pObjIndex->value[3], pObjIndex->value[4]); break; case ITEM_WEAPON: fprintf (fp, "%s %ld %ld %s %s\n", weapon_name (pObjIndex->value[0]), pObjIndex->value[1], pObjIndex->value[2], attack_table[pObjIndex->value[3]].name, fwrite_flags (pObjIndex->value[4])); break; case ITEM_PILL: case ITEM_POTION: case ITEM_SCROLL: fprintf (fp, "%ld '%s' '%s' '%s' '%s'\n", pObjIndex->value[0] > 0 ? /* no negative numbers */ pObjIndex->value[0] : 0, pObjIndex->value[1] != -1 ? skill_table[pObjIndex->value[1]].name : "", pObjIndex->value[2] != -1 ? skill_table[pObjIndex->value[2]].name : "", pObjIndex->value[3] != -1 ? skill_table[pObjIndex->value[3]].name : "", pObjIndex->value[4] != -1 ? skill_table[pObjIndex->value[4]].name : ""); break; case ITEM_STAFF: case ITEM_WAND: fprintf (fp, "%ld %ld %ld '%s' %ld\n", pObjIndex->value[0], pObjIndex->value[1], pObjIndex->value[2], pObjIndex->value[3] != -1 ? skill_table[pObjIndex->value[3]].name : "", pObjIndex->value[4]); break; } fprintf (fp, "%d ", pObjIndex->level); fprintf (fp, "%d ", pObjIndex->weight); fprintf (fp, "%d ", pObjIndex->cost); if (pObjIndex->condition > 90) letter = 'P'; else if (pObjIndex->condition > 75) letter = 'G'; else if (pObjIndex->condition > 50) letter = 'A'; else if (pObjIndex->condition > 25) letter = 'W'; else if (pObjIndex->condition > 10) letter = 'D'; else if (pObjIndex->condition > 0) letter = 'B'; else letter = 'R'; fprintf (fp, "%c\n", letter); for (pAf = pObjIndex->affected; pAf; pAf = pAf->next) { if (pAf->where == TO_OBJECT || pAf->bitvector == 0) fprintf (fp, "A\n%d %d\n", pAf->location, pAf->modifier); else { fprintf (fp, "F\n"); switch (pAf->where) { case TO_AFFECTS: fprintf (fp, "A "); break; case TO_IMMUNE: fprintf (fp, "I "); break; case TO_RESIST: fprintf (fp, "R "); break; case TO_VULN: fprintf (fp, "V "); break; default: bug ("olc_save: Invalid Affect->where", 0); break; } fprintf (fp, "%d %d %s\n", pAf->location, pAf->modifier, fwrite_flags (pAf->bitvector)); } } for (pEd = pObjIndex->extra_descr; pEd; pEd = pEd->next) { fprintf (fp, "E\n%s~\n%s~\n", pEd->keyword, fix_string (pEd->description)); } return; } /***************************************************************************** Name: save_objects Purpose: Save #OBJECTS section of an area file. Called by: save_area(olc_save.c). Notes: Changed for ROM OLC. ****************************************************************************/ void save_objects (FILE * fp, AREA_DATA * pArea) { vnum_t i; OBJ_INDEX_DATA *pObj; fprintf (fp, "#OBJECTS\n"); for (i = pArea->min_vnum; i <= pArea->max_vnum; i++) { if ((pObj = get_obj_index (i))) save_object (fp, pObj); } fprintf (fp, "#0\n\n\n\n"); return; } /***************************************************************************** Name: save_rooms Purpose: Save #ROOMS section of an area file. Called by: save_area(olc_save.c). ****************************************************************************/ void save_rooms (FILE * fp, AREA_DATA * pArea) { ROOM_INDEX_DATA *pRoomIndex; EXTRA_DESCR_DATA *pEd; EXIT_DATA *pExit; int iHash; int door; fprintf (fp, "#ROOMS\n"); for (iHash = 0; iHash < MAX_KEY_HASH; iHash++) { for (pRoomIndex = room_index_hash[iHash]; pRoomIndex; pRoomIndex = pRoomIndex->next) { if (pRoomIndex->area == pArea) { fprintf (fp, "#%ld\n", pRoomIndex->vnum); fprintf (fp, "%s~\n", pRoomIndex->name); fprintf (fp, "%s~\n", fix_string (pRoomIndex->description)); fprintf (fp, "0 "); fprintf (fp, "%s ", fwrite_flags (pRoomIndex->room_flags)); fprintf (fp, "%d\n", pRoomIndex->sector_type); for (pEd = pRoomIndex->extra_descr; pEd; pEd = pEd->next) { fprintf (fp, "E\n%s~\n%s~\n", pEd->keyword, fix_string (pEd->description)); } for (door = 0; door < MAX_DIR; door++) /* I hate this! */ { if ((pExit = pRoomIndex->exit[door]) && pExit->u1.to_room) { int locks = 0; /* HACK : TO PREVENT EX_LOCKED etc without EX_ISDOOR to stop booting the mud */ if (IS_SET (pExit->rs_flags, EX_CLOSED) || IS_SET (pExit->rs_flags, EX_LOCKED) || IS_SET (pExit->rs_flags, EX_PICKPROOF) || IS_SET (pExit->rs_flags, EX_NOPASS) || IS_SET (pExit->rs_flags, EX_EASY) || IS_SET (pExit->rs_flags, EX_HARD) || IS_SET (pExit->rs_flags, EX_INFURIATING) || IS_SET (pExit->rs_flags, EX_NOCLOSE) || IS_SET (pExit->rs_flags, EX_NOLOCK)) SET_BIT (pExit->rs_flags, EX_ISDOOR); else REMOVE_BIT (pExit->rs_flags, EX_ISDOOR); /* THIS SUCKS but it's backwards compatible */ /* NOTE THAT EX_NOCLOSE NOLOCK etc aren't being saved */ if (IS_SET (pExit->rs_flags, EX_ISDOOR) && (!IS_SET (pExit->rs_flags, EX_PICKPROOF)) && (!IS_SET (pExit->rs_flags, EX_NOPASS))) locks = 1; if (IS_SET (pExit->rs_flags, EX_ISDOOR) && (IS_SET (pExit->rs_flags, EX_PICKPROOF)) && (!IS_SET (pExit->rs_flags, EX_NOPASS))) locks = 2; if (IS_SET (pExit->rs_flags, EX_ISDOOR) && (!IS_SET (pExit->rs_flags, EX_PICKPROOF)) && (IS_SET (pExit->rs_flags, EX_NOPASS))) locks = 3; if (IS_SET (pExit->rs_flags, EX_ISDOOR) && (IS_SET (pExit->rs_flags, EX_PICKPROOF)) && (IS_SET (pExit->rs_flags, EX_NOPASS))) locks = 4; fprintf (fp, "D%d\n", pExit->orig_door); fprintf (fp, "%s~\n", fix_string (pExit->description)); fprintf (fp, "%s~\n", pExit->keyword); fprintf (fp, "%d %ld %ld\n", locks, pExit->key, pExit->u1.to_room->vnum); } } if (pRoomIndex->mana_rate != 100 || pRoomIndex->heal_rate != 100) fprintf (fp, "M %d H %d\n", pRoomIndex->mana_rate, pRoomIndex->heal_rate); if (pRoomIndex->clan > -1) fprintf (fp, "C %s~\n", clan_table[pRoomIndex->clan].name); if (!IS_NULLSTR (pRoomIndex->owner)) fprintf (fp, "O %s~\n", pRoomIndex->owner); fprintf (fp, "S\n"); } } } fprintf (fp, "#0\n\n\n\n"); return; } /***************************************************************************** Name: save_specials Purpose: Save #SPECIALS section of area file. Called by: save_area(olc_save.c). ****************************************************************************/ void save_specials (FILE * fp, AREA_DATA * pArea) { int iHash; MOB_INDEX_DATA *pMobIndex; fprintf (fp, "#SPECIALS\n"); for (iHash = 0; iHash < MAX_KEY_HASH; iHash++) { for (pMobIndex = mob_index_hash[iHash]; pMobIndex; pMobIndex = pMobIndex->next) { if (pMobIndex && pMobIndex->area == pArea && pMobIndex->spec_fun) { #if defined( VERBOSE ) fprintf (fp, "M %d %s Load to: %s\n", pMobIndex->vnum, spec_name (pMobIndex->spec_fun), pMobIndex->short_descr); #else fprintf (fp, "M %ld %s\n", pMobIndex->vnum, spec_name (pMobIndex->spec_fun)); #endif } } } fprintf (fp, "S\n\n\n\n"); return; } /* * This function is obsolete. It it not needed but has been left here * for historical reasons. It is used currently for the same reason. * * I don't think it's obsolete in ROM -- Hugin. */ void save_door_resets (FILE * fp, AREA_DATA * pArea) { int iHash; ROOM_INDEX_DATA *pRoomIndex; EXIT_DATA *pExit; int door; for (iHash = 0; iHash < MAX_KEY_HASH; iHash++) { for (pRoomIndex = room_index_hash[iHash]; pRoomIndex; pRoomIndex = pRoomIndex->next) { if (pRoomIndex->area == pArea) { for (door = 0; door < MAX_DIR; door++) { if ((pExit = pRoomIndex->exit[door]) && pExit->u1.to_room && (IS_SET (pExit->rs_flags, EX_CLOSED) || IS_SET (pExit->rs_flags, EX_LOCKED))) #if defined( VERBOSE ) fprintf (fp, "D 0 %d %d %d The %s door of %s is %s\n", pRoomIndex->vnum, pExit->orig_door, IS_SET (pExit->rs_flags, EX_LOCKED) ? 2 : 1, dir_name[pExit->orig_door], pRoomIndex->name, IS_SET (pExit->rs_flags, EX_LOCKED) ? "closed and locked" : "closed"); #endif #if !defined( VERBOSE ) fprintf (fp, "D 0 %ld %d %d\n", pRoomIndex->vnum, pExit->orig_door, IS_SET (pExit->rs_flags, EX_LOCKED) ? 2 : 1); #endif } } } } return; } /***************************************************************************** Name: save_resets Purpose: Saves the #RESETS section of an area file. Called by: save_area(olc_save.c) ****************************************************************************/ void save_resets (FILE * fp, AREA_DATA * pArea) { RESET_DATA *pReset; MOB_INDEX_DATA *pLastMob = NULL; OBJ_INDEX_DATA *pLastObj; ROOM_INDEX_DATA *pRoom; char buf[MAX_STRING_LENGTH]; int iHash; fprintf (fp, "#RESETS\n"); save_door_resets (fp, pArea); for (iHash = 0; iHash < MAX_KEY_HASH; iHash++) { for (pRoom = room_index_hash[iHash]; pRoom; pRoom = pRoom->next) { if (pRoom->area == pArea) { for (pReset = pRoom->reset_first; pReset; pReset = pReset->next) { switch (pReset->command) { default: bug ("Save_resets: bad command %c.", pReset->command); break; #if defined( VERBOSE ) case 'M': pLastMob = get_mob_index (pReset->arg1); fprintf (fp, "M 0 %ld %d %ld %d Load %s\n", pReset->arg1, pReset->arg2, pReset->arg3, pReset->arg4, pLastMob->short_descr); break; case 'O': pLastObj = get_obj_index (pReset->arg1); pRoom = get_room_index (pReset->arg3); fprintf (fp, "O 0 %ld 0 %ld %s loaded to %s\n", pReset->arg1, pReset->arg3, capitalize (pLastObj->short_descr), pRoom->name); break; case 'P': pLastObj = get_obj_index (pReset->arg1); fprintf (fp, "P 0 %ld %d %ld %d %s put inside %s\n", pReset->arg1, pReset->arg2, pReset->arg3, pReset->arg4, capitalize (get_obj_index (pReset->arg1)->short_descr), pLastObj->short_descr); break; case 'G': fprintf (fp, "G 0 %ld 0 %s is given to %s\n", pReset->arg1, capitalize (get_obj_index (pReset->arg1)->short_descr), pLastMob ? pLastMob->short_descr : "!NO_MOB!"); if (!pLastMob) { sprintf (buf, "Save_resets: !NO_MOB! in [%s]", pArea->file_name); bug (buf, 0); } break; case 'E': fprintf (fp, "E 0 %ld 0 %ld %s is loaded %s of %s\n", pReset->arg1, pReset->arg3, capitalize (get_obj_index (pReset->arg1)->short_descr), flag_string (wear_loc_strings, pReset->arg3), pLastMob ? pLastMob->short_descr : "!NO_MOB!"); if (!pLastMob) { sprintf (buf, "Save_resets: !NO_MOB! in [%s]", pArea->file_name); bug (buf, 0); } break; case 'D': break; case 'R': pRoom = get_room_index (pReset->arg1); fprintf (fp, "R 0 %ld %d Randomize %s\n", pReset->arg1, pReset->arg2, pRoom->name); break; #endif #if !defined( VERBOSE ) case 'M': pLastMob = get_mob_index (pReset->arg1); fprintf (fp, "M 0 %ld %d %ld %d\n", pReset->arg1, pReset->arg2, pReset->arg3, pReset->arg4); break; case 'O': pLastObj = get_obj_index (pReset->arg1); pRoom = get_room_index (pReset->arg3); fprintf (fp, "O 0 %ld 0 %ld\n", pReset->arg1, pReset->arg3); break; case 'P': pLastObj = get_obj_index (pReset->arg1); fprintf (fp, "P 0 %ld %d %ld %d\n", pReset->arg1, pReset->arg2, pReset->arg3, pReset->arg4); break; case 'G': fprintf (fp, "G 0 %ld 0\n", pReset->arg1); if (!pLastMob) { sprintf (buf, "Save_resets: !NO_MOB! in [%s]", pArea->file_name); bug (buf, 0); } break; case 'E': fprintf (fp, "E 0 %ld 0 %ld\n", pReset->arg1, pReset->arg3); if (!pLastMob) { sprintf (buf, "Save_resets: !NO_MOB! in [%s]", pArea->file_name); bug (buf, 0); } break; case 'D': break; case 'R': pRoom = get_room_index (pReset->arg1); fprintf (fp, "R 0 %ld %d\n", pReset->arg1, pReset->arg2); break; #endif } } } /* End if correct area */ } /* End for pRoom */ } /* End for iHash */ fprintf (fp, "S\n\n\n\n"); return; } /***************************************************************************** Name: save_shops Purpose: Saves the #SHOPS section of an area file. Called by: save_area(olc_save.c) ****************************************************************************/ void save_shops (FILE * fp, AREA_DATA * pArea) { SHOP_DATA *pShopIndex; MOB_INDEX_DATA *pMobIndex; int iTrade; int iHash; fprintf (fp, "#SHOPS\n"); for (iHash = 0; iHash < MAX_KEY_HASH; iHash++) { for (pMobIndex = mob_index_hash[iHash]; pMobIndex; pMobIndex = pMobIndex->next) { if (pMobIndex && pMobIndex->area == pArea && pMobIndex->pShop) { pShopIndex = pMobIndex->pShop; fprintf (fp, "%ld ", pShopIndex->keeper); for (iTrade = 0; iTrade < MAX_TRADE; iTrade++) { if (pShopIndex->buy_type[iTrade] != 0) { fprintf (fp, "%d ", pShopIndex->buy_type[iTrade]); } else fprintf (fp, "0 "); } fprintf (fp, "%d %d ", pShopIndex->profit_buy, pShopIndex->profit_sell); fprintf (fp, "%d %d\n", pShopIndex->open_hour, pShopIndex->close_hour); } } } fprintf (fp, "0\n\n\n\n"); return; } void save_helps (FILE * fp, HELP_AREA * ha) { HELP_DATA *help = ha->first; fprintf (fp, "#HELPS\n"); for (; help; help = help->next_area) { fprintf (fp, "%d %s~\n", help->level, help->keyword); fprintf (fp, "%s~\n\n", fix_string (help->text)); } fprintf (fp, "-1 $~\n\n"); ha->changed = FALSE; return; } void save_other_helps (CHAR_DATA * ch) { extern HELP_AREA *had_list; HELP_AREA *ha; FILE *fp; for (ha = had_list; ha; ha = ha->next) if (ha->changed == TRUE) { fp = file_open (ha->filename, "w"); if (!fp) { perror (ha->filename); return; } save_helps (fp, ha); if (ch) chprintf (ch, "%s\n\r", ha->filename); fprintf (fp, "#$\n"); file_close (fp); } return; } /***************************************************************************** Name: save_area Purpose: Save an area, note that this format is new. Called by: do_asave(olc_save.c). ****************************************************************************/ void save_area (AREA_DATA * pArea) { FILE *fp; if (!(fp = file_open (pArea->file_name, "w"))) { bug ("Open_area: file_open", 0); perror (pArea->file_name); } fprintf (fp, "#AREADATA\n"); fprintf (fp, "Name %s~\n", pArea->name); fprintf (fp, "Builders %s~\n", fix_string (pArea->builders)); fprintf (fp, "VNUMs %ld %ld\n", pArea->min_vnum, pArea->max_vnum); fprintf (fp, "Credits %s~\n", pArea->credits); fprintf (fp, "Security %d\n", pArea->security); fprintf (fp, "Flags %s\n", fwrite_flags (pArea->area_flags)); fprintf (fp, "End\n\n\n\n"); save_mobiles (fp, pArea); save_objects (fp, pArea); save_rooms (fp, pArea); save_specials (fp, pArea); save_resets (fp, pArea); save_shops (fp, pArea); save_mobprogs (fp, pArea); if (pArea->helps && pArea->helps->first) save_helps (fp, pArea->helps); fprintf (fp, "#$\n"); file_close (fp); return; } /***************************************************************************** Name: do_asave Purpose: Entry point for saving area data. Called by: interpreter(interp.c) ****************************************************************************/ CH_CMD (do_asave) { char arg1[MAX_INPUT_LENGTH]; AREA_DATA *pArea; FILE *fp; int value, sec; fp = NULL; if (!ch) /* Do an autosave */ sec = 9; else if (!IS_NPC (ch)) sec = ch->pcdata->security; else sec = 0; /* { save_area_list(); for( pArea = area_first; pArea; pArea = pArea->next ) { save_area( pArea ); REMOVE_BIT( pArea->area_flags, AREA_CHANGED ); } return; } */ smash_tilde (argument); strcpy (arg1, argument); if (arg1[0] == '\0') { if (ch) { chprintln (ch, "Syntax:"); chprintln (ch, " asave <vnum> - saves a particular area"); chprintln (ch, " asave list - saves the area.lst file"); chprintln (ch, " asave area - saves the area being edited"); chprintln (ch, " asave changed - saves all changed zones"); chprintln (ch, " asave world - saves the world! (db dump)"); chprintln (ch, " asave clans - saves clan data"); chprintln (ch, " asave commands - saves command data"); chprintln (ch, " asave skills - saves skill data"); chprintln (ch, " asave groups - saves group data"); chprintln (ch, " asave races - saves race data"); chprintln (ch, " asave classes - saves class data"); chprintln (ch, " asave socials - saves social data"); chprintln (ch, ""); } return; } /* Snarf the value (which need not be numeric). */ value = atoi (arg1); if (!(pArea = get_area_data (value)) && is_number (arg1)) { if (ch) chprintln (ch, "That area does not exist."); return; } /* Save area of given vnum. */ /* ------------------------ */ if (is_number (arg1)) { if (ch && !IS_BUILDER (ch, pArea)) { chprintln (ch, "You are not a builder for this area."); return; } save_area_list (); save_area (pArea); return; } /* Save the world, only authorized areas. */ /* -------------------------------------- */ if (!str_cmp ("world", arg1)) { save_area_list (); for (pArea = area_first; pArea; pArea = pArea->next) { /* Builder must be assigned this area. */ if (ch && !IS_BUILDER (ch, pArea)) continue; save_area (pArea); REMOVE_BIT (pArea->area_flags, AREA_CHANGED); } if (ch) chprintln (ch, "You saved the world."); save_other_helps (NULL); return; } /* Save changed areas, only authorized areas. */ /* ------------------------------------------ */ if (!str_cmp ("changed", arg1)) { char buf[MAX_INPUT_LENGTH]; save_area_list (); if (ch) chprintln (ch, "Saved zones:"); else log_string ("Saved zones:"); sprintf (buf, "None.\n\r"); for (pArea = area_first; pArea; pArea = pArea->next) { /* Builder must be assigned this area. */ if (ch && !IS_BUILDER (ch, pArea)) continue; /* Save changed areas. */ if (IS_SET (pArea->area_flags, AREA_CHANGED)) { save_area (pArea); sprintf (buf, "%24s - '%s'", pArea->name, pArea->file_name); if (ch) { chprint (ch, buf); chprintln (ch, ""); } else log_string (buf); REMOVE_BIT (pArea->area_flags, AREA_CHANGED); } } save_other_helps (ch); if (!str_cmp (buf, "None.\n\r")) { if (ch) chprint (ch, buf); else log_string ("None."); } return; } /* Save the area.lst file. */ /* ----------------------- */ if (!str_cmp (arg1, "list")) { save_area_list (); return; } if (!str_cmp (arg1, "clans")) { save_clans (); chprint (ch, "Clans saved."); return; } if (!str_cmp (arg1, "socials")) { save_social_table (); chprintln (ch, "Socials saved."); return; } if (!str_cmp (arg1, "commands")) { save_commands (); chprintln (ch, "Commands saved."); return; } if (!str_cmp (arg1, "skills")) { save_skills (); chprintln (ch, "Skills saved."); return; } if (!str_cmp (arg1, "groups")) { save_groups (); chprintln (ch, "Groups saved."); return; } if (!str_cmp (arg1, "races")) { save_races (); chprintln (ch, "Races saved."); return; } if (!str_cmp (arg1, "classes")) { save_classes (); chprintln (ch, "Classes saved."); return; } /* Save area being edited, if authorized. */ /* -------------------------------------- */ if (!str_cmp (arg1, "area")) { if (!ch || !ch->desc) return; /* Is character currently editing. */ if (ch->desc->editor == ED_NONE) { chprintln (ch, "You are not editing an area, " "therefore an area vnum is required."); return; } /* Find the area to save. */ switch (ch->desc->editor) { case ED_AREA: pArea = (AREA_DATA *) ch->desc->pEdit; break; case ED_ROOM: pArea = ch->in_room->area; break; case ED_OBJECT: pArea = ((OBJ_INDEX_DATA *) ch->desc->pEdit)->area; break; case ED_MOBILE: pArea = ((MOB_INDEX_DATA *) ch->desc->pEdit)->area; break; case ED_HELP: chprint (ch, "Grabando area : "); save_other_helps (ch); return; default: pArea = ch->in_room->area; break; } if (!IS_BUILDER (ch, pArea)) { chprintln (ch, "You are not a builder for this area."); return; } save_area_list (); save_area (pArea); REMOVE_BIT (pArea->area_flags, AREA_CHANGED); chprintln (ch, "Area saved."); return; } /* Show correct syntax. */ /* -------------------- */ if (ch) do_asave (ch, ""); return; }