/* $Id: db_area.c,v 1.666 2004/09/20 10:50:19 shrike Exp $ */ /************************************************************************************ * Copyright 2004 Astrum Metaphora consortium * * * * Licensed under the Apache License, Version 2.0 (the "License"); * * you may not use this file except in compliance with the License. * * You may obtain a copy of the License at * * * * http://www.apache.org/licenses/LICENSE-2.0 * * * * Unless required by applicable law or agreed to in writing, software * * distributed under the License is distributed on an "AS IS" BASIS, * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * * See the License for the specific language governing permissions and * * limitations under the License. * * * ************************************************************************************/ /************************************************************************************ * ANATOLIA 2.1 is copyright 1996-1997 Serdar BULUT, Ibrahim CANPUNAR * * ANATOLIA has been brought to you by ANATOLIA consortium * * Serdar BULUT {Chronos} bulut@rorqual.cc.metu.edu.tr * * Ibrahim Canpunar {Asena} canpunar@rorqual.cc.metu.edu.tr * * Murat BICER {KIO} mbicer@rorqual.cc.metu.edu.tr * * D.Baris ACAR {Powerman} dbacar@rorqual.cc.metu.edu.tr * * By using this code, you have agreed to follow the terms of the * * ANATOLIA license, in the file Anatolia/anatolia.licence * ***********************************************************************************/ /************************************************************************************ * Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, * * Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe. * * * * Merc Diku Mud improvments 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 * * benefitting. We hope that you share your changes too. What goes * * around, comes around. * ************************************************************************************/ /************************************************************************************ * ROM 2.4 is copyright 1993-1995 Russ Taylor * * ROM has been brought to you by the ROM consortium * * Russ Taylor (rtaylor@pacinfo.com) * * Gabrielle Taylor (gtaylor@pacinfo.com) * * Brian Moore (rom@rom.efn.org) * * By using this code, you have agreed to follow the terms of the * * ROM license, in the file Rom24/doc/rom.license * *************************************************************************************/ /************************************************************************************ * Copyright (c) 1998 fjoe <fjoe@iclub.nsu.ru> * * All rights reserved. * * * * Redistribution and use in source and binary forms, with or without * * modification, are permitted provided that the following conditions * * are met: * * 1. Redistributions of source code must retain the above copyright * * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * * notice, this list of conditions and the following disclaimer in the * * documentation and/or other materials provided with the distribution. * * * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * * SUCH DAMAGE. * ************************************************************************************/ #include <stdio.h> #include <string.h> #include <stdlib.h> #include "typedef.h" #include "merc.h" #include "obj_prog.h" #include "db.h" #include "olc/olc.h" DECLARE_DBLOAD_FUN(load_area); DECLARE_DBLOAD_FUN(load_areadata); DECLARE_DBLOAD_FUN(load_helps); DECLARE_DBLOAD_FUN(load_old_mob); DECLARE_DBLOAD_FUN(load_mobiles); DECLARE_DBLOAD_FUN(load_mobprogs); DECLARE_DBLOAD_FUN(load_objprogs); DECLARE_DBLOAD_FUN(load_roomprogs); DECLARE_DBLOAD_FUN(load_old_obj); DECLARE_DBLOAD_FUN(load_objects); DECLARE_DBLOAD_FUN(load_resets); DECLARE_DBLOAD_FUN(load_rooms); DECLARE_DBLOAD_FUN(load_shops); DECLARE_DBLOAD_FUN(load_omprogs); DECLARE_DBLOAD_FUN(load_olimits); DECLARE_DBLOAD_FUN(load_specials); DECLARE_DBLOAD_FUN(load_practicers); DECLARE_DBLOAD_FUN(load_resetmsg); DECLARE_DBLOAD_FUN(load_aflag); extern int top_oprog_index; extern int top_rprog_index; DBFUN db_load_areas[] = { { "AREA", load_area}, { "AREADATA", load_areadata}, { "HELPS", load_helps}, { "MOBOLD", load_old_mob}, { "MOBILES", load_mobiles}, { "MOBPROGS", load_mobprogs}, { "OBJPROGS", load_objprogs}, { "ROOMPROGS", load_roomprogs}, { "OBJOLD", load_old_obj}, { "OBJECTS", load_objects}, { "RESETS", load_resets}, { "ROOMS", load_rooms}, { "SHOPS", load_shops}, { "OMPROGS", load_omprogs}, { "OLIMITS", load_olimits}, { "SPECIALS", load_specials}, { "PRACTICERS", load_practicers}, { "RESETMESSAGE", load_resetmsg}, { "FLAG", load_aflag}, { NULL} }; AREA_DATA * area_current; const HELP_DATA * help_greeting; static int slot_lookup (int slot); static void convert_mobile (MOB_INDEX_DATA *pMobIndex); DBINIT_FUN(init_area) { area_current = NULL; } /* * Snarf an 'area' header line. */ DBLOAD_FUN(load_area) { AREA_DATA *pArea; pArea = alloc_perm(sizeof(*pArea)); pArea->reset_first = NULL; pArea->reset_last = NULL; pArea->help_first = NULL; pArea->help_last = NULL; free_string(fread_string(fp)); /* file name */ pArea->file_name = get_filename(filename); pArea->builders = str_empty; pArea->security = 9; pArea->vnum = top_area; pArea->name = fread_string(fp); pArea->mlname = NULL; fread_letter(fp);/* '{' */ pArea->min_level = fread_number(fp); pArea->max_level = fread_number(fp); fread_letter(fp);/* '}' */ pArea->credits = str_dup(fread_word(fp)); free_string(fread_string(fp)); pArea->min_vnum = fread_number(fp); pArea->max_vnum = fread_number(fp); pArea->age = 15; pArea->nplayer = 0; pArea->empty = FALSE; pArea->count = 0; pArea->resetmsg = NULL; pArea->flags = 0; pArea->explorable_rooms = 0; pArea->climat_type = fread_flags(fp); pArea->planet = fread_flags(fp); pArea->weather.weather_status = 0; pArea->weather.weather_delta = 0; pArea->weather.temperature = 0; pArea->weather.wind_direction = 0; pArea->weather.wind_speed = 0; pArea->weather.humidity = 0; if (area_first == NULL) area_first = pArea; if (area_last != NULL) area_last->next = pArea; area_last = pArea; pArea->next = NULL; area_current = pArea; top_area++; } /* OLC * Snarf an 'area' header line. Check this format. MUCH better. Add fields * too. * * #AREAFILE * Name { All } Locke Newbie School~ * Repop A teacher pops in the room and says, 'Repop coming!'~ * Recall 3001 * End */ DBLOAD_FUN(load_areadata) { AREA_DATA * pArea; char * word; bool fMatch; pArea = alloc_perm(sizeof(*pArea)); pArea->age = 15; pArea->nplayer = 0; pArea->file_name = get_filename(filename); pArea->builders = str_empty; pArea->vnum = top_area; pArea->name = str_dup("New Area"); pArea->mlname = NULL; pArea->security = 9; /* 9 -- Hugin */ pArea->min_vnum = 0; pArea->max_vnum = 0; pArea->flags = 0; pArea->min_level = 0; pArea->max_level = 0; pArea->resetmsg = NULL; pArea->version = 0.0; pArea->climat_type = 0; // For climat type pArea->planet = 0; pArea->weather.weather_status = 0; pArea->weather.weather_delta = 0; pArea->weather.temperature = 0; pArea->weather.wind_direction = 0; pArea->weather.wind_speed = 0; pArea->weather.humidity = 0; pArea->clan_owner = NULL; pArea->conq_enabled = FALSE; pArea->time_owned = 0; pArea->explore_required = 0; pArea->prev_clan_owner = NULL; pArea->guards_left = 0; pArea->curr_attack_time = 0; pArea->curr_defence_time = 0; pArea->prev_lock_time = 0; pArea->areaguard_rank = 0; /* pArea->recall = ROOM_VNUM_TEMPLE; ROM OLC */ for (; ;) { word = feof(fp) ? "End" : fread_word(fp); fMatch = FALSE; switch (UPPER(word[0])) { case 'B': SKEY("Builders", pArea->builders); break; case 'C': KEY("Clan", pArea->clan, fread_clan(fp)); SKEY("Credits", pArea->credits); KEY("Climat", pArea->climat_type, fread_fstring(climat_flags, fp)); KEY("ConqEnabled", pArea->conq_enabled, fread_number(fp)); break; case 'E': KEY("ExploreReq", pArea->explore_required, fread_number(fp)); if (!str_cmp(word, "End")) { fMatch = TRUE; if (mlstr_null(pArea->mlname)) pArea->mlname = mlstr_new(pArea->name); if (area_first == NULL) area_first = pArea; if (area_last != NULL) area_last->next = pArea; area_last = pArea; pArea->next = NULL; area_current = pArea; top_area++; return; } break; case 'F': KEY("Flags", pArea->flags, fread_fstring(area_flags, fp)); break; case 'G': KEY("GuardCount", pArea->max_guard_count,fread_number(fp)); if (!str_cmp(word, "GuardVNUMs")) { int i; for (i = 0; i < pArea->max_guard_count; ++i) pArea->guard_room_vnums[i] = fread_number(fp); } break; case 'L': if (!str_cmp(word, "LevelRange")) { pArea->min_level = fread_number(fp); pArea->max_level = fread_number(fp); } break; case 'M': MLSKEY("MLName", pArea->mlname); break; case 'N': SKEY("Name", pArea->name); break; case 'R': MLSKEY("ResetMessage", pArea->resetmsg); break; case 'S': KEY("Security", pArea->security, fread_number(fp)); break; case 'P': KEY("Planet", pArea->planet, fread_fstring(planet_flags, fp)); break; case 'V': if (!str_cmp(word, "VNUMs")) { pArea->min_vnum = fread_number(fp); pArea->max_vnum = fread_number(fp); } else if (!str_cmp(word, "Version")) { pArea->version = fread_fnumber(fp); } break; } } } /* * Snarf a help section. */ DBLOAD_FUN(load_helps) { HELP_DATA *pHelp; int level; const char *keyword; if (!area_current) { /* OLC */ log("load_helps: no #AREA seen yet."); exit(1); } for (; ;) { level = fread_number(fp); keyword = fread_string(fp); if (keyword[0] == '$') break; pHelp = help_new(); pHelp->level = level; pHelp->keyword = keyword; pHelp->text = mlstr_fread(fp); if (!str_cmp(pHelp->keyword, "greeting")) //if (!str_cmp(pHelp->keyword, "greeting_old")) help_greeting = pHelp; help_add(area_current, pHelp); } } /* * Snarf a mob section. old style */ DBLOAD_FUN(load_old_mob) { MOB_INDEX_DATA *pMobIndex; /* for race updating */ int race; char name[MAX_STRING_LENGTH]; if (!area_current) { /* OLC */ log("load_old_mob: no #AREA seen yet."); exit(1); } for (; ;) { int vnum; char letter; int iHash; int i; letter = fread_letter(fp); if (letter != '#') { log("load_old_mob: # not found."); exit(1); } vnum = fread_number(fp); if (vnum == 0) break; fBootDb = FALSE; if (get_mob_index(vnum)) { log_printf("load_old_mob: vnum %d duplicated.", vnum); exit(1); } fBootDb = TRUE; pMobIndex = alloc_perm(sizeof(*pMobIndex)); for (i = 0; i < MAX_DAM; i++) pMobIndex->resists[i] = 0; pMobIndex->immunes = 0; pMobIndex->short_descr = NULL; pMobIndex->long_descr = NULL; pMobIndex->description = NULL; pMobIndex->listen_data = NULL; pMobIndex->vnum = vnum; pMobIndex->name = fread_string(fp); pMobIndex->short_descr = mlstr_fread(fp); pMobIndex->long_descr = mlstr_fread(fp); pMobIndex->description = mlstr_fread(fp); pMobIndex->act = fread_flags(fp) | ACT_NPC; pMobIndex->affected_by = fread_flags(fp); pMobIndex->practicer = 0; pMobIndex->pShop = NULL; pMobIndex->alignment = fread_number(fp); letter = fread_letter(fp); pMobIndex->level = fread_number(fp); /* * The unused stuff is for imps who want to use the old-style * stats-in-files method. */ fread_number(fp); /* Unused */ fread_number(fp); /* Unused */ fread_number(fp); /* Unused */ /* 'd' */ fread_letter(fp); /* Unused */ fread_number(fp); /* Unused */ /* '+' */ fread_letter(fp); /* Unused */ fread_number(fp); /* Unused */ fread_number(fp); /* Unused */ /* 'd' */ fread_letter(fp); /* Unused */ fread_number(fp); /* Unused */ /* '+' */ fread_letter(fp); /* Unused */ fread_number(fp); /* Unused */ pMobIndex->wealth = fread_number(fp)/20; /* xp can't be used! */ fread_number(fp); /* Unused */ pMobIndex->start_pos = fread_number(fp); /* Unused */ pMobIndex->default_pos = fread_number(fp); /* Unused */ if (pMobIndex->start_pos < POS_SLEEPING) pMobIndex->start_pos = POS_STANDING; if (pMobIndex->default_pos < POS_SLEEPING) pMobIndex->default_pos = POS_STANDING; /* * Back to meaningful values. */ pMobIndex->sex = fread_number(fp); /* compute the race BS */ one_argument(pMobIndex->name, name, sizeof(name)); if (name[0] == '\0' || (race = rn_lookup(name)) == 0) { race_t *r; /* fill in with blanks */ pMobIndex->race = rn_lookup("human"); r = RACE(pMobIndex->race); pMobIndex->affected_by = pMobIndex->affected_by | r->aff; pMobIndex->off_flags = OFF_DODGE | OFF_DISARM | OFF_TRIP | ASSIST_VNUM; pMobIndex->form = FORM_EDIBLE | FORM_SENTIENT | FORM_BIPED | FORM_MAMMAL; pMobIndex->parts = PART_HEAD | PART_ARMS | PART_LEGS | PART_HEART | PART_BRAINS | PART_GUTS; pMobIndex->pcnt = 6; } else { race_t *r = RACE(race); pMobIndex->race = race; pMobIndex->affected_by = pMobIndex->affected_by | r->aff; pMobIndex->off_flags = OFF_DODGE | OFF_DISARM | OFF_TRIP | ASSIST_RACE | r->off; pMobIndex->immunes = r->immunes; for (i = 0; i < MAX_DAM; i++) pMobIndex->resists[i] = r->resists[i]; pMobIndex->form = r->form; pMobIndex->parts = r->parts; pMobIndex->pcnt = r->pcnt; } if (letter != 'S') { log_printf("load_old_mob: vnum %d non-S.", vnum); exit(1); } convert_mobile(pMobIndex); /* ROM OLC */ iHash = vnum % MAX_KEY_HASH; pMobIndex->next = mob_index_hash[iHash]; mob_index_hash[iHash] = pMobIndex; top_mob_index++; /* OLC */ top_vnum_mob = top_vnum_mob < vnum ? vnum : top_vnum_mob; vnum_check(area_current, vnum); /* OLC */ kill_table[URANGE(0, pMobIndex->level, MAX_LEVEL-2)].number++; } } /* * Load mobprogs section */ DBLOAD_FUN(load_mobprogs) { MPCODE *mpcode; if (area_current == NULL) { log("load_mobprogs: no #AREA seen yet."); exit(1); } for (; ;) { int vnum; const char *code; char letter; letter = fread_letter(fp); if (letter != '#') { log("load_mobprogs: # not found."); exit(1); } vnum = fread_number(fp); if (vnum == 0) break; if (mpcode_lookup(vnum) != NULL) { log_printf("load_mobprogs: vnum %d duplicated.", vnum); exit(1); } code = fread_string(fp); mpcode = mpcode_new(); mpcode->vnum = vnum; mpcode->code = code; mpcode_add(mpcode); } } /* * Snarf an obj section. old style */ DBLOAD_FUN(load_old_obj) { OBJ_INDEX_DATA *pObjIndex; if (!area_current) db_error("load_old_obj", "no #AREA seen yet."); for (; ;) { int vnum; char letter; int iHash; letter = fread_letter(fp); if (letter != '#') db_error("load_old_obj", "# not found."); vnum = fread_number(fp); if (vnum == 0) break; fBootDb = FALSE; if (get_obj_index(vnum)) { db_error("load_old_obj", "vnum %d duplicated.", vnum); exit(1); } fBootDb = TRUE; pObjIndex = alloc_perm(sizeof(*pObjIndex)); pObjIndex->short_descr = NULL; pObjIndex->description = NULL; pObjIndex->vnum = vnum; pObjIndex->reset_num = 0; pObjIndex->name = fread_string(fp); pObjIndex->short_descr = mlstr_fread(fp); pObjIndex->description = mlstr_fread(fp); /* Action description */ fread_string(fp); pObjIndex->material = str_dup("copper"); pObjIndex->item_type = fread_number(fp); pObjIndex->extra_flags = fread_flags(fp) | ITEM_OLDSTYLE; pObjIndex->wear_flags = fread_flags(fp); pObjIndex->value[0] = fread_number(fp); pObjIndex->value[1] = fread_number(fp); pObjIndex->value[2] = fread_number(fp); pObjIndex->value[3] = fread_number(fp); pObjIndex->value[4] = 0; pObjIndex->level = 0; pObjIndex->condition = 100; pObjIndex->weight = fread_number(fp); pObjIndex->cost = fread_number(fp); /* Unused */ /* Cost per day */ fread_number(fp); pObjIndex->limit = -1; pObjIndex->oprogs_old = NULL; if (pObjIndex->item_type == ITEM_WEAPON) if (is_name("two",pObjIndex->name) || is_name("two-handed",pObjIndex->name) || is_name("claymore",pObjIndex->name)) SET_BIT(pObjIndex->value[4], WEAPON_TWO_HANDS); for (; ;) { char letter; letter = fread_letter(fp); if (letter == 'A') { AFFECT_DATA *paf; paf = alloc_perm(sizeof(*paf)); paf->where = TO_OBJECT; paf->type = -1; paf->level = 20; /* RT temp fix */ paf->duration = -1; paf->location = fread_number(fp); paf->modifier = fread_number(fp); paf->bitvector = 0; SLIST_ADD(AFFECT_DATA, pObjIndex->affected, paf); top_affect++; } else if (letter == 'E') ed_fread(fp, &pObjIndex->ed); else { xungetc(letter, fp); break; } } /* fix armors */ if (pObjIndex->item_type == ITEM_ARMOR) { pObjIndex->value[1] = pObjIndex->value[0]; pObjIndex->value[2] = pObjIndex->value[1]; } /* * Translate spell "slot numbers" to internal "skill numbers." */ switch (pObjIndex->item_type) { case ITEM_PILL: case ITEM_POTION: case ITEM_SCROLL: pObjIndex->value[1] = slot_lookup(pObjIndex->value[1]); pObjIndex->value[2] = slot_lookup(pObjIndex->value[2]); pObjIndex->value[3] = slot_lookup(pObjIndex->value[3]); pObjIndex->value[4] = slot_lookup(pObjIndex->value[4]); break; case ITEM_STAFF: case ITEM_WAND: pObjIndex->value[3] = slot_lookup(pObjIndex->value[3]); break; } iHash = vnum % MAX_KEY_HASH; pObjIndex->next = obj_index_hash[iHash]; obj_index_hash[iHash] = pObjIndex; top_obj_index++; /* OLC */ top_vnum_obj = top_vnum_obj < vnum ? vnum : top_vnum_obj; vnum_check(area_current, vnum); /* OLC */ } } /* * Snarf a reset section. Adjust levels of ITEM_OLDSTYLE objects on the fly. * if loading an old-style area it's assumed that #SHOPS section * (if any) has already been parsed */ DBLOAD_FUN(load_resets) { MOB_INDEX_DATA *pLastMob = NULL; ROOM_INDEX_DATA *pLastRoom = NULL; if (area_current == NULL) { db_error("load_resets", "no #AREA seen yet."); return; } for (; ;) { RESET_DATA *pReset; ROOM_INDEX_DATA *pRoom; EXIT_DATA *pexit = NULL; char letter; OBJ_INDEX_DATA *pObj; if ((letter = fread_letter(fp)) == 'S') break; if (letter == '*') { fread_to_eol(fp); continue; } pReset = alloc_perm(sizeof(*pReset)); pReset->command = letter; /* if_flag */ fread_number(fp); pReset->arg1 = fread_number(fp); pReset->arg2 = fread_number(fp); pReset->arg3 = (letter == 'G' || letter == 'R') ? 0 : fread_number(fp); pReset->arg4 = (letter == 'P' || letter == 'M') ? fread_number(fp) : 0; fread_to_eol(fp); /* * Validate parameters. * We're calling the index functions for the side effect. */ switch (letter) { default: db_error("load_resets", "bad command '%c'.", letter); break; case 'M': if ((pLastMob = get_mob_index(pReset->arg1)) == NULL || (pRoom = get_room_index(pReset->arg3)) == NULL) break; new_reset(pRoom, pReset); pLastRoom = pRoom; break; case 'O': if ((pObj = get_obj_index(pReset->arg1)) == NULL || (pRoom = get_room_index(pReset->arg3)) == NULL) break; pObj->reset_num++; new_reset(pRoom, pReset); pLastRoom = pRoom; if (IS_SET(pObj->extra_flags, ITEM_OLDSTYLE)) { if (!pLastMob) { db_error("load_resets", "can't calculate obj level: " "no mob reset yet"); break; } pObj->level = pObj->level < 1 ? pLastMob->level : UMIN(pLastMob->level, pObj->level); } break; case 'P': { OBJ_INDEX_DATA *pObjTo; if ((pObj = get_obj_index(pReset->arg1)) == NULL || (pObjTo = get_obj_index(pReset->arg3)) == NULL) break; if (!pLastRoom) { db_error("load_resets", "room undefined"); break; } new_reset(pLastRoom, pReset); pObj->reset_num++; if (IS_SET(pObj->extra_flags, ITEM_OLDSTYLE)) pObj->level = pObj->level < 1 ? pObjTo->level : UMIN(pObjTo->level, pObj->level); break; } case 'G': case 'E': if ((pObj = get_obj_index(pReset->arg1)) == NULL) break; if (!pLastRoom) { db_error("load_resets", "room undefined"); break; } pObj->reset_num++; new_reset(pLastRoom, pReset); if (IS_SET(pObj->extra_flags, ITEM_OLDSTYLE)) { if (!pLastMob) { db_error("load_resets", "can't calculate obj level: " "no mob reset yet"); break; } if (pLastMob->pShop) { switch (pObj->item_type) { default: pObj->level = UMAX(0, pObj->level); break; case ITEM_PILL: case ITEM_POTION: pObj->level = UMAX(5, pObj->level); break; case ITEM_SCROLL: case ITEM_ARMOR: case ITEM_WEAPON: pObj->level = UMAX(10, pObj->level); break; case ITEM_WAND: case ITEM_TREASURE: pObj->level = UMAX(15, pObj->level); break; case ITEM_STAFF: pObj->level = UMAX(20, pObj->level); break; } } else pObj->level = pObj->level < 1 ? pLastMob->level : UMIN(pObj->level, pLastMob->level); } break; case 'D': if ((pRoom = get_room_index(pReset->arg1)) == NULL) break; if (pReset->arg2 < 0 || pReset->arg2 >= MAX_DIR || (pexit = pRoom->exit[pReset->arg2]) == NULL || !IS_SET(pexit->rs_flags, EX_ISDOOR)) { db_error("load_resets", "'D': exit %d not door.", pReset->arg2); break; } switch (pReset->arg3) { default: db_error("load_resets", "'D': bad 'locks': %d.", pReset->arg3); /* FALLTHRU */ case 0: break; case 1: SET_BIT(pexit->rs_flags, EX_CLOSED); SET_BIT(pexit->exit_info, EX_CLOSED); break; case 2: SET_BIT(pexit->rs_flags, EX_CLOSED | EX_LOCKED); SET_BIT(pexit->exit_info, EX_CLOSED | EX_LOCKED); break; } break; case 'R': if ((pRoom = get_room_index(pReset->arg1)) == NULL) break; if (pReset->arg2 < 0 || pReset->arg2 > MAX_DIR) { db_error("load_resets", "'R': bad exit %d.", pReset->arg2); break; } if (pRoom) new_reset(pRoom, pReset); break; } } } /* * Snarf a room section. */ DBLOAD_FUN(load_rooms) { ROOM_INDEX_DATA *pRoomIndex; if (area_current == NULL) db_error("load_rooms", "no #AREA seen yet."); for (; ;) { int vnum; char letter; int door; int iHash; //bool explorable = FALSE; letter = fread_letter(fp); if (letter != '#') { log("load_rooms: # not found."); exit(1); } vnum = fread_number(fp); if (vnum == 0) break; fBootDb = FALSE; if (get_room_index(vnum)) { db_error("load_rooms", "vnum %d duplicated.", vnum); exit(1); } fBootDb = TRUE; pRoomIndex = alloc_perm(sizeof(*pRoomIndex)); pRoomIndex->name = NULL; pRoomIndex->description = NULL; pRoomIndex->owner = str_dup(str_empty); pRoomIndex->people = NULL; pRoomIndex->contents = NULL; pRoomIndex->ed = NULL; pRoomIndex->history = NULL; pRoomIndex->area = area_current; pRoomIndex->vnum = vnum; pRoomIndex->name = mlstr_fread(fp); pRoomIndex->description = mlstr_fread(fp); pRoomIndex->space = fread_number(fp); if (area_current->version < 1.04) pRoomIndex->space = 255; pRoomIndex->room_flags = fread_flags(fp); pRoomIndex->sector_type = fread_fword(sector_types, fp); pRoomIndex->light = 0; for (door = 0; door <= 5; door++) pRoomIndex->exit[door] = NULL; /* defaults */ pRoomIndex->heal_rate = 100; pRoomIndex->mana_rate = 100; pRoomIndex->affected = NULL; pRoomIndex->affected_by = 0; pRoomIndex->aff_next = NULL; for (; ;) { letter = fread_letter(fp); if (letter == 'S') break; if (letter == 'H') /* healing room */ pRoomIndex->heal_rate = fread_number(fp); else if (letter == 'M') /* mana room */ pRoomIndex->mana_rate = fread_number(fp); else if (letter == 'D') { EXIT_DATA *pexit; int locks; //explorable = TRUE; door = fread_number(fp); if (door < 0 || door > 5) { log_printf("load_rooms: vnum %d has " "bad door number.", vnum); exit(1); } pexit = alloc_perm(sizeof(*pexit)); pexit->description = mlstr_fread(fp); pexit->keyword = fread_string(fp); pexit->exit_info = 0; pexit->rs_flags = 0; /* OLC */ locks = fread_flags(fp); pexit->key = fread_number(fp); pexit->to_room.vnum = fread_number(fp); pexit->orig_door = door; /* OLC */ if (area_current->version < 1.01) pexit->size = SIZE_GARGANTUAN_MAX; else pexit->size = fread_number(fp); if (!IS_SET(locks, EX_BITVAL)) { switch (locks) { case 1: pexit->exit_info = EX_ISDOOR; pexit->rs_flags = EX_ISDOOR; break; case 2: pexit->exit_info = EX_ISDOOR | EX_PICKPROOF; pexit->rs_flags = EX_ISDOOR | EX_PICKPROOF; break; case 3: pexit->exit_info = EX_ISDOOR | EX_NOPASS; pexit->rs_flags = EX_ISDOOR | EX_NOPASS; break; case 4: pexit->exit_info = EX_ISDOOR | EX_NOPASS | EX_PICKPROOF; pexit->rs_flags = EX_ISDOOR | EX_NOPASS | EX_PICKPROOF; break; } } else { pexit->exit_info = locks; pexit->rs_flags = locks; } pRoomIndex->exit[door] = pexit; top_exit++; } else if (letter == 'E') ed_fread(fp, &pRoomIndex->ed); else if (letter == 'O') { if (pRoomIndex->owner[0] != '\0') { log("load_rooms: duplicate owner."); exit(1); } pRoomIndex->owner = fread_string(fp); } else if (letter == 'R') { MPTRIG *rptrig; char *word; int type; const char *phrase; int vnum; word = fread_word(fp); if ((type = flag_value(rprog_flags, word)) == 0) db_error("load_room", "vnum %d: " "'%s': invalid room prog trigger", pRoomIndex->vnum, word); vnum = fread_number(fp); phrase = fread_string(fp); rptrig = rptrig_new(type, phrase, vnum); rptrig_add(pRoomIndex, rptrig); free_string(phrase); } else if (letter == 'C') { if (pRoomIndex->clan) { log("load_rooms: duplicate clan."); exit(1); } pRoomIndex->clan = fread_clan(fp); } else { log_printf("load_rooms: vnum %d has flag " "'%c' (not 'DES').", vnum, letter); exit(1); } } iHash = vnum % MAX_KEY_HASH; pRoomIndex->next = room_index_hash[iHash]; room_index_hash[iHash] = pRoomIndex; top_room++; /* OLC */ top_vnum_room = top_vnum_room < vnum ? vnum : top_vnum_room; vnum_check(area_current, vnum); /* OLC */ // if (explorable // && !IS_SET(pRoomIndex->room_flags,ROOM_GODS_ONLY|ROOM_IMP_ONLY|ROOM_PET_SHOP)) // { // area_current->explorable_rooms++; // } } //log_printf ("Area: %s, total explorable rooms: %d", area_current->name, area_current->explorable_rooms); } /* * Snarf a shop section. */ DBLOAD_FUN(load_shops) { SHOP_DATA *pShop; for (; ;) { MOB_INDEX_DATA *pMobIndex; int iTrade; pShop = alloc_perm(sizeof(*pShop)); pShop->keeper = fread_number(fp); if (pShop->keeper == 0) break; for (iTrade = 0; iTrade < MAX_TRADE; iTrade++) pShop->buy_type[iTrade] = fread_number(fp); pShop->profit_buy = fread_number(fp); pShop->profit_sell = fread_number(fp); pShop->open_hour = fread_number(fp); pShop->close_hour = fread_number(fp); fread_to_eol(fp); pMobIndex = get_mob_index(pShop->keeper); pMobIndex->pShop = pShop; if (shop_first == NULL) shop_first = pShop; if (shop_last != NULL) shop_last->next = pShop; shop_last = pShop; pShop->next = NULL; top_shop++; } return; } /* * Snarf spec proc declarations. */ DBLOAD_FUN(load_specials) { for (; ;) { MOB_INDEX_DATA *pMobIndex; char letter; switch (letter = fread_letter(fp)) { default: log_printf("load_specials: letter '%c' not *MS.", letter); exit(1); case 'S': return; case '*': break; case 'M': pMobIndex = get_mob_index (fread_number (fp)); pMobIndex->spec_fun = spec_lookup (fread_word (fp)); if (pMobIndex->spec_fun == 0) { log_printf("load_specials: 'M': vnum %d.", pMobIndex->vnum); exit(1); } break; } fread_to_eol(fp); } } /* * Snarf can prac declarations. */ DBLOAD_FUN(load_practicers) { for (; ;) { MOB_INDEX_DATA *pMobIndex; char letter; switch (letter = fread_letter(fp)) { default: log_printf("load_practicers: letter '%c' not *MS.", letter); exit(1); case 'S': return; case '*': break; case 'M': pMobIndex = get_mob_index(fread_number(fp)); SET_BIT(pMobIndex->practicer, fread_fstring(skill_groups, fp)); break; } fread_to_eol(fp); } } DBLOAD_FUN(load_olimits) { int vnum; int limit; char ch; OBJ_INDEX_DATA *pIndex; for (ch = fread_letter(fp); ch != 'S'; ch = fread_letter(fp)) { switch (ch) { case 'O': vnum = fread_number(fp); limit = fread_number(fp); if ((pIndex = get_obj_index(vnum)) == NULL) { bug("Load_olimits: bad vnum %d",vnum); exit(1); } else pIndex->limit = limit; break; case '*': fread_to_eol(fp); break; default: bug("Load_olimits: bad command '%c'",ch); exit(1); } } } DBLOAD_FUN(load_resetmsg) { area_current->resetmsg = mlstr_fread(fp); } DBLOAD_FUN(load_aflag) { area_current->flags = fread_flags(fp); } static struct { int dam; flag64_t res; } damres[MAX_DAM] = { { DAM_NONE, -1 }, { DAM_BASH, RES_BASH }, { DAM_PIERCE, RES_PIERCE }, { DAM_SLASH, RES_SLASH }, { DAM_FIRE, RES_FIRE }, { DAM_COLD, RES_COLD }, { DAM_LIGHTNING, RES_LIGHTNING }, { DAM_ACID, RES_ACID }, { DAM_POISON, RES_POISON }, { DAM_NEGATIVE, RES_NEGATIVE }, { DAM_HOLY, RES_HOLY }, { DAM_ENERGY, RES_ENERGY }, { DAM_MENTAL, RES_MENTAL }, { DAM_DISEASE, RES_DISEASE }, { DAM_LIGHT, RES_LIGHT }, { DAM_OTHER, -1 }, { DAM_HARM, -1 }, { DAM_CHARM, RES_CHARM }, { DAM_SOUND, RES_SOUND }, { DAM_THIRST, -1 }, { DAM_HUNGER, -1 }, { DAM_LIGHT_V, -1 }, { DAM_TRAP_ROOM, -1 }, { DAM_SPACE, -1 }, { DAM_RADIATION, RES_RADIATION }, { DAM_SUMMON, RES_SUMMON }, { DAM_MAGIC, RES_MAGIC }, { DAM_WEAPON, RES_WEAPON }, { DAM_WOOD, RES_WOOD }, { DAM_IRON, RES_IRON }, { DAM_SILVER, RES_SILVER } }; void convert_res2percent(sh_int *resists, flag64_t res_flags, flag64_t vuln_flags) { int i; for (i = 0; i < MAX_DAM; i++) resists[i] = 0; for (i = 0; i < MAX_DAM; i++) { if (damres[i].res != -1) { if (IS_SET(res_flags, damres[i].res)) resists[damres[i].dam] += 50; if (IS_SET(vuln_flags, damres[i].res)) resists[damres[i].dam] -= 50; } } } /* * Snarf a mob section. new style */ DBLOAD_FUN(load_mobiles) { MOB_INDEX_DATA *pMobIndex; if (!area_current) db_error("load_mobiles", "no #AREA seen yet."); for (; ;) { race_t *r; int vnum; char letter; int iHash; char *tmp; flag64_t res_flags = 0, immflags = 0, vuln_flags = 0; letter = fread_letter(fp); if (letter != '#') db_error("load_mobiles", "# not found."); vnum = fread_number(fp); if (vnum == 0) break; fBootDb = FALSE; if (get_mob_index(vnum)) { db_error("load_mobiles", "vnum %d duplicated.", vnum); exit(1); } fBootDb = TRUE; pMobIndex = alloc_perm(sizeof(*pMobIndex)); pMobIndex->short_descr = NULL; pMobIndex->long_descr = NULL; pMobIndex->description = NULL; pMobIndex->listen_data = NULL; pMobIndex->vnum = vnum; newmobs++; pMobIndex->name = fread_string(fp); pMobIndex->short_descr = mlstr_fread(fp); pMobIndex->long_descr = mlstr_fread(fp); pMobIndex->description = mlstr_fread(fp); pMobIndex->race = rn_lookup(fread_string(fp)); r = RACE(pMobIndex->race); pMobIndex->act = fread_flags(fp) | ACT_NPC | r->act; pMobIndex->affected_by = fread_flags(fp) | r->aff; pMobIndex->practicer = 0; pMobIndex->pShop = NULL; pMobIndex->alignment = fread_number(fp); pMobIndex->group = fread_number(fp); pMobIndex->level = fread_number(fp); pMobIndex->hitroll = fread_number(fp); /* read hit dice */ pMobIndex->hit[DICE_NUMBER] = fread_number(fp); /* 'd' */ fread_letter(fp); pMobIndex->hit[DICE_TYPE] = fread_number(fp); /* '+' */ fread_letter(fp); pMobIndex->hit[DICE_BONUS] = fread_number(fp); /* read mana dice */ pMobIndex->mana[DICE_NUMBER] = fread_number(fp); fread_letter(fp); pMobIndex->mana[DICE_TYPE] = fread_number(fp); fread_letter(fp); pMobIndex->mana[DICE_BONUS] = fread_number(fp); /* read damage dice */ pMobIndex->damage[DICE_NUMBER] = fread_number(fp); fread_letter(fp); pMobIndex->damage[DICE_TYPE] = fread_number(fp); fread_letter(fp); pMobIndex->damage[DICE_BONUS] = fread_number(fp); pMobIndex->dam_type = attack_lookup(fread_word(fp)); /* read armor class */ pMobIndex->ac[AC_PIERCE] = fread_number(fp) * 10; pMobIndex->ac[AC_BASH] = fread_number(fp) * 10; pMobIndex->ac[AC_SLASH] = fread_number(fp) * 10; pMobIndex->ac[AC_EXOTIC] = fread_number(fp) * 10; /* read flags and add in data from the race table */ pMobIndex->off_flags = fread_flags(fp) | r->off; /* Percent resistance is introduced in version 1.04 */ if (area_current->version < 1.04) { immflags = fread_flags(fp); res_flags = fread_flags(fp); vuln_flags = fread_flags(fp); } /* vital statistics */ pMobIndex->start_pos = fread_fword(position_table, fp); pMobIndex->default_pos = fread_fword(position_table, fp); pMobIndex->sex = fread_fword(sex_table, fp); pMobIndex->wealth = fread_number(fp); pMobIndex->form = fread_flags(fp) | r->form; pMobIndex->parts = fread_flags(fp) | r->parts; BITS_CNT(pMobIndex->parts, pMobIndex->pcnt, MAX_PARTS); /* size */ tmp = fread_word(fp); if (!is_number(tmp)) { CHECK_POS(pMobIndex->size, size_lookup(tmp), "size", pMobIndex->vnum); } else { CHECK_POS(pMobIndex->size, atoi(tmp), "size", pMobIndex->vnum); } /* pMobIndex->size = size_lookup(fread_word(fp)); */ pMobIndex->material = str_dup(fread_word(fp)); for (; ;) { letter = fread_letter(fp); if (letter == 'A') { char *word; long vector; word = fread_word(fp); vector = fread_flags(fp); if (!str_prefix(word,"det")) SET_BIT(pMobIndex->affected_by, vector); } else if (letter == 'C') { if (pMobIndex->clan) { log("load_mobiles: duplicate clan."); exit(1); } pMobIndex->clan = fread_clan(fp); } else if (letter == 'I') /* Invis or Immunity */ { char *word; word = fread_word(fp); if (!str_cmp(word, "mmunes")) pMobIndex->immunes = pMobIndex->immunes | fread_fstring(imm_flags, fp); else pMobIndex->invis_level = atoi(word); } else if (letter == 'F') { char *word; long vector; word = fread_word(fp); vector = fread_flags(fp); if (!str_prefix(word,"act")) REMOVE_BIT(pMobIndex->act,vector); else if (!str_prefix(word,"aff")) REMOVE_BIT(pMobIndex->affected_by,vector); else if (!str_prefix(word,"off")) REMOVE_BIT(pMobIndex->affected_by,vector); else if (!str_prefix(word,"imm") && area_current->version < 1.04) REMOVE_BIT(immflags,vector); else if (!str_prefix(word,"res") && area_current->version < 1.04) REMOVE_BIT(res_flags,vector); else if (!str_prefix(word,"vul") && area_current->version < 1.04) REMOVE_BIT(vuln_flags,vector); else if (!str_prefix(word,"for")) REMOVE_BIT(pMobIndex->form,vector); else if (!str_prefix(word,"par")) { REMOVE_BIT(pMobIndex->parts,vector); BITS_CNT(pMobIndex->parts, pMobIndex->pcnt, MAX_PARTS); } else db_error("flag remove", "flag not found."); } else if (letter == 'M') { MPTRIG *mptrig; char *word; int type; const char *phrase; int vnum; word = fread_word(fp); if ((type = flag_value(mptrig_types, word)) == 0) db_error("load_mobiles", "vnum %d: " "'%s': invalid mob prog trigger", pMobIndex->vnum, word); vnum = fread_number(fp); phrase = fread_string(fp); mptrig = mptrig_new(type, phrase, vnum); mptrig_add(pMobIndex, mptrig); free_string(phrase); } else if (letter == 'R') { char *dam_type; int dt; int percent; dam_type = fread_word(fp); if ((dt = flag_value(dam_flags, dam_type)) == -1) { if (str_cmp(dam_type, "drowning")) db_error("load_mobiles", "vnum: %d: '%s': invalid damage type", pMobIndex->vnum, dam_type); } percent = fread_number(fp); pMobIndex->resists[dt] = percent; } else if (letter == 'L') // listen_data { pMobIndex->listen_data = mlstr_fread(fp); } else { xungetc(letter,fp); break; } } pMobIndex->immunes = pMobIndex->immunes | immflags; if (area_current->version < 1.04) convert_res2percent(pMobIndex->resists, res_flags, vuln_flags); iHash = vnum % MAX_KEY_HASH; pMobIndex->next = mob_index_hash[iHash]; mob_index_hash[iHash] = pMobIndex; top_mob_index++; top_vnum_mob = top_vnum_mob < vnum ? vnum : top_vnum_mob; /* OLC */ vnum_check(area_current, vnum); /* OLC */ kill_table[URANGE(0, pMobIndex->level, MAX_LEVEL-2)].number++; } } /* * Snarf an obj section. new style */ DBLOAD_FUN(load_objects) { OBJ_INDEX_DATA *pObjIndex; if (!area_current) db_error("load_objects", "no #AREA seen yet."); for (; ;) { char *p; int vnum; char letter; int iHash; letter = fread_letter(fp); if (letter != '#') db_error("load_objects", "# not found."); vnum = fread_number(fp); if (vnum == 0) break; fBootDb = FALSE; if (get_obj_index(vnum)) { db_error("load_objects", "vnum %d duplicated.", vnum); exit(1); } fBootDb = TRUE; pObjIndex = alloc_perm(sizeof(*pObjIndex)); pObjIndex->short_descr = NULL; pObjIndex->description = NULL; pObjIndex->vnum = vnum; pObjIndex->reset_num = 0; newobjs++; pObjIndex->name = fread_string(fp); pObjIndex->short_descr = mlstr_fread(fp); pObjIndex->description = mlstr_fread(fp); pObjIndex->material = fread_string(fp); pObjIndex->oprogs_old = NULL; p = fread_word(fp); pObjIndex->item_type = item_lookup(p); if (pObjIndex->item_type < 0) log_printf("load_objects: vnum %d: unknown item type '%s'", pObjIndex->vnum, p); /* pObjIndex->item_type = item_lookup(fread_word(fp)); */ pObjIndex->extra_flags = fread_flags(fp); pObjIndex->wear_flags = fread_flags(fp); switch (pObjIndex->item_type) { case ITEM_WEAPON: pObjIndex->value[0] = fread_fword(weapon_class, fp); pObjIndex->value[1] = fread_number(fp); pObjIndex->value[2] = fread_number(fp); pObjIndex->value[3] = attack_lookup(fread_word(fp)); pObjIndex->value[4] = fread_flags(fp); break; case ITEM_CONTAINER: pObjIndex->value[0] = fread_number(fp); pObjIndex->value[1] = fread_flags(fp); pObjIndex->value[2] = fread_number(fp); pObjIndex->value[3] = fread_number(fp); pObjIndex->value[4] = fread_number(fp); break; case ITEM_DRINK_CON: case ITEM_FOUNTAIN: pObjIndex->value[0] = fread_number(fp); pObjIndex->value[1] = fread_number(fp); //CHECK_POS(pObjIndex->value[2], liq_lookup(fread_word(fp)), "liq_lookup", pObjIndex->vnum); CHECK_POS(pObjIndex->value[2], liquid_lookup(fread_word(fp)), "liq_lookup", pObjIndex->vnum); /* pObjIndex->value[2] = liq_lookup(fread_word(fp)); */ pObjIndex->value[3] = fread_number(fp); pObjIndex->value[4] = fread_number(fp); break; case ITEM_WAND: case ITEM_STAFF: pObjIndex->value[0] = fread_number(fp); pObjIndex->value[1] = fread_number(fp); pObjIndex->value[2] = fread_number(fp); pObjIndex->value[3] = sn_lookup(fread_word(fp)); pObjIndex->value[4] = fread_number(fp); break; case ITEM_POTION: case ITEM_PILL: case ITEM_SCROLL: pObjIndex->value[0] = fread_number(fp); pObjIndex->value[1] = sn_lookup(fread_word(fp)); pObjIndex->value[2] = sn_lookup(fread_word(fp)); pObjIndex->value[3] = sn_lookup(fread_word(fp)); pObjIndex->value[4] = sn_lookup(fread_word(fp)); break; default: pObjIndex->value[0] = fread_flags(fp); pObjIndex->value[1] = fread_flags(fp); pObjIndex->value[2] = fread_flags(fp); pObjIndex->value[3] = fread_flags(fp); pObjIndex->value[4] = fread_flags(fp); break; } pObjIndex->level = fread_number(fp); pObjIndex->weight = fread_number(fp); pObjIndex->cost = fread_number(fp); pObjIndex->limit = -1; /* condition */ letter = fread_letter(fp); switch (letter) { case ('P') : pObjIndex->condition = 100; break; case ('G') : pObjIndex->condition = 90; break; case ('A') : pObjIndex->condition = 75; break; case ('W') : pObjIndex->condition = 50; break; case ('D') : pObjIndex->condition = 25; break; case ('B') : pObjIndex->condition = 10; break; case ('R') : pObjIndex->condition = 0; break; default: pObjIndex->condition = 100; break; } for (; ;) { char letter; letter = fread_letter(fp); if (letter == 'A') { AFFECT_DATA *paf; paf = alloc_perm(sizeof(*paf)); paf->where = TO_OBJECT; paf->type = -1; paf->level = pObjIndex->level; paf->duration = -1; paf->location = fread_number(fp); paf->modifier = fread_number(fp); paf->bitvector = 0; SLIST_ADD(AFFECT_DATA, pObjIndex->affected, paf); top_affect++; } else if (letter == 'C') { if (pObjIndex->clan) { log("load_objects: duplicate clan."); exit(1); } pObjIndex->clan = fread_clan(fp); } else if (letter == 'D') pObjIndex->riddle = fread_number(fp); else if (letter == 'G') pObjIndex->gender = fread_fword(gender_table, fp); else if (letter == 'F') { AFFECT_DATA *paf, *paf2; sh_int resists[MAX_DAM]; int i, cnt = 1; paf = alloc_perm(sizeof(*paf)); letter = fread_letter(fp); switch (letter) { case 'A': paf->where = TO_AFFECTS; break; case 'I': paf->where = TO_IMMUNE; break; case 'R': paf->where = TO_RESIST; break; case 'V': paf->where = TO_RESIST; break; case 'D': paf->where = TO_AFFECTS; break; default: db_error("load_objects", "vnum %d: '%c': bad where on flag.", pObjIndex->vnum, letter); } paf->type = -1; paf->level = pObjIndex->level; paf->duration = -1; paf->location = fread_number(fp); paf->modifier = fread_number(fp); if (area_current->version > 1.03 && letter == 'R') paf->bitvector = flag_value(dam_flags, fread_word(fp)); else paf->bitvector = fread_flags(fp); /* Fix old areas */ if (area_current->version < 1.04 && (letter == 'R' || letter == 'V')) { if (paf->modifier != 0 || paf->bitvector == 0) { paf2 = alloc_perm(sizeof(*paf2)); paf2->where = TO_AFFECTS; paf2->type = -1; paf2->level = pObjIndex->level; paf2->duration = -1; paf2->location = paf->location; paf2->modifier = paf->modifier; paf2->bitvector = 0; SLIST_ADD(AFFECT_DATA, pObjIndex->affected, paf); top_affect++; } paf->location = APPLY_NONE; paf->modifier = 0; convert_res2percent(resists, letter == 'R' ? paf->bitvector : 0, letter == 'V' ? paf->bitvector : 0); for (i = 0; i < MAX_DAM; i++) if (resists[i] != 0) { if (cnt == 0) { paf = alloc_perm(sizeof(*paf)); paf->where = TO_RESIST; paf->type = -1; paf->level = -1; paf->duration = -1; paf->location = APPLY_NONE; } paf->modifier = resists[i]; paf->bitvector = i; SLIST_ADD(AFFECT_DATA, pObjIndex->affected, paf); top_affect++; cnt = 0; } } else { SLIST_ADD(AFFECT_DATA, pObjIndex->affected, paf); top_affect++; } } else if (letter == 'E') ed_fread(fp, &pObjIndex->ed); else if (letter == 'O') { MPTRIG *optrig; char *word; int type; const char *phrase; int vnum; word = fread_word(fp); if ((type = flag_value(oprog_flags, word)) == 0) db_error("load_object", "vnum %d: " "'%s': invalid obj prog trigger", pObjIndex->vnum, word); vnum = fread_number(fp); phrase = fread_string(fp); optrig = optrig_new(type, phrase, vnum); optrig_add(pObjIndex, optrig); free_string(phrase); } else if (letter == 'S') pObjIndex->size = fread_number(fp); else { xungetc(letter, fp); break; } } iHash = vnum % MAX_KEY_HASH; pObjIndex->next = obj_index_hash[iHash]; obj_index_hash[iHash] = pObjIndex; top_obj_index++; top_vnum_obj = top_vnum_obj < vnum ? vnum : top_vnum_obj; /* OLC */ vnum_check(area_current, vnum); /* OLC */ } } /* * Snarf a mprog section */ DBLOAD_FUN(load_omprogs) { char progtype[MAX_INPUT_LENGTH]; char progname[MAX_INPUT_LENGTH]; for (; ;) { OBJ_INDEX_DATA *pObjIndex; char letter; switch (letter = fread_letter(fp)) { default: db_error("load_omprogs", "letter '%c' not *IMS.", letter); exit(1); case 'S': return; case '*': break; case 'O': pObjIndex = get_obj_index (fread_number (fp)); strnzcpy(progtype, sizeof(progtype), fread_word(fp)); strnzcpy(progname, sizeof(progname), fread_word(fp)); oprog_set(pObjIndex, progtype, progname); break; case 'M': /* will be removed at all after new mob prog code integration */ break; } fread_to_eol(fp); } } /* * Lookup a skill by slot number. * Used for object loading. */ static int slot_lookup(int slot) { int sn; if (slot <= 0) return -1; for (sn = 0; sn < skills.nused; sn++) if (slot == SKILL(sn)->slot) return sn; db_error("slot_lookup", "bad slot %d.", slot); return -1; } /***************************************************************************** Name: convert_mobile Purpose: Converts an old format mob into new format Called by: load_old_mob (db.c). Note: Dug out of create_mob (db.c) Author: Hugin ****************************************************************************/ void convert_mobile(MOB_INDEX_DATA *pMobIndex) { int i; int type, number, bonus; int level; level = pMobIndex->level; pMobIndex->act |= ACT_WARRIOR; /* * Calculate hit dice. Gives close to the hitpoints * of old format mobs created with create_mob() (db.c) * A high number of dice makes for less variance in mobiles * hitpoints. * (might be a good idea to reduce the max number of dice) * * The conversion below gives: level: dice min max diff mean 1: 1d2+6 7 (7) 8 (8) 1 (1) 8 (8) 2: 1d3+15 16 (15) 18 (18) 2 (3) 17 (17) 3: 1d6+24 25 (24) 30 (30) 5 (6) 27 (27) 5: 1d17+42 43 (42) 59 (59) 16 (17) 51 (51) 10: 3d22+96 99 (95) 162 (162) 63 (67) 131 () 15: 5d30+161 166 (159) 311 (311) 145 (150) 239 () 30: 10d61+416 426 (419) 1026 (1026) 600 (607) 726 () 50: 10d169+920 930 (923) 2610 (2610) 1680 (1688) 1770 () The values in parenthesis give the values generated in create_mob. Diff = max - min. Mean is the arithmetic mean. (hmm.. must be some roundoff error in my calculations.. smurfette got 1d6+23 hp at level 3 ? -- anyway.. the values above should be approximately right..) */ type = level*level*27/40; number = UMIN(type/40 + 1, 10); /* how do they get 11 ??? */ type = UMAX(2, type/number); bonus = UMAX(0, level*(8 + level)*.9 - number*type); pMobIndex->hit[DICE_NUMBER] = number; pMobIndex->hit[DICE_TYPE] = type; pMobIndex->hit[DICE_BONUS] = bonus; pMobIndex->mana[DICE_NUMBER] = level; pMobIndex->mana[DICE_TYPE] = 10; pMobIndex->mana[DICE_BONUS] = 100; /* * Calculate dam dice. Gives close to the damage * of old format mobs in damage() (fight.c) */ type = level*7/4; number = UMIN(type/8 + 1, 5); type = UMAX(2, type/number); bonus = UMAX(0, level*9/4 - number*type); pMobIndex->damage[DICE_NUMBER] = number; pMobIndex->damage[DICE_TYPE] = type; pMobIndex->damage[DICE_BONUS] = bonus; switch (number_range(1, 3)) { case (1): pMobIndex->dam_type = 3; break; /* slash */ case (2): pMobIndex->dam_type = 7; break; /* pound */ case (3): pMobIndex->dam_type = 11; break; /* pierce */ } for (i = 0; i < 3; i++) pMobIndex->ac[i]= interpolate(level, 100, -100); pMobIndex->ac[3] = interpolate(level, 100, 0); /* exotic */ pMobIndex->wealth /= 100; pMobIndex->size = SIZE_MEDIUM; pMobIndex->material = str_dup("none"); ++newmobs; } MPCODE *get_prog_index( int vnum, int type ) { MPCODE *prg; switch (type) { case PRG_MPROG: prg = mpcode_list; break; case PRG_OPROG: prg = opcode_list; break; case PRG_RPROG: prg = rpcode_list; break; default: return NULL; } for (; prg; prg = prg->next) { if (prg->vnum == vnum) return( prg ); } return NULL; } DBLOAD_FUN(load_objprogs) { MPCODE *pOprog; if (area_last == NULL) { bug( "Load_objprogs: no #AREA seen yet.", 0 ); exit( 1 ); } for (; ;) { int vnum; char letter; letter = fread_letter( fp ); if (letter != '#') { bug( "Load_objprogs: # not found.", 0 ); exit( 1 ); } vnum = fread_number( fp ); if (vnum == 0) break; fBootDb = FALSE; if (get_prog_index( vnum, PRG_OPROG ) != NULL) { bug( "Load_objprogs: vnum %d duplicated.", vnum ); exit( 1 ); } fBootDb = TRUE; pOprog = alloc_perm( sizeof(*pOprog) ); pOprog->vnum = vnum; pOprog->code = fread_string( fp ); if (opcode_list == NULL) opcode_list = pOprog; else { pOprog->next = opcode_list; opcode_list = pOprog; } top_oprog_index++; } return; } DBLOAD_FUN(load_roomprogs) { MPCODE *pRprog; int vnum; char letter; if ( area_last == NULL ) { bug( "Load_roomprogs: no #AREA seen yet.", 0 ); exit( 1 ); } for ( ; ; ) { letter = fread_letter( fp ); if ( letter != '#' ) { bug( "Load_roomprogs: # not found.", 0 ); exit( 1 ); } vnum = fread_number( fp ); if ( vnum == 0 ) break; fBootDb = FALSE; if ( get_prog_index( vnum, PRG_RPROG ) != NULL ) { bug( "Load_roomprogs: vnum %d duplicated.", vnum ); exit( 1 ); } fBootDb = TRUE; pRprog = alloc_perm( sizeof(*pRprog) ); pRprog->vnum = vnum; pRprog->code = fread_string( fp ); if ( rpcode_list == NULL ) rpcode_list = pRprog; else { pRprog->next = rpcode_list; rpcode_list = pRprog; } top_rprog_index++; } return; }