/************************************************************************* * 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. */ #if defined(macintosh) #include <types.h> #else #include <sys/types.h> #endif #include <ctype.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #include "merc.h" #include "utils.h" #include "olc.h" #include "tables.h" /* * 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: find_mprog_type Purpose: Returns the name of a trigger type ****************************************************************************/ char *find_mprog_type(int type) { switch (type) { case TRIG_ACT: return "ACT"; case TRIG_SPEECH: return "SPEECH"; case TRIG_RANDOM: return "RANDOM"; case TRIG_FIGHT: return "FIGHT"; case TRIG_HPCNT: return "HPCNT"; case TRIG_DEATH: return "DEATH"; case TRIG_ENTRY: return "ENTRY"; case TRIG_GREET: return "GREET"; case TRIG_GRALL: return "GRALL"; case TRIG_GIVE: return "GIVE"; case TRIG_BRIBE: return "BRIBE"; case TRIG_KILL: return "KILL"; case TRIG_DELAY: return "DELAY"; case TRIG_SURR: return "SURRENDER"; case TRIG_EXIT: return "EXIT"; case TRIG_EXALL: return "EXALL"; default: return "ERROR"; } } /***************************************************************************** Name: fix_string Purpose: Returns a string without \r and ~. ****************************************************************************/ char *fix_string(const char *str) { static char strfix[MAX_STRING_LENGTH]; int i; int o; if (str == NULL) return '\0'; for (o = i = 0; i == 0 || str[i + o - 1] != '\0'; i++) { while (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; if ((fp = fopen("area.lst", "w")) == NULL) { bug("Save_area_list: fopen", 0); perror("area.lst"); } else { /* * Add any help files that need to be loaded at * startup to this section. */ fprintf(fp, "help.are\n"); fprintf(fp, "mobprog.prg\n"); fprintf(fp, "social.are\n"); for (pArea = area_first; pArea; pArea = pArea->next) { fprintf(fp, "%s\n", pArea->file_name); } fprintf(fp, "$\n"); fclose(fp); } return; } /* * ROM OLC * Used in save_mobile and save_object below. Writes * flags on the form fread_flag reads. * * buf[] must hold at least 32+1 characters. * * -- Hugin */ char *fwrite_flag(long flags, char buf[]) { char offset; char *cp; buf[0] = '\0'; if (flags == 0) { strcpy(buf, "0"); return buf; } /* 32 -- number of bits in a long */ for (offset = 0, cp = buf; offset < 32; offset++) if (flags & ((long) 1 << offset)) { if (offset <= 'Z' - 'A') *(cp++) = 'A' + offset; else *(cp++) = 'a' + offset - ('Z' - 'A' + 1); } *cp = '\0'; return buf; } /***************************************************************************** Name: save_race Purpose: Save one race entry to the race file. Called by: save_races (below). ****************************************************************************/ void save_race(FILE * fp, RACE_DATA *pRace) { int value; char buf[MAX_STRING_LENGTH]; fprintf( fp,"Name %s~\n", fix_string(pRace->name) ); fprintf( fp,"Who %s~\n", fix_string(pRace->who_name) ); fprintf( fp,"Gen %s~\n", fix_string(pRace->gen_name) ); fprintf( fp,"PC %d\n", pRace->pc_race ); fprintf( fp,"Act %s\n", fwrite_flag(pRace->act, buf) ); fprintf( fp,"Aff %s\n", fwrite_flag(pRace->aff, buf) ); fprintf( fp,"Off %s\n", fwrite_flag(pRace->off, buf) ); fprintf( fp,"Imm %s\n", fwrite_flag(pRace->imm, buf) ); fprintf( fp,"Res %s\n", fwrite_flag(pRace->res, buf) ); fprintf( fp,"Vuln %s\n", fwrite_flag(pRace->vuln, buf) ); fprintf( fp,"Form %s\n", fwrite_flag(pRace->form, buf) ); fprintf( fp,"Parts %s\n", fwrite_flag(pRace->parts, buf) ); fprintf( fp,"Sex %d\n", pRace->sex ); fprintf( fp,"Size %d\n", pRace->size ); fprintf( fp,"Min %d\n", pRace->min_level ); fprintf( fp,"Max %d\n", pRace->max_level ); fprintf( fp,"Version %d\n", pRace->version ); fprintf( fp,"Lifespan %d\n", pRace->lifespan ); fprintf( fp,"Points %d\n", pRace->points ); fprintf( fp,"Stats "); for (value = 0; value < MAX_STATS; value++) fprintf( fp, "%d ", pRace->stats[value]); fprintf( fp,"\nSenses "); for (value = 0; value < MAX_SENSES; value++) fprintf( fp, "%d ", pRace->senses[value]); fprintf( fp,"\n"); for (value = 0; value < MAX_RACE_SKILLS; value++) if ( pRace->skills[value] != NULL ) fprintf( fp, "Skill '%s'\n", pRace->skills[value] ); else continue; for (value = 0; value < MAX_RACE_FEEDS; value++) fprintf( fp, "Feeds '%s'\n" , pRace->feeds[value] != NULL ? pRace->feeds[value] : "" ); fprintf( fp,"End\n"); return; } /***************************************************************************** Name: save_races Purpose: Save all the races, Noah's Arc style. Called by: asave and whatnot. ****************************************************************************/ void save_races() { RACE_DATA *pRace; FILE *fp; if ((fp = fopen(RACE_LIST, "w")) == NULL) { perror(RACE_LIST); exit(1); } for (pRace = race_first; pRace != NULL; pRace = pRace->next) { if ( !pRace->deleted ) save_race( fp, pRace ); } fprintf( fp, "$\n" ); fclose( fp ); 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) { MPROG_LIST *pMprog; char buf[MAX_STRING_LENGTH]; 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", pMobIndex->race->name); fprintf(fp, "%s ", fwrite_flag(pMobIndex->act, buf)); fprintf(fp, "%s ", fwrite_flag(pMobIndex->affected_by, buf)); fprintf(fp, "%d %d\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_flag(pMobIndex->off_flags, buf)); fprintf(fp, "%s ", fwrite_flag(pMobIndex->imm_flags, buf)); fprintf(fp, "%s ", fwrite_flag(pMobIndex->res_flags, buf)); fprintf(fp, "%s\n", fwrite_flag(pMobIndex->vuln_flags, buf)); 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_flag(pMobIndex->form, buf)); fprintf(fp, "%s ", fwrite_flag(pMobIndex->parts, buf)); fprintf(fp, "%s ", size_table[pMobIndex->size].name); fprintf(fp, "%s\n", ((pMobIndex->material[0] != '\0') ? pMobIndex-> material : "unknown")); for (pMprog = pMobIndex->mprogs; pMprog; pMprog = pMprog->next) { fprintf(fp, "M %s", mprog_type_name(pMprog->trig_type)); fprintf(fp, "%ld ", pMprog->vnum); fprintf(fp, "%s~\n", 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) { long 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))) if (!pMob->deleted) 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; char buf[MAX_STRING_LENGTH]; 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_flag(pObjIndex->extra_flags, buf)); fprintf(fp, "%s\n", fwrite_flag(pObjIndex->wear_flags, buf)); /* * 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_flag(pObjIndex->value[0], buf)); fprintf(fp, "%s ", fwrite_flag(pObjIndex->value[1], buf)); fprintf(fp, "%s ", fwrite_flag(pObjIndex->value[2], buf)); fprintf(fp, "%s ", fwrite_flag(pObjIndex->value[3], buf)); fprintf(fp, "%s\n", fwrite_flag(pObjIndex->value[4], buf)); break; case ITEM_LIGHT: fprintf(fp, "0 0 %d 0 0\n", pObjIndex->value[2] < 1 ? 999 /* infinite */ : pObjIndex->value[2]); break; case ITEM_MONEY: fprintf(fp, "%d %d 0 0 0\n", pObjIndex->value[0], pObjIndex->value[1]); break; case ITEM_DRINK_CON: fprintf(fp, "%d %d '%s' %d 0\n", pObjIndex->value[0], pObjIndex->value[1], liq_table[pObjIndex->value[2]].liq_name, pObjIndex->value[3]); break; case ITEM_BLOOD_CON: fprintf(fp, "%d %d '%s' %d 0\n", pObjIndex->value[0], pObjIndex->value[1], liq_table[pObjIndex->value[2]].liq_name, pObjIndex->value[3]); break; case ITEM_FOUNTAIN: fprintf(fp, "%d %d '%s' 0 0\n", pObjIndex->value[0], pObjIndex->value[1], liq_table[pObjIndex->value[2]].liq_name); break; case ITEM_CONTAINER: fprintf(fp, "%d %s %d %d %d\n", pObjIndex->value[0], fwrite_flag(pObjIndex->value[1], buf), pObjIndex->value[2], pObjIndex->value[3], pObjIndex->value[4]); break; case ITEM_FOOD: fprintf(fp, "%d %d 0 %s 0\n", pObjIndex->value[0], pObjIndex->value[1], fwrite_flag(pObjIndex->value[3], buf)); break; case ITEM_PORTAL: fprintf(fp, "%d %s %s %d 0\n", pObjIndex->value[0], fwrite_flag(pObjIndex->value[1], buf), fwrite_flag(pObjIndex->value[2], buf), pObjIndex->value[3]); break; case ITEM_FURNITURE: fprintf(fp, "%d %d %s %d %d\n", pObjIndex->value[0], pObjIndex->value[1], fwrite_flag(pObjIndex->value[2], buf), pObjIndex->value[3], pObjIndex->value[4]); break; case ITEM_WEAPON: fprintf(fp, "%s %d %d %s %s\n", weapon_name(pObjIndex->value[0]), pObjIndex->value[1], pObjIndex->value[2], attack_table[pObjIndex->value[3]].name, fwrite_flag(pObjIndex->value[4], buf)); break; case ITEM_ARMOR: fprintf(fp, "%d %d %d %d %d\n", pObjIndex->value[0], pObjIndex->value[1], pObjIndex->value[2], pObjIndex->value[3], pObjIndex->value[4]); break; case ITEM_PILL: case ITEM_POTION: case ITEM_SCROLL: fprintf(fp, "%d '%s' '%s' '%s' '%s'\n", pObjIndex->value[0] > 0 ? 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, "%d ", pObjIndex->value[0]); fprintf(fp, "%d ", pObjIndex->value[1]); fprintf(fp, "%d '%s' 0\n", pObjIndex->value[2], pObjIndex->value[3] != -1 ? skill_table[pObjIndex->value[3]].name : 0); break; } fprintf(fp, "%d ", pObjIndex->level); fprintf(fp, "%d ", pObjIndex->weight); fprintf(fp, "%d ", pObjIndex->cost); fprintf(fp, "%d ", pObjIndex->timer); 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) { fprintf(fp, "A\n%d %d\n", pAf->location, pAf->modifier); } 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) { long 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))) if( !pObj->deleted ) 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 && !pRoomIndex->deleted) { 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, "%d ", 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 && !pExit->u1.to_room->deleted) { int locks = 0; 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; if (IS_SET(pExit->rs_flags, EX_ISDOOR) && (IS_SET(pExit->rs_flags, EX_HIDDEN))) locks = 5; 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 %d %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 > 0) fprintf(fp, "C %s~\n", clan_table[pRoomIndex->clan].name); 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 && !pMobIndex->deleted) { #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 && !pRoomIndex->deleted) { for (door = 0; door < MAX_DIR; door++) { if ((pExit = pRoomIndex->exit[door]) && pExit->u1.to_room && !pExit->u1.to_room->deleted && (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 && !pRoom->deleted) { for (pReset = pRoom->reset_first; pReset; pReset = pReset->next) { switch (pReset->command) { default: bug("Save_resets: bad command %c.", pReset->command); break; case 'M': pLastMob = get_mob_index(pReset->arg1); if (!pLastMob->deleted) { pRoom = get_room_index(pReset->arg3); if (!pRoom->deleted) { fprintf(fp, "M 0 %d %d %d %d\n", pReset->arg1, pReset->arg2, pReset->arg3, pReset->arg4); } } break; case 'O': pLastObj = get_obj_index(pReset->arg1); if (!pLastObj->deleted) { pRoom = get_room_index(pReset->arg3); if (!pRoom->deleted) { fprintf(fp, "O 0 %d 0 %d\n", pReset->arg1, pReset->arg3); } } break; case 'P': pLastObj = get_obj_index(pReset->arg1); if (!pLastObj->deleted) { pLastObj = get_obj_index(pReset->arg3); if (!pLastObj->deleted) { fprintf(fp, "P 0 %d %d %d %d\n", pReset->arg1, pReset->arg2, pReset->arg3, pReset->arg4); } } break; case 'G': /* bad mobile handled at load time */ pLastObj = get_obj_index(pReset->arg1); if (!pLastObj->deleted) { fprintf(fp, "G 0 %d 0\n", pReset->arg1); if (!pLastMob) { sprintf(buf, "Save_resets: !NO_MOB! in [%s]", pArea->file_name); bug(buf, 0); } } break; case 'E': pLastObj = get_obj_index(pReset->arg1); if (!pLastObj->deleted) { fprintf(fp, "E 0 %d 0 %d\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 %d %d\n", pReset->arg1, pReset->arg2); break; } } } /* 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 && !pMobIndex->deleted) { pShopIndex = pMobIndex->pShop; fprintf(fp, "%d ", 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; } /***************************************************************************** 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; fclose(fpReserve); if (!(fp = fopen(pArea->file_name, "w"))) { bug("Open_area: fopen", 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, "Version %d\n", 1); 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); fprintf(fp, "#$\n"); fclose(fp); fpReserve = fopen(NULL_FILE, "r"); return; } /***************************************************************************** Name: do_asave Purpose: Entry point for saving area data. Called by: interpreter(interp.c) ****************************************************************************/ void do_asave(CHAR_DATA * ch, char *argument) { char arg1[MAX_INPUT_LENGTH]; AREA_DATA *pArea; FILE *fp; int value; fp = NULL; if (!ch) { /* Do an autosave */ bool changed = FALSE; for (pArea = area_first; pArea; pArea = pArea->next) { if (IS_SET(pArea->area_flags, AREA_CHANGED)) { save_area(pArea); REMOVE_BIT(pArea->area_flags, AREA_CHANGED); changed = TRUE; } } if (changed) save_area_list(); return; } smash_tilde(argument); strcpy(arg1, argument); if (arg1[0] == '\0') { send_to_char("Syntax:\n\r", ch); send_to_char(" asave <vnum> - saves a particular area\n\r", ch); send_to_char(" asave world - saves everything\n\r", ch); send_to_char(" asave list - saves the area.lst file\n\r", ch); send_to_char(" asave area - saves the area being edited\n\r", ch); send_to_char(" asave changed - saves all changed zones\n\r", ch); send_to_char(" asave helps - saves the help files\n\r", ch); send_to_char(" asave races - saves the races\n\r", ch); send_to_char("\n\r", ch); return; } if (IS_NPC(ch)) return; /* Snarf the value (which need not be numeric). */ value = atoi(arg1); if (!(pArea = get_area_data(value)) && is_number(arg1)) { send_to_char("That area does not exist.\n\r", ch); return; } /* Save area of given vnum. */ /* ------------------------ */ if (is_number(arg1)) { if (!IS_BUILDER(ch, pArea)) { send_to_char("You are not a builder for this area.\n\r", ch); return; } save_area_list(); save_area(pArea); return; } if (!str_cmp("world", arg1)) { save_races(); save_area_list(); save_helps(); for (pArea = area_first; pArea; pArea = pArea->next) { if (!IS_BUILDER(ch, pArea)) continue; save_area(pArea); REMOVE_BIT(pArea->area_flags, AREA_CHANGED); } send_to_char("You saved the world.\n\r", ch); return; } /* Save changed areas, only authorized areas. */ /* ------------------------------------------ */ if (!str_cmp("changed", arg1)) { char buf[MAX_INPUT_LENGTH]; save_area_list(); send_to_char("Saved zones:\n\r", ch); sprintf(buf, "None.\n\r"); for (pArea = area_first; pArea; pArea = pArea->next) { /* Builder must be assigned this area. */ if (!IS_BUILDER(ch, pArea)) continue; /* Save changed areas. */ if (IS_SET(pArea->area_flags, AREA_CHANGED)) { save_area(pArea); sprintf(buf, "%24s - '%s'\n\r", pArea->name, pArea->file_name); send_to_char(buf, ch); REMOVE_BIT(pArea->area_flags, AREA_CHANGED); } } if (!str_cmp(buf, "None.\n\r")) send_to_char(buf, ch); return; } /* Save the area.lst file. */ /* ----------------------- */ if (!str_cmp(arg1, "list")) { save_area_list(); return; } /* Save area being edited, if authorized. */ /* -------------------------------------- */ if (!str_cmp(arg1, "area")) { /* Is character currently editing. */ if (ch->desc->editor == 0) { send_to_char("You are not editing an area, " "therefore an area vnum is required.\n\r", ch); 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; default: pArea = ch->in_room->area; break; } if (!IS_BUILDER(ch, pArea)) { send_to_char("You are not a builder for this area.\n\r", ch); return; } save_area_list(); save_area(pArea); REMOVE_BIT(pArea->area_flags, AREA_CHANGED); send_to_char("Area saved.\n\r", ch); return; } /* Save Races */ if (!str_cmp(arg1, "races")) { save_races(); send_to_char("Races Saved.\n\r", ch); return; } /* Save Help File */ if (!str_cmp(arg1, "helps")) { save_helps(); send_to_char("Helps Saved.\n\r", ch); return; } /* Show correct syntax. */ /* -------------------- */ do_asave(ch, ""); return; } void save_helps() { HELP_DATA *pHelp; FILE *fp; if (!(fp = fopen("help.are", "w"))) { bug("Open_help: fopen", 0); perror("help.are"); } fprintf(fp, "#HELPS\n"); for (pHelp = help_first; pHelp != NULL; pHelp = pHelp->next) { if (pHelp->delete) continue; fprintf(fp, "%d %s~\n\n%s~\n", pHelp->level, pHelp->keyword, fix_string(pHelp->text)); } fprintf(fp, "0 $~\n\n#$\n"); fclose(fp); return; } void save_mobprogs(FILE * fp, MPROG_CODE * pMprog) { int i; fprintf(fp, "#MOBPROGS\n"); for (i = 0; i < MAX_VNUM; i++) { if ((pMprog = get_mprog_index(i)) != NULL) fprintf(fp, "#%d\n%s~\n", i, fix_string(pMprog->code)); } fprintf(fp, "#0\n\n"); return; } void save_mobprog(MPROG_CODE * pMcode) { FILE *fp; fclose(fpReserve); if (!(fp = fopen("mobprog.prg", "w"))) { bug("Open_help: fopen", 0); perror("mobprog.prg"); } save_mobprogs(fp, pMcode); fprintf(fp, "#$\n"); fclose(fp); fpReserve = fopen(NULL_FILE, "r"); return; } void do_mpsave(CHAR_DATA * ch, char *argument) { MPROG_CODE *pMcode; FILE *fp; if (!IS_IMMORTAL(ch)) { send_to_char("Huh?\n\r", ch); return; } fp = NULL; if (ch->desc->editor == 0) { send_to_char("You are not editing a mobprogram code\n\r", ch); return; } pMcode = (MPROG_CODE *) ch->desc->pEdit; save_mobprog(pMcode); send_to_char("Code saved.\n\r", ch); return; }