/************************************************************************** * 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-2004 by Markanth * * http://www.firstmud.com/ <markanth@firstmud.com> * * By using this code you have agreed to follow the term of * * the 1stMud license in ../doc/1stMud/LICENSE * ***************************************************************************/ #define IN_DB_C 1 #include "merc.h" #include "recycle.h" #include "tables.h" #include "olc.h" #include "interp.h" #include "data_table.h" #include "vnums.h" #include "special.h" #undef IN_DB_C AreaData *current_area; FileData *fpArea; char strArea[MAX_INPUT_LENGTH]; Proto(void init_mm, (void)); Declare_Boot_F(load_old_area); Declare_Boot_F(load_area); Declare_Boot_F(load_old_helps); Declare_Boot_F(load_old_mob); Declare_Boot_F(load_old_obj); Declare_Boot_F(load_resets); Declare_Boot_F(load_rooms); Declare_Boot_F(load_shops); Declare_Boot_F(load_specials); Declare_Boot_F(load_mobprogs); Declare_Boot_F(load_objprogs); Declare_Boot_F(load_roomprogs); Proto(void fix_objprogs, (void)); Proto(void fix_roomprogs, (void)); Proto(void init_area_weather, (void)); Proto(void fix_exits, (void)); Proto(void fix_mobprogs, (void)); Proto(void build_player_index, (void)); DataTable time_data_table[] = { {"hour", FIELD_INT, (void *) &time_zero.hour, NULL, NULL, olced_int, NULL}, {"day", FIELD_INT, (void *) &time_zero.day, NULL, NULL, olced_int, NULL}, { "month", FIELD_INT, (void *) &time_zero.month, NULL, NULL, olced_int, NULL}, {"year", FIELD_INT, (void *) &time_zero.year, NULL, NULL, olced_int, NULL}, {"sunlight", FIELD_INT, (void *) &time_zero.sunlight, NULL, NULL, olced_int, NULL}, {NULL, (field_t) - 1, NULL, NULL, NULL, NULL, NULL} }; TableSave_Fun(rw_time_data) { rw_single(type, TIME_FILE, time); } void setup_myrlims(void) { #ifdef HAVE_SETRLIMIT #define getsetlimit(res) \ do { \ struct rlimit limit; \ getrlimit(res, &limit); \ limit.rlim_cur = limit.rlim_max = RLIM_INFINITY; \ setrlimit(res, &limit); \ } while(0) log_string("Setting user limits..."); getsetlimit(RLIMIT_CPU); getsetlimit(RLIMIT_FSIZE); getsetlimit(RLIMIT_DATA); getsetlimit(RLIMIT_STACK); getsetlimit(RLIMIT_CORE); #ifdef RLIMIT_RSS getsetlimit(RLIMIT_RSS); #endif #if 0 getsetlimit(RLIMIT_NPROC); #endif #if 0 getsetlimit(RLIMIT_NOFILE); #endif #ifdef RLIMIT_MEMLOCK getsetlimit(RLIMIT_MEMLOCK); #endif #ifdef RLIMIT_AS getsetlimit(RLIMIT_AS); #endif #endif } void load_area_db(void) { FileData *fpList; const struct bootf_type { const char *header; Boot_F *fun; } bootf_table[] = { { "AREA", load_old_area} , { "AREADATA", load_area} , { "HELPS", load_old_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} , { "SPECIALS", load_specials} , { NULL, NULL} }; if ((fpList = f_open(AREA_LIST, "r")) == NULL) { log_error(AREA_LIST); exit(1); } while (true) { char buf[MIL]; strcpy(strArea, read_word(fpList)); if (strArea[0] == '$') break; sprintf(buf, AREA_DIR "%s", strArea); if ((fpArea = f_open(buf, "r")) == NULL) { log_error(strArea); exit(1); } logf("Loading %s...", strArea); current_area = NULL; while (true) { char *word; int i; if (read_letter(fpArea) != '#') { bug("Boot_db: # not found."); exit(1); } word = read_word(fpArea); if (word[0] == '$') break; for (i = 0; bootf_table[i].header != NULL; i++) { if (!str_cmp(word, bootf_table[i].header)) break; } if (bootf_table[i].fun != NULL) { (*bootf_table[i].fun) (fpArea); } else { bug("Boot_db: bad section name."); exit(1); } } f_close(fpArea); } f_close(fpList); fpArea = NULL; logf("Loaded %d areas.", top_area); } void boot_db(void) { run_level = RUNLEVEL_BOOTING; setup_myrlims(); init_mm(); #ifndef DISABLE_MYSQL init_db_first_run(); #endif rw_time_data(act_read); rw_class_data(act_read); rw_skill_data(act_read); rw_group_data(act_read); rw_cmd_data(act_read); rw_race_data(act_read); rw_clan_data(act_read); rw_deity_data(act_read); rw_color_data(act_read); rw_color_template_data(act_read); #ifndef DISABLE_MYSQL db_load_areas(); #else load_area_db(); #endif rw_help_data(act_read); fix_exits(); fix_mobprogs(); fix_objprogs(); fix_roomprogs(); run_level = RUNLEVEL_SAFE_BOOT; convert_objects(); area_update(); build_player_index(); rw_note_data(act_read); rw_ban_data(act_read); rw_song_data(act_read); rw_disabled_data(act_read); rw_social_data(act_read); rw_change_data(act_read); rw_gquest_data(act_read); rw_war_data(act_read); rw_mbr_data(act_read); rw_channel_data(act_read); rw_name_profile_data(act_read); #ifndef DISABLE_WEBSRV init_www_history(); #endif examine_crash_log(); load_corpses(); load_room_objs(); rw_wpwd_data(act_read); init_area_weather(); #ifndef DISABLE_MYSQL finish_db_first_run(); #endif logf("Stored %d Areas, %d Rooms, %d Mobs, %d Objects & %d Helps.", top_area, top_room_index, top_char_index, top_obj_index, top_help); logf("Finished. Bootup took %s.", timestr(getcurrenttime() - boot_time, false)); #ifndef DISABLE_WEBSRV if (web_is_connected()) logf("Integrated world wide web server running on port %d.", webport); #endif return; } Proto(void convert_area_credits, (AreaData *)); Boot_Fun(load_old_area) { AreaData *pArea; pArea = new_area(); read_strfree(fp, &pArea->file_name); pArea->area_flags = AREA_LOADING; read_strfree(fp, &pArea->name); read_strfree(fp, &pArea->credits); pArea->min_vnum = read_number(fp); pArea->max_vnum = read_number(fp); add_area(pArea); current_area = pArea; convert_area_credits(pArea); top_area++; return; } Boot_Fun(load_area) { AreaData *pArea; const char *word; bool fMatch; pArea = new_area(); replace_str(&pArea->file_name, strArea); while (true) { word = f_eof(fp) ? "End" : read_word(fp); fMatch = false; switch (toupper(word[0])) { case 'L': Key_Str("LvlComment", pArea->lvl_comment); break; case 'M': Key("MinLevel", pArea->min_level, read_number(fp)); Key("MaxLevel", pArea->max_level, read_number(fp)); break; case 'N': Key_Str("Name", pArea->name); break; case 'F': Key("Flags", pArea->area_flags, read_flag(fp)); break; case 'R': Key("ResetMsg", pArea->resetmsg, read_string(fp)); Key("Recall", pArea->recall, read_number(fp)); break; case 'S': Key("Security", pArea->security, read_number(fp)); Key("Sound", pArea->sound, read_sound(fp)); if (!str_cmp(word, "Stats")) { pArea->kills = read_long(fp); pArea->deaths = read_long(fp); fMatch = true; break; } break; case 'V': Key("Version", pArea->version, read_number(fp)); if (!str_cmp(word, "VNUMs")) { pArea->min_vnum = read_number(fp); pArea->max_vnum = read_number(fp); fMatch = true; break; } break; case 'E': if (!str_cmp(word, "End")) { fMatch = true; add_area(pArea); current_area = pArea; convert_area_credits(pArea); return; } break; case 'B': Key_Str("Builders", pArea->builders); break; case 'C': Key_Str("Credits", pArea->credits); if (!str_cmp(word, "Climate")) { pArea->weather.climate_temp = read_number(fp); pArea->weather.climate_precip = read_number(fp); pArea->weather.climate_wind = read_number(fp); fMatch = true; break; } Key_SFun("Clan", pArea->clan, clan_lookup); break; } } } void assign_area_vnum(vnum_t vnum) { if (current_area->min_vnum == 0 || current_area->max_vnum == 0) current_area->min_vnum = current_area->max_vnum = vnum; if (vnum != Range(current_area->min_vnum, vnum, current_area->max_vnum)) { if (vnum < current_area->min_vnum) current_area->min_vnum = vnum; else current_area->max_vnum = vnum; } return; } Boot_Fun(load_old_helps) { HelpData *pHelp; int level; const char *keyword; while (true) { level = read_number(fp); keyword = read_string(fp); if (keyword[0] == '$') break; pHelp = new_help(); pHelp->level = level; pHelp->keyword = keyword; read_strfree(fp, &pHelp->text); add_help(pHelp); } return; } Boot_Fun(load_old_mob) { CharIndex *pMobIndex; RaceData *race; char name[MAX_STRING_LENGTH]; if (!current_area) { bug("Load_mobiles: no #AREA seen yet."); exit(1); } while (true) { vnum_t vnum; char letter; int iHash; letter = read_letter(fp); if (letter != '#') { bug("Load_mobiles: # not found."); exit(1); } vnum = read_number(fp); if (vnum == 0) break; run_level = RUNLEVEL_SAFE_BOOT; if (get_char_index(vnum) != NULL) { bugf("Load_mobiles: vnum %ld duplicated.", vnum); exit(1); } run_level = RUNLEVEL_BOOTING; pMobIndex = new_char_index(); pMobIndex->vnum = vnum; pMobIndex->area = current_area; pMobIndex->new_format = false; read_strfree(fp, &pMobIndex->player_name); read_strfree(fp, &pMobIndex->short_descr); read_strfree(fp, &pMobIndex->long_descr); read_strfree(fp, &pMobIndex->description); pMobIndex->act = read_flag(fp) | ACT_IS_NPC; pMobIndex->affected_by = read_flag(fp); pMobIndex->pShop = NULL; pMobIndex->alignment = read_number(fp); letter = read_letter(fp); pMobIndex->level = read_number(fp); read_number(fp); read_number(fp); read_number(fp); read_letter(fp); read_number(fp); read_letter(fp); read_number(fp); read_number(fp); read_letter(fp); read_number(fp); read_letter(fp); read_number(fp); pMobIndex->wealth = read_number(fp) / 20; read_number(fp); pMobIndex->start_pos = read_enum(position_t, fp); pMobIndex->default_pos = read_enum(position_t, fp); if (pMobIndex->start_pos < POS_SLEEPING) pMobIndex->start_pos = POS_STANDING; if (pMobIndex->default_pos < POS_SLEEPING) pMobIndex->default_pos = POS_STANDING; pMobIndex->sex = read_enum(sex_t, fp); one_argument(pMobIndex->player_name, name); if (NullStr(name) || (race = race_lookup(name)) == NULL) { pMobIndex->race = default_race; pMobIndex->off_flags = OFF_DODGE | OFF_DISARM | OFF_TRIP | ASSIST_VNUM; pMobIndex->imm_flags = 0; pMobIndex->res_flags = 0; pMobIndex->vuln_flags = 0; pMobIndex->form = FORM_EDIBLE | FORM_SENTIENT | FORM_BIPED | FORM_MAMMAL; pMobIndex->parts = PART_HEAD | PART_ARMS | PART_LEGS | PART_HEART | PART_BRAINS | PART_GUTS; } else { pMobIndex->race = race; pMobIndex->off_flags = OFF_DODGE | OFF_DISARM | OFF_TRIP | ASSIST_RACE | race->off; pMobIndex->imm_flags = race->imm; pMobIndex->res_flags = race->res; pMobIndex->vuln_flags = race->vuln; pMobIndex->form = race->form; pMobIndex->parts = race->parts; } if (letter != 'S') { bugf("Load_mobiles: vnum %ld non-S.", vnum); exit(1); } convert_mobile(pMobIndex); iHash = vnum % MAX_KEY_HASH; LinkSingle(pMobIndex, char_index_hash[iHash], next); top_vnum_mob = Max(top_vnum_mob, vnum); assign_area_vnum(vnum); kill_table[Range(0, pMobIndex->level, MAX_LEVEL - 1)].number++; } return; } Boot_Fun(load_old_obj) { ObjIndex *pObjIndex; if (!current_area) { bug("Load_objects: no #AREA seen yet."); exit(1); } while (true) { vnum_t vnum; char letter; int iHash = -1; const char *str; letter = read_letter(fp); if (letter != '#') { bug("Load_objects: # not found."); exit(1); } vnum = read_number(fp); if (vnum == 0) break; run_level = RUNLEVEL_SAFE_BOOT; if (get_obj_index(vnum) != NULL) { bugf("Load_objects: vnum %ld duplicated.", vnum); exit(1); } run_level = RUNLEVEL_BOOTING; pObjIndex = new_obj_index(); pObjIndex->vnum = vnum; pObjIndex->area = current_area; pObjIndex->new_format = false; pObjIndex->reset_num = 0; read_strfree(fp, &pObjIndex->name); str = read_string(fp); replace_str(&pObjIndex->short_descr, Upper(str)); free_string(str); str = read_string(fp); replace_str(&pObjIndex->description, Upper(str)); free_string(str); read_string(fp); pObjIndex->item_type = read_enum(item_t, fp); pObjIndex->extra_flags = read_flag(fp); pObjIndex->wear_flags = read_flag(fp); pObjIndex->value[0] = read_number(fp); pObjIndex->value[1] = read_number(fp); pObjIndex->value[2] = read_number(fp); pObjIndex->value[3] = read_number(fp); pObjIndex->value[4] = 0; pObjIndex->level = 0; pObjIndex->condition = 100; pObjIndex->weight = read_number(fp); pObjIndex->cost = read_number(fp); read_number(fp); if (pObjIndex->item_type == ITEM_WEAPON) { if (is_name("two", pObjIndex->name) || is_name("two-handed", pObjIndex->name) || is_name("claymore", pObjIndex->name)) SetBit(pObjIndex->value[4], WEAPON_TWO_HANDS); } while (iHash == -1) { letter = read_letter(fp); switch (letter) { case 'A': { AffectData *paf; paf = new_affect(); paf->where = TO_OBJECT; paf->type = -1; paf->level = 20; paf->duration = -1; paf->location = read_enum(apply_t, fp); paf->modifier = read_number(fp); paf->bitvector = 0; Link(paf, pObjIndex->affect, next, prev); } break; case 'E': { ExDescrData *ed; ed = new_ed(); read_strfree(fp, &ed->keyword); read_strfree(fp, &ed->description); Link(ed, pObjIndex->ed, next, prev); } break; default: { iHash = vnum % MAX_KEY_HASH; f_ungetc(letter, fp); break; } } } if (pObjIndex->item_type == ITEM_ARMOR) { pObjIndex->value[1] = pObjIndex->value[0]; pObjIndex->value[2] = pObjIndex->value[1]; } LinkSingle(pObjIndex, obj_index_hash[iHash], next); top_vnum_obj = Max(top_vnum_obj, vnum); assign_area_vnum(vnum); } return; } Boot_Fun(load_resets) { ResetData *pReset; ExitData *pexit; RoomIndex *pRoomIndex; vnum_t rVnum = -1; flag_t arg5; if (!current_area) { bug("Load_resets: no #AREA seen yet."); exit(1); } while (true) { char letter; if ((letter = read_letter(fp)) == 'S') break; if (letter == '*') { read_to_eol(fp); continue; } pReset = new_reset(); pReset->command = letter; read_number(fp); pReset->arg1 = read_number(fp); pReset->arg2 = read_number(fp); pReset->arg3 = (letter == 'G' || (current_area->version < 3 && letter == 'R')) ? 0 : read_number(fp); pReset->arg4 = (letter == 'P' || letter == 'M') ? read_number(fp) : 0; arg5 = (letter == 'F') ? read_flag(fp) : 0; read_to_eol(fp); switch (pReset->command) { case 'M': case 'O': rVnum = pReset->arg3; break; case 'P': case 'G': case 'E': break; case 'D': pRoomIndex = get_room_index((rVnum = pReset->arg1)); if (pReset->arg2 < 0 || pReset->arg2 >= MAX_DIR || !pRoomIndex || !(pexit = pRoomIndex->exit[pReset->arg2]) || !IsSet(pexit->rs_flags, EX_ISDOOR)) { bugf("Load_resets: 'D': exit %d, room %ld not door.", pReset->arg2, pReset->arg1); exit(1); } switch (pReset->arg3) { default: bugf("Load_resets: 'D': bad 'locks': %ld.", pReset->arg3); break; case 0: break; case 1: SetBit(pexit->rs_flags, EX_CLOSED); SetBit(pexit->exit_info, EX_CLOSED); break; case 2: SetBit(pexit->rs_flags, EX_CLOSED | EX_LOCKED); SetBit(pexit->exit_info, EX_CLOSED | EX_LOCKED); break; } break; case 'F': pRoomIndex = get_room_index((rVnum = pReset->arg1)); if (pReset->arg2 < 0 || pReset->arg2 > (MAX_DIR - 1) || !pRoomIndex || !(pexit = pRoomIndex->exit[pReset->arg2])) { bugf("'F': Nonexistent exit [%ld:%d].", pRoomIndex->vnum, pReset->arg2); break; } pexit->rs_flags = arg5; pexit->exit_info = arg5; break; case 'R': rVnum = pReset->arg1; break; } if (rVnum == -1) { bugf("load_resets : rVnum == -1"); exit(1); } if (pReset->command != 'D' && pReset->command != 'F') add_reset(get_room_index(rVnum), pReset, 0); else free_reset(pReset); } return; } Boot_Fun(load_rooms) { RoomIndex *pRoomIndex; if (current_area == NULL) { bug("Load_resets: no #AREA seen yet."); exit(1); } while (true) { vnum_t vnum; char letter; int door; int iHash = -1; letter = read_letter(fp); if (letter != '#') { bug("Load_rooms: # not found."); exit(1); } vnum = read_number(fp); if (vnum == 0) break; run_level = RUNLEVEL_SAFE_BOOT; if (get_room_index(vnum) != NULL) { bugf("Load_rooms: vnum %ld duplicated.", vnum); exit(1); } run_level = RUNLEVEL_BOOTING; pRoomIndex = new_room_index(); pRoomIndex->person_first = NULL; pRoomIndex->content_first = NULL; pRoomIndex->ed_first = NULL; pRoomIndex->area = current_area; pRoomIndex->vnum = vnum; read_strfree(fp, &pRoomIndex->name); read_strfree(fp, &pRoomIndex->description); read_number(fp); pRoomIndex->room_flags = read_flag(fp); if (3000 <= vnum && vnum < 3400) SetBit(pRoomIndex->room_flags, ROOM_LAW); pRoomIndex->sector_type = read_enum(sector_t, fp); pRoomIndex->light = 0; for (door = 0; door <= 5; door++) pRoomIndex->exit[door] = NULL; pRoomIndex->heal_rate = 100; pRoomIndex->mana_rate = 100; while (iHash == -1) { letter = read_letter(fp); switch (letter) { case 'S': iHash = vnum % MAX_KEY_HASH; break; case 'H': pRoomIndex->heal_rate = read_number(fp); break; case 'M': pRoomIndex->mana_rate = read_number(fp); break; case 'C': { const char *tmp = read_string(fp); free_string(tmp); } break; case 'G': if (pRoomIndex->guild > -1 && pRoomIndex->guild < top_class) { bug("Duplicate guild."); exit(1); } pRoomIndex->guild = read_number(fp); break; case 'D': { ExitData *pexit; door = read_number(fp); if (door < 0 || door > 5) { bugf("Fread_rooms: vnum %ld has bad door number.", vnum); exit(1); } pexit = new_exit(); read_strfree(fp, &pexit->description); read_strfree(fp, &pexit->keyword); pexit->exit_info = 0; pexit->rs_flags = 0; if (pRoomIndex->area->version < 2) { switch (read_number(fp)) { 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->rs_flags = read_flag(fp); if (IsSet(pexit->rs_flags, EX_TEMP)) RemBit(pexit->rs_flags, EX_TEMP); pexit->exit_info = pexit->rs_flags; pexit->key = read_number(fp); pexit->u1.vnum = read_number(fp); pexit->orig_door = door; pRoomIndex->exit[door] = pexit; } break; case 'E': { ExDescrData *ed; ed = new_ed(); read_strfree(fp, &ed->keyword); read_strfree(fp, &ed->description); Link(ed, pRoomIndex->ed, next, prev); } break; case 'O': if (!NullStr(pRoomIndex->owner)) { bug("Load_rooms: duplicate owner."); exit(1); } pRoomIndex->owner = read_string(fp); SetBit(pRoomIndex->room_flags, ROOM_NOEXPLORE); break; case 'R': { ProgList *pRprog; const char *word; flag_t trigger = 0; pRprog = new_prog_list(); word = read_word(fp); if ((trigger = flag_value(rprog_flags, word)) == NO_FLAG) { bug("ROOMprogs: invalid trigger."); exit(1); } SetBit(pRoomIndex->rprog_flags, trigger); pRprog->trig_type = trigger; pRprog->prog = (ProgCode *) read_long(fp); read_strfree(fp, &pRprog->trig_phrase); Link(pRprog, pRoomIndex->rprog, next, prev); } break; default: bugf("Load_rooms: vnum %ld has invalid flag %c.", vnum, letter); exit(1); break; } } LinkSingle(pRoomIndex, room_index_hash[iHash], next); if (!IsSet(pRoomIndex->room_flags, ROOM_NOEXPLORE)) top_explored++; top_vnum_room = Max(top_vnum_room, vnum); assign_area_vnum(vnum); } return; } Boot_Fun(load_shops) { ShopData *pShop; while (true) { CharIndex *pMobIndex; int iTrade; pShop = new_shop(); pShop->keeper = read_number(fp); if (pShop->keeper == 0) break; for (iTrade = 0; iTrade < MAX_TRADE; iTrade++) pShop->buy_type[iTrade] = read_number(fp); pShop->profit_buy = read_number(fp); pShop->profit_sell = read_number(fp); pShop->open_hour = read_number(fp); pShop->close_hour = read_number(fp); read_to_eol(fp); pMobIndex = get_char_index(pShop->keeper); pMobIndex->pShop = pShop; Link(pShop, shop, next, prev); } return; } Boot_Fun(load_specials) { while (true) { CharIndex *pMobIndex; char letter = read_letter(fp); switch (letter) { default: bugf("Load_specials: letter '%c' not *MS.", letter); exit(1); case 'S': return; case '*': break; case 'M': pMobIndex = get_char_index(read_number(fp)); pMobIndex->spec_fun = spec_lookup(read_word(fp)); if (pMobIndex->spec_fun == 0) { bugf("Load_specials: 'M': vnum %ld.", pMobIndex->vnum); exit(1); } break; } read_to_eol(fp); } } void fix_exits(void) { RoomIndex *pRoomIndex; ExitData *pexit; ResetData *pReset; RoomIndex *iLastRoom, *iLastObj; int iHash; int door; log_string("Fixing exits..."); for (iHash = 0; iHash < MAX_KEY_HASH; iHash++) { for (pRoomIndex = room_index_hash[iHash]; pRoomIndex != NULL; pRoomIndex = pRoomIndex->next) { bool fexit; iLastRoom = iLastObj = NULL; for (pReset = pRoomIndex->reset_first; pReset; pReset = pReset->next) { switch (pReset->command) { default: bugf("fix_exits : cuarto %ld con reset cmd %c", pRoomIndex->vnum, pReset->command); exit(1); break; case 'M': get_char_index(pReset->arg1); iLastRoom = get_room_index(pReset->arg3); break; case 'O': get_obj_index(pReset->arg1); iLastObj = get_room_index(pReset->arg3); break; case 'P': get_obj_index(pReset->arg1); if (iLastObj == NULL) { bugf ("fix_exits : reset en cuarto %ld con iLastObj NULL", pRoomIndex->vnum); exit(1); } break; case 'G': case 'E': get_obj_index(pReset->arg1); if (iLastRoom == NULL) { bugf ("fix_exits : reset en cuarto %ld con iLastRoom NULL", pRoomIndex->vnum); exit(1); } iLastObj = iLastRoom; break; case 'D': bugf("???"); break; case 'R': get_room_index(pReset->arg1); if (pReset->arg2 < 0 || pReset->arg2 > MAX_DIR) { bugf ("fix_exits : reset en cuarto %ld con arg2 %d >= MAX_DIR", pRoomIndex->vnum, pReset->arg2); exit(1); } break; } } fexit = false; for (door = 0; door <= 5; door++) { if ((pexit = pRoomIndex->exit[door]) != NULL) { if (pexit->u1.vnum <= 0 || get_room_index(pexit->u1.vnum) == NULL) pexit->u1.to_room = NULL; else { fexit = true; pexit->u1.to_room = get_room_index(pexit->u1.vnum); } } } if (!fexit) SetBit(pRoomIndex->room_flags, ROOM_NO_MOB); } } return; } Boot_Fun(load_mobprogs) { ProgCode *pMprog; if (current_area == NULL) { bug("Load_mobprogs: no #AREA seen yet."); exit(1); } while (true) { vnum_t vnum; char letter; letter = read_letter(fp); if (letter != '#') { bug("Load_mobprogs: # not found."); exit(1); } vnum = read_number(fp); if (vnum == 0) break; run_level = RUNLEVEL_SAFE_BOOT; if (get_prog_index(vnum, PRG_MPROG) != NULL) { bugf("Load_mobprogs: vnum %ld duplicated.", vnum); exit(1); } run_level = RUNLEVEL_BOOTING; pMprog = new_mprog(); pMprog->vnum = vnum; read_strfree(fp, &pMprog->code); pMprog->area = current_area; Link(pMprog, mprog, next, prev); } return; } void fix_mobprogs(void) { CharIndex *pMobIndex; ProgList *list; ProgCode *prog; int iHash; log_string("Fixing mob programs..."); for (iHash = 0; iHash < MAX_KEY_HASH; iHash++) { for (pMobIndex = char_index_hash[iHash]; pMobIndex != NULL; pMobIndex = pMobIndex->next) { for (list = pMobIndex->mprog_first; list != NULL; list = list->next) { if ((prog = get_prog_index((vnum_t) list->prog, PRG_MPROG)) == NULL) { bugf("Fix_roomprogs: code vnum %ld not found.", (vnum_t) list->prog); exit(1); } else list->prog = prog; } } } } void area_update(void) { AreaData *pArea; int hash; RoomIndex *room; if (run_level == RUNLEVEL_BOOTING) log_string("Updating areas..."); for (pArea = area_first; pArea != NULL; pArea = pArea->next) { if (++pArea->age < 3) continue; if ((!pArea->empty && (pArea->nplayer == 0 || pArea->age >= 15)) || pArea->age >= 31) { RoomIndex *pRoomIndex; const char *msg = NULL; reset_area(pArea); new_wiznet(NULL, NULL, WIZ_RESETS, false, 0, "%s has just been reset.", pArea->name); if (IsSet(pArea->area_flags, OLC_CHANGED)) { save_area(pArea); new_wiznet(NULL, NULL, WIZ_RESETS, true, 0, "%s has just been saved.", pArea->name); } pArea->age = number_range(0, 3); pRoomIndex = get_room_index(ROOM_VNUM_SCHOOL); if (pRoomIndex != NULL && pArea == pRoomIndex->area) pArea->age = 15 - 2; else if (pArea->nplayer == 0) pArea->empty = true; if (!NullStr(pArea->resetmsg)) msg = pArea->resetmsg; else if (!pRoomIndex || pRoomIndex->area != pArea) { switch (number_range(0, 4)) { default: msg = "The area repopulates itself."; break; case 1: msg = "You notice a change in the area."; break; case 2: msg = "Time completes another cycle bringing life to the area."; break; case 3: msg = "You feel a sudden deja-vu bringing change to the area."; break; case 4: msg = "You hear noises off in the distance..."; break; } } if (!NullStr(msg)) { CharData *ch; for (ch = player_first; ch != NULL; ch = ch->next_player) { if (ch->desc && ch->desc->connected == CON_PLAYING && IsAwake(ch) && ch->in_room && ch->in_room->area == pArea) chprintlnf(ch, "{?%s{x", msg); } } } } for (hash = 0; hash < MAX_KEY_HASH; hash++) for (room = room_index_hash[hash]; room; room = room->next) { if (room->area->empty) continue; if (HasTriggerRoom(room, TRIG_DELAY) && room->rprog_delay > 0) { if (--room->rprog_delay <= 0) p_percent_trigger(NULL, NULL, room, NULL, NULL, NULL, TRIG_DELAY); } else if (HasTriggerRoom(room, TRIG_RANDOM)) p_percent_trigger(NULL, NULL, room, NULL, NULL, NULL, TRIG_RANDOM); } return; } void reset_room(RoomIndex * pRoom) { ResetData *pReset; CharData *pMob; CharData *mob; ObjData *pObj; CharData *LastMob = NULL; ObjData *LastObj = NULL; int iExit; int level = 0; bool last; if (!pRoom) return; pMob = NULL; last = false; for (iExit = 0; iExit < MAX_DIR; iExit++) { ExitData *pExit; if ((pExit = pRoom->exit[iExit])) { pExit->exit_info = pExit->rs_flags; if ((pExit->u1.to_room != NULL) && ((pExit = pExit->u1.to_room->exit[rev_dir[iExit]]))) { pExit->exit_info = pExit->rs_flags; } } } for (pReset = pRoom->reset_first; pReset != NULL; pReset = pReset->next) { CharIndex *pMobIndex; ObjIndex *pObjIndex; ObjIndex *pObjToIndex; RoomIndex *pRoomIndex; char buf[MAX_STRING_LENGTH]; int count, limit = 0; switch (pReset->command) { default: bugf("Reset_room: bad command %c.", pReset->command); break; case 'M': if (!(pMobIndex = get_char_index(pReset->arg1))) { bugf("Reset_room: 'M': bad vnum %ld.", pReset->arg1); continue; } if ((pRoomIndex = get_room_index(pReset->arg3)) == NULL) { bugf("Reset_area: 'R': bad vnum %ld.", pReset->arg3); continue; } if (pMobIndex->count >= pReset->arg2) { last = false; break; } count = 0; for (mob = pRoomIndex->person_first; mob != NULL; mob = mob->next_in_room) if (mob->pIndexData == pMobIndex) { count++; if (count >= pReset->arg4) { last = false; break; } } if (count >= pReset->arg4) break; pMob = create_mobile(pMobIndex); if (room_is_dark(pRoom)) SetBit(pMob->affected_by, AFF_INFRARED); { RoomIndex *pRoomIndexPrev; pRoomIndexPrev = get_room_index(pRoom->vnum - 1); if (pRoomIndexPrev && IsSet(pRoomIndexPrev->room_flags, ROOM_PET_SHOP)) SetBit(pMob->act, ACT_PET); } char_to_room(pMob, pRoom); LastMob = pMob; level = Range(0, pMob->level - 2, MAX_MORTAL_LEVEL - 1); last = true; break; case 'O': if (!(pObjIndex = get_obj_index(pReset->arg1))) { bugf("Reset_room: 'O' 1 : bad vnum %ld", pReset->arg1); sprintf(buf, "%ld %d %ld %d", pReset->arg1, pReset->arg2, pReset->arg3, pReset->arg4); bugf(buf, 1); continue; } if (!(pRoomIndex = get_room_index(pReset->arg3))) { bugf("Reset_room: 'O' 2 : bad vnum %ld.", pReset->arg3); sprintf(buf, "%ld %d %ld %d", pReset->arg1, pReset->arg2, pReset->arg3, pReset->arg4); bugf(buf, 1); continue; } if (pRoom->area->nplayer > 0 || count_obj_list(pObjIndex, pRoom->content_first) > 0) { last = false; break; } pObj = create_object(pObjIndex, Min(number_fuzzy(level), MAX_MORTAL_LEVEL - 1)); pObj->cost = 0; obj_to_room(pObj, pRoom); last = true; break; case 'P': if (!(pObjIndex = get_obj_index(pReset->arg1))) { bugf("Reset_room: 'P': bad vnum %ld.", pReset->arg1); continue; } if (!(pObjToIndex = get_obj_index(pReset->arg3))) { bugf("Reset_room: 'P': bad vnum %ld.", pReset->arg3); continue; } if (pReset->arg2 > 50) limit = 6; else if (pReset->arg2 == -1) limit = 999; else limit = pReset->arg2; if (pRoom->area->nplayer > 0 || (LastObj = get_obj_type(pObjToIndex)) == NULL || (LastObj->in_room == NULL && !last) || (pObjIndex->count >= limit) || (count = count_obj_list(pObjIndex, LastObj->content_first)) > pReset->arg4) { last = false; break; } while (count < pReset->arg4) { pObj = create_object(pObjIndex, number_fuzzy(LastObj->level)); obj_to_obj(pObj, LastObj); count++; if (pObjIndex->count >= limit) break; } LastObj->value[1] = LastObj->pIndexData->value[1]; last = true; break; case 'G': case 'E': if (!(pObjIndex = get_obj_index(pReset->arg1))) { bugf("Reset_room: 'E' or 'G': bad vnum %ld.", pReset->arg1); continue; } if (!last) break; if (!LastMob) { bugf("Reset_room: 'E' or 'G': null mob for vnum %ld.", pReset->arg1); last = false; break; } if (LastMob->pIndexData->pShop) { int olevel = 0, i, j; if (!pObjIndex->new_format) switch (pObjIndex->item_type) { default: olevel = 0; break; case ITEM_PILL: case ITEM_POTION: case ITEM_SCROLL: olevel = ANGEL; for (i = 1; i < 5; i++) { if (pObjIndex->value[i] > 0) { for (j = 0; j < top_class; j++) { olevel = Min(olevel, skill_table [pObjIndex->value[i]]. skill_level[j]); } } } olevel = Max(0, (olevel * 3 / 4) - 2); break; case ITEM_WAND: olevel = number_range(10, 20); break; case ITEM_STAFF: olevel = number_range(15, 25); break; case ITEM_ARMOR: olevel = number_range(5, 15); break; case ITEM_WEAPON: olevel = number_range(5, 15); break; case ITEM_TREASURE: olevel = number_range(10, 20); break; } pObj = create_object(pObjIndex, olevel); SetBit(pObj->extra_flags, ITEM_INVENTORY); } else { int plimit; if (pReset->arg2 > 50) plimit = 6; else if (pReset->arg2 == -1 || pReset->arg2 == 0) plimit = 999; else plimit = pReset->arg2; if (pObjIndex->count < plimit || number_range(0, 4) == 0) { pObj = create_object(pObjIndex, Min(number_fuzzy(level), MAX_MORTAL_LEVEL - 1)); } else break; } obj_to_char(pObj, LastMob); if (pReset->command == 'E') equip_char(LastMob, pObj, (wloc_t) pReset->arg3); last = true; break; case 'D': break; case 'R': if (!(pRoomIndex = get_room_index(pReset->arg1))) { bugf("Reset_room: 'R': bad vnum %ld.", pReset->arg1); continue; } { ExitData *pExit; int d0; int d1; switch (pReset->arg3) { default: for (d0 = 0; d0 < pReset->arg2 - 1; d0++) { d1 = number_range(d0, pReset->arg2 - 1); pExit = pRoomIndex->exit[d0]; pRoomIndex->exit[d0] = pRoomIndex->exit[d1]; pRoomIndex->exit[d1] = pExit; } break; case 1: add_random_exit(pRoomIndex, pReset, true); break; case 2: add_random_exit(pRoomIndex, pReset, false); break; } } break; } } return; } void reset_area(AreaData * pArea) { RoomIndex *pRoom; vnum_t vnum; for (vnum = pArea->min_vnum; vnum <= pArea->max_vnum; vnum++) { if ((pRoom = get_room_index(vnum))) reset_room(pRoom); } return; } CharData *create_mobile(CharIndex * pMobIndex) { CharData *mob; int i; AffectData af; mobile_count++; if (pMobIndex == NULL) { bug("Create_mobile: NULL pMobIndex."); exit(1); } mob = new_char(); mob->pIndexData = pMobIndex; mob->name = str_dup(pMobIndex->player_name); mob->short_descr = str_dup(pMobIndex->short_descr); mob->long_descr = str_dup(pMobIndex->long_descr); mob->description = str_dup(pMobIndex->description); mob->id = get_mob_id(); mob->spec_fun = pMobIndex->spec_fun; mob->prompt = NULL; mob->mprog_target = NULL; if (pMobIndex->wealth == 0) { mob->silver = 0; mob->gold = 0; } else { money_t wealth; wealth = number_range(pMobIndex->wealth / 2, 3 * pMobIndex->wealth / 2); mob->gold = number_range(wealth / 200, wealth / 100); mob->silver = wealth - (mob->gold * 100); } mob->act = pMobIndex->act; mob->affected_by = pMobIndex->affected_by; mob->alignment = pMobIndex->alignment; mob->level = pMobIndex->level; mob->hitroll = pMobIndex->hitroll; if (pMobIndex->random > 0) mob->level = number_range(Max(1, pMobIndex->level - pMobIndex->random), pMobIndex->level + pMobIndex->random); else mob->level = pMobIndex->level; mob->race = pMobIndex->race; mob->off_flags = pMobIndex->off_flags; mob->imm_flags = pMobIndex->imm_flags; mob->res_flags = pMobIndex->res_flags; mob->vuln_flags = pMobIndex->vuln_flags; mob->start_pos = pMobIndex->start_pos; mob->default_pos = pMobIndex->default_pos; mob->sex = pMobIndex->sex; if (mob->sex == SEX_RANDOM) mob->sex = (sex_t) number_range(SEX_MALE, SEX_FEMALE); mob->form = pMobIndex->form; mob->parts = pMobIndex->parts; if (pMobIndex->new_format) { mob->group = pMobIndex->group; mob->comm = COMM_NOCHANNELS | COMM_NOSHOUT | COMM_NOTELL; mob->damroll = pMobIndex->damage[DICE_BONUS]; mob->max_hit = dice(pMobIndex->hit[DICE_NUMBER], pMobIndex->hit[DICE_TYPE]) + pMobIndex->hit[DICE_BONUS]; mob->hit = mob->max_hit; mob->max_mana = dice(pMobIndex->mana[DICE_NUMBER], pMobIndex->mana[DICE_TYPE]) + pMobIndex->mana[DICE_BONUS]; mob->mana = mob->max_mana; mob->damage[DICE_NUMBER] = pMobIndex->damage[DICE_NUMBER]; mob->damage[DICE_TYPE] = pMobIndex->damage[DICE_TYPE]; mob->dam_type = pMobIndex->dam_type; if (mob->dam_type == 0) switch (number_range(1, 3)) { case (1): mob->dam_type = 3; break; case (2): mob->dam_type = 7; break; case (3): mob->dam_type = 11; break; } for (i = 0; i < MAX_AC; i++) mob->armor[i] = pMobIndex->ac[i]; mob->material = str_dup(pMobIndex->material); for (i = 0; i < STAT_MAX; i++) mob->perm_stat[i] = Min(25, 11 + mob->level / 4); { int stance = number_range(STANCE_NORMAL, STANCE_SWALLOW); SetStance(mob, STANCE_CURRENT, STANCE_NONE); SetStance(mob, STANCE_AUTODROP, stance); } if (IsSet(mob->act, ACT_WARRIOR)) { mob->perm_stat[STAT_STR] += 3; mob->perm_stat[STAT_INT] -= 1; mob->perm_stat[STAT_CON] += 2; } if (IsSet(mob->act, ACT_THIEF)) { mob->perm_stat[STAT_DEX] += 3; mob->perm_stat[STAT_INT] += 1; mob->perm_stat[STAT_WIS] -= 1; } if (IsSet(mob->act, ACT_CLERIC)) { mob->perm_stat[STAT_WIS] += 3; mob->perm_stat[STAT_DEX] -= 1; mob->perm_stat[STAT_STR] += 1; } if (IsSet(mob->act, ACT_MAGE)) { mob->perm_stat[STAT_INT] += 3; mob->perm_stat[STAT_STR] -= 1; mob->perm_stat[STAT_DEX] += 1; } if (IsSet(mob->off_flags, OFF_FAST)) mob->perm_stat[STAT_DEX] += 2; mob->perm_stat[STAT_STR] += mob->size - SIZE_MEDIUM; mob->perm_stat[STAT_CON] += (mob->size - SIZE_MEDIUM) / 2; if (IsAffected(mob, AFF_SANCTUARY)) { af.where = TO_AFFECTS; af.type = skill_lookup("sanctuary"); af.level = mob->level; af.duration = -1; af.location = APPLY_NONE; af.modifier = 0; af.bitvector = AFF_SANCTUARY; affect_to_char(mob, &af); } if (IsAffected(mob, AFF_HASTE)) { af.where = TO_AFFECTS; af.type = skill_lookup("haste"); af.level = mob->level; af.duration = -1; af.location = APPLY_DEX; af.modifier = 1 + (mob->level >= 18) + (mob->level >= 25) + (mob->level >= 32); af.bitvector = AFF_HASTE; affect_to_char(mob, &af); } if (IsAffected(mob, AFF_PROTECT_EVIL)) { af.where = TO_AFFECTS; af.type = skill_lookup("protection evil"); af.level = mob->level; af.duration = -1; af.location = APPLY_SAVES; af.modifier = -1; af.bitvector = AFF_PROTECT_EVIL; affect_to_char(mob, &af); } if (IsAffected(mob, AFF_PROTECT_GOOD)) { af.where = TO_AFFECTS; af.type = skill_lookup("protection good"); af.level = mob->level; af.duration = -1; af.location = APPLY_SAVES; af.modifier = -1; af.bitvector = AFF_PROTECT_GOOD; affect_to_char(mob, &af); } } else { mob->damroll = 0; mob->max_hit = mob->level * 8 + number_range(mob->level * mob->level / 4, mob->level * mob->level); mob->max_hit = mob->max_hit * 9 / 10; mob->hit = mob->max_hit; mob->max_mana = 100 + dice(mob->level, 10); mob->mana = mob->max_mana; switch (number_range(1, 3)) { case (1): mob->dam_type = 3; break; case (2): mob->dam_type = 7; break; case (3): mob->dam_type = 11; break; } for (i = 0; i < 3; i++) mob->armor[i] = interpolate(mob->level, 100, -100); mob->armor[3] = interpolate(mob->level, 100, 0); mob->size = SIZE_MEDIUM; mob->material = ""; for (i = 0; i < STAT_MAX; i++) mob->perm_stat[i] = 11 + mob->level / 4; } mob->position = mob->start_pos; Link(mob, char, next, prev); pMobIndex->count++; return mob; } void clone_mobile(CharData * parent, CharData * clone) { int i; AffectData *paf; if (parent == NULL || clone == NULL || !IsNPC(parent)) return; replace_str(&clone->name, parent->name); clone->version = parent->version; replace_str(&clone->short_descr, parent->short_descr); replace_str(&clone->long_descr, parent->long_descr); replace_str(&clone->description, parent->description); clone->group = parent->group; clone->sex = parent->sex; for (i = 0; i < MAX_MCLASS; i++) clone->Class[i] = parent->Class[i]; clone->race = parent->race; clone->level = parent->level; clone->trust = 0; clone->timer = parent->timer; clone->wait = parent->wait; clone->hit = parent->hit; clone->max_hit = parent->max_hit; clone->mana = parent->mana; clone->max_mana = parent->max_mana; clone->move = parent->move; clone->max_move = parent->max_move; clone->gold = parent->gold; clone->silver = parent->silver; clone->exp = parent->exp; clone->act = parent->act; clone->comm = parent->comm; clone->imm_flags = parent->imm_flags; clone->res_flags = parent->res_flags; clone->vuln_flags = parent->vuln_flags; clone->invis_level = parent->invis_level; clone->affected_by = parent->affected_by; clone->position = parent->position; clone->practice = parent->practice; clone->train = parent->train; clone->saving_throw = parent->saving_throw; clone->alignment = parent->alignment; clone->hitroll = parent->hitroll; clone->damroll = parent->damroll; clone->wimpy = parent->wimpy; clone->form = parent->form; clone->parts = parent->parts; clone->size = parent->size; replace_str(&clone->material, parent->material); clone->off_flags = parent->off_flags; clone->dam_type = parent->dam_type; clone->start_pos = parent->start_pos; clone->default_pos = parent->default_pos; clone->spec_fun = parent->spec_fun; for (i = 0; i < MAX_AC; i++) clone->armor[i] = parent->armor[i]; for (i = 0; i < STAT_MAX; i++) { clone->perm_stat[i] = parent->perm_stat[i]; clone->mod_stat[i] = parent->mod_stat[i]; } for (i = 0; i < 3; i++) clone->damage[i] = parent->damage[i]; for (paf = parent->affect_first; paf != NULL; paf = paf->next) affect_to_char(clone, paf); } ObjData *create_object(ObjIndex * pObjIndex, int level) { AffectData *paf; ObjData *obj; int i; if (pObjIndex == NULL) { bug("Create_object: NULL pObjIndex."); exit(1); } obj = new_obj(); obj->pIndexData = pObjIndex; obj->in_room = NULL; obj->enchanted = false; if (pObjIndex->new_format) obj->level = pObjIndex->level; else obj->level = Max(0, level); obj->wear_loc = WEAR_NONE; obj->name = str_dup(pObjIndex->name); obj->short_descr = str_dup(pObjIndex->short_descr); obj->description = str_dup(pObjIndex->description); obj->material = str_dup(pObjIndex->material); obj->item_type = pObjIndex->item_type; obj->extra_flags = pObjIndex->extra_flags; obj->wear_flags = pObjIndex->wear_flags; obj->value[0] = pObjIndex->value[0]; obj->value[1] = pObjIndex->value[1]; obj->value[2] = pObjIndex->value[2]; obj->value[3] = pObjIndex->value[3]; obj->value[4] = pObjIndex->value[4]; obj->weight = pObjIndex->weight; if (level == -1 || pObjIndex->new_format) obj->cost = pObjIndex->cost; else obj->cost = number_fuzzy(10) * number_fuzzy(level) * number_fuzzy(level); switch (obj->item_type) { default: bugf("Read_object: vnum %ld bad type.", pObjIndex->vnum); break; case ITEM_LIGHT: if (obj->value[2] == 999) obj->value[2] = -1; break; case ITEM_FURNITURE: case ITEM_TRASH: case ITEM_CONTAINER: case ITEM_DRINK_CON: case ITEM_KEY: case ITEM_FOOD: case ITEM_BOAT: case ITEM_CORPSE_NPC: case ITEM_CORPSE_PC: case ITEM_FOUNTAIN: case ITEM_MAP: case ITEM_CLOTHING: case ITEM_PORTAL: if (!pObjIndex->new_format) obj->cost /= 5; break; case ITEM_TREASURE: case ITEM_WARP_STONE: case ITEM_ROOM_KEY: case ITEM_GEM: case ITEM_JEWELRY: break; case ITEM_JUKEBOX: for (i = 0; i < 5; i++) obj->value[i] = -1; break; case ITEM_SCROLL: if (level != -1 && !pObjIndex->new_format) obj->value[0] = number_fuzzy(obj->value[0]); break; case ITEM_WAND: case ITEM_STAFF: if (level != -1 && !pObjIndex->new_format) { obj->value[0] = number_fuzzy(obj->value[0]); obj->value[1] = number_fuzzy(obj->value[1]); obj->value[2] = obj->value[1]; } if (!pObjIndex->new_format) obj->cost *= 2; break; case ITEM_WEAPON: if (level != -1 && !pObjIndex->new_format) { obj->value[1] = number_fuzzy(number_fuzzy(1 * level / 4 + 2)); obj->value[2] = number_fuzzy(number_fuzzy(3 * level / 4 + 6)); } break; case ITEM_ARMOR: if (level != -1 && !pObjIndex->new_format) { obj->value[0] = number_fuzzy(level / 5 + 3); obj->value[1] = number_fuzzy(level / 5 + 3); obj->value[2] = number_fuzzy(level / 5 + 3); } break; case ITEM_POTION: case ITEM_PILL: if (level != -1 && !pObjIndex->new_format) obj->value[0] = number_fuzzy(number_fuzzy(obj->value[0])); break; case ITEM_MONEY: if (!pObjIndex->new_format) obj->value[0] = obj->cost; break; } for (paf = pObjIndex->affect_first; paf != NULL; paf = paf->next) if (paf->location == APPLY_SPELL_AFFECT) affect_to_obj(obj, paf); Link(obj, obj, next, prev); pObjIndex->count++; return obj; } void clone_object(ObjData * parent, ObjData * clone) { int i; AffectData *paf; ExDescrData *ed, *ed_new; if (parent == NULL || clone == NULL) return; replace_str(&clone->name, parent->name); replace_str(&clone->short_descr, parent->short_descr); replace_str(&clone->description, parent->description); clone->item_type = parent->item_type; clone->extra_flags = parent->extra_flags; clone->wear_flags = parent->wear_flags; clone->weight = parent->weight; clone->cost = parent->cost; clone->level = parent->level; clone->condition = parent->condition; replace_str(&clone->material, parent->material); clone->timer = parent->timer; for (i = 0; i < 5; i++) clone->value[i] = parent->value[i]; clone->enchanted = parent->enchanted; for (paf = parent->affect_first; paf != NULL; paf = paf->next) affect_to_obj(clone, paf); for (ed = parent->ed_first; ed != NULL; ed = ed->next) { ed_new = new_ed(); ed_new->keyword = str_dup(ed->keyword); ed_new->description = str_dup(ed->description); Link(ed_new, clone->ed, next, prev); } } const char *get_ed(const char *name, ExDescrData * ed) { for (; ed != NULL; ed = ed->next) { if (is_name(name, ed->keyword)) return ed->description; } return NULL; } CharIndex *get_char_index(vnum_t vnum) { CharIndex *pMobIndex; for (pMobIndex = char_index_hash[vnum % MAX_KEY_HASH]; pMobIndex != NULL; pMobIndex = pMobIndex->next) { if (pMobIndex->vnum == vnum) return pMobIndex; } if (run_level == RUNLEVEL_BOOTING) { bugf("Get_char_index: bad vnum %ld.", vnum); exit(1); } return NULL; } ObjIndex *get_obj_index(vnum_t vnum) { ObjIndex *pObjIndex; for (pObjIndex = obj_index_hash[vnum % MAX_KEY_HASH]; pObjIndex != NULL; pObjIndex = pObjIndex->next) { if (pObjIndex->vnum == vnum) return pObjIndex; } if (run_level == RUNLEVEL_BOOTING) { bugf("Get_obj_index: bad vnum %ld.", vnum); exit(1); } return NULL; } RoomIndex *get_room_index(vnum_t vnum) { RoomIndex *pRoomIndex; for (pRoomIndex = room_index_hash[vnum % MAX_KEY_HASH]; pRoomIndex != NULL; pRoomIndex = pRoomIndex->next) { if (pRoomIndex->vnum == vnum) return pRoomIndex; } if (run_level == RUNLEVEL_BOOTING) { bugf("Get_room_index: bad vnum %ld.", vnum); exit(1); } return NULL; } ProgCode *get_prog_index(vnum_t vnum, prog_t type) { ProgCode *prg; switch (type) { case PRG_MPROG: prg = mprog_first; break; case PRG_OPROG: prg = oprog_first; break; case PRG_RPROG: prg = rprog_first; break; default: return NULL; } for (; prg; prg = prg->next) { if (prg->vnum == vnum) return (prg); } return NULL; } flag_t flag_convert(char letter) { flag_t bitsum = 0; char i; if ('A' <= letter && letter <= 'Z') { bitsum = ((flag_t) 1 << 0); for (i = letter; i > 'A'; i--) bitsum <<= 1; } else if ('a' <= letter && letter <= 'z') { bitsum = ((flag_t) 1 << 26); for (i = letter; i > 'a'; i--) bitsum <<= 1; } return bitsum; } const char *str_dup(const char *pstr) { if (NullStr(pstr)) return &str_empty[0]; sAllocString += strlen(pstr); nAllocString += 1; return strdup(pstr); } const char *str_dupf(const char *pstr, ...) { va_list args; char str_new[MPL]; if (NullStr(pstr)) return &str_empty[0]; va_start(args, pstr); sAllocString += vsnprintf(str_new, sizeof(str_new), pstr, args); va_end(args); nAllocString += 1; return strdup(str_new); } void replace_str(const char **pstr, const char *nstr) { free_string(*pstr); if (NullStr(nstr)) *pstr = &str_empty[0]; else { sAllocString += strlen(nstr); nAllocString += 1; *pstr = strdup(nstr); } } void replace_strf(const char **pstr, const char *nstr, ...) { va_list args; char str_new[MPL]; free_string(*pstr); if (NullStr(nstr)) { *pstr = &str_empty[0]; return; } va_start(args, nstr); sAllocString += vsnprintf(str_new, sizeof(str_new), nstr, args); va_end(args); nAllocString += 1; *pstr = strdup(str_new); } void free_string(const char *pstr) { if (NullStr(pstr)) return; sAllocString -= strlen(pstr); nAllocString -= 1; free_mem(pstr); return; } void newarea_insert_level_sort(AreaData * a) { AreaData *lsort = area_first_sorted; AreaData *lsort_prev = NULL; if (!area_first_sorted) { area_first_sorted = a; return; } for (; lsort; lsort_prev = lsort, lsort = lsort->next_sort) { if (NullStr(a->lvl_comment)) { if (NullStr(lsort->lvl_comment)) { if (lsort->min_level > 0) { if (a->min_level <= 0 || a->min_level > lsort->min_level) { continue; } if (a->min_level == lsort->min_level && a->max_level > lsort->max_level) { continue; } } else { if (a->min_level < lsort->min_level) { continue; } } } } else { int i; if (NullStr(lsort->lvl_comment)) { continue; } i = str_cmp(a->lvl_comment, lsort->lvl_comment); if (i > 0) { continue; } if (i == 0 && str_cmp(a->name, lsort->name) > 0) { continue; } } if (lsort_prev) { a->next_sort = lsort; lsort_prev->next_sort = a; } else { a->next_sort = area_first_sorted; area_first_sorted = a; } return; } lsort_prev->next_sort = a; } void add_area(AreaData * pArea) { newarea_insert_level_sort(pArea); Link(pArea, area, next, prev); } void unlink_area(AreaData * pArea) { UnlinkSingle(pArea, AreaData, area_first_sorted, next_sort); UnLink(pArea, area, next, prev); } const char *print_area_levels(AreaData * pArea) { static char buf[8]; char low[4], high[4]; if (!NullStr(pArea->lvl_comment)) return str_align(7, Center, pArea->lvl_comment); if (pArea->min_level >= LEVEL_HERO && pArea->max_level >= LEVEL_HERO) return str_align(7, Center, "HERO+"); if (pArea->min_level >= LEVEL_HERO) strncpy(low, "HRO", sizeof(low)); else snprintf(low, sizeof(low), "%03d", pArea->min_level); if (pArea->max_level >= LEVEL_HERO) strncpy(high, "HRO", sizeof(high)); else snprintf(high, sizeof(high), "%03d", pArea->max_level); snprintf(buf, sizeof(buf), "%s %s", low, high); return buf; } int convert_level(const char *arg) { if (NullStr(arg)) return 0; else if (is_number(arg)) return atoi(arg); else if (is_name("IMM", arg)) return LEVEL_IMMORTAL; else if (is_name("HERO", arg) || is_name("HRO", arg)) return MAX_MORTAL_LEVEL; else return 0; } Do_Fun(do_areas) { AreaData *pArea; Buffer *output; int lo_lv, hi_lv, count; char arg1[MIL], arg2[MIL]; lo_lv = 0; hi_lv = 0; count = 0; if (!NullStr(argument)) { argument = one_argument(argument, arg1); one_argument(argument, arg2); lo_lv = convert_level(arg1); hi_lv = convert_level(arg2); } lo_lv = lo_lv > 0 ? Range(1, lo_lv, MAX_LEVEL) : 0; hi_lv = hi_lv > 0 ? Range(1, hi_lv, MAX_LEVEL) : MAX_LEVEL; output = new_buf(); bprintlnf(output, NEWLINE "{W%s{x", stringf(ch, 0, Center, "oO", "[ {RAREAS ON %s{W ]", strupper(mud_info.name))); for (pArea = area_first_sorted; pArea != NULL; pArea = pArea->next_sort) { if (pArea->max_level <= hi_lv && pArea->min_level >= lo_lv && !AreaFlag(pArea, AREA_CLOSED)) { if (!MudFlag(DISABLE_AREA_DIRECTIONS)) { bprintlnf(output, "%s{W[{B%-7s{W] {r%s {C%-23s {W({M%s{W){x", (AreaClan(pArea) != CharClan(ch)) ? "{G*" : " ", print_area_levels(pArea), str_width(7, pArea->credits), pArea->name, path_to_area(ch, pArea)); } else { bprintlnf(output, "%s{W[{B%-7s{W] {r%s {C%s{x", (AreaClan(pArea) != CharClan(ch)) ? "{G*" : " ", print_area_levels(pArea), str_width(7, pArea->credits), pArea->name); } count++; } } if (!count) { bprintlnf(output, "{W%s{x", stringf(ch, 0, Center, "oO", "[ {RNo areas meeting those criteria.{W ]")); } else { bprintlnf(output, "{W%s{x", stringf(ch, 0, Center, "oO", "[ {R%d areas found{W ]", count)); bprintln(output, "{G*{x = Area has restrictions that affect you.{x"); bprintln(output, "All directions are from your current position."); } sendpage(ch, buf_string(output)); free_buf(output); return; } void examine_crash_log(void) { FileData *fp; char date[MIL]; EXTERN time_t last_crash; fp = f_open(CRASH_FILE, "r"); if (!fp) { return; } last_crash = read_long(fp); unlink(CRASH_FILE); sprintf(date, "Crash Log %s", str_time(-1, -1, "%D")); make_note("Immortal", "System", "Imm", date, 5, fp->str, NULL, NULL); f_close(fp); } int number_fuzzy(int number) { switch (number_bits(2)) { case 0: number -= 1; break; case 3: number += 1; break; } return Max(1, number); } int number_fuzzier(int number) { switch (number_bits(2)) { case 0: number -= 2; break; case 1: number -= 1; break; case 3: number += 1; break; case 4: number += 2; break; } return Max(1, number); } int number_range(int from, int to) { int power; int number; if (from == 0 && to == 0) return 0; if ((to = to - from + 1) <= 1) return from; for (power = 2; power < to; power <<= 1) ; while ((number = number_mm() & (power - 1)) >= to) ; return from + number; } int number_percent(void) { int percent; while ((percent = number_mm() & (128 - 1)) > 99) ; return 1 + percent; } int level_percent(void) { return number_range(1, MAX_MORTAL_LEVEL); } int number_door(void) { int door; while ((door = number_mm() & (8 - 1)) > 5) ; return door; } int number_bits(int width) { return number_mm() & ((1 << width) - 1); } #ifdef OLD_RAND static int rgiState[2 + 55]; #endif void init_mm() { log_string("Starting random number generator..."); #ifdef OLD_RAND int *piState; int iState; piState = &rgiState[2]; piState[-2] = 55 - 55; piState[-1] = 55 - 24; piState[0] = ((int) current_time) & ((1 << 30) - 1); piState[1] = 1; for (iState = 2; iState < 55; iState++) { piState[iState] = (piState[iState - 1] + piState[iState - 2]) & ((1 << 30) - 1); } #else srandom(time(NULL) ^ getpid()); #endif return; } long number_mm(void) { #ifdef OLD_RAND int *piState; int iState1; int iState2; int iRand; piState = &rgiState[2]; iState1 = piState[-2]; iState2 = piState[-1]; iRand = (piState[iState1] + piState[iState2]) & ((1 << 30) - 1); piState[iState1] = iRand; if (++iState1 == 55) iState1 = 0; if (++iState2 == 55) iState2 = 0; piState[-2] = iState1; piState[-1] = iState2; return iRand >> 6; #else return random() >> 6; #endif } int dice(int number, int size) { int idice; int sum; switch (size) { case 0: return 0; case 1: return number; } for (idice = 0, sum = 0; idice < number; idice++) sum += number_range(1, size); return sum; } int interpolate(int level, int value_00, int value_32) { return value_00 + level * (value_32 - value_00) / 32; } int str_cmp(const char *astr, const char *bstr) { if (astr == NULL) return bstr == NULL ? 0 : -1; if (bstr == NULL) return 1; return strcasecmp(astr, bstr); } int str_casecmp(const char *astr, const char *bstr) { if (astr == NULL) return bstr == NULL ? 0 : -1; if (bstr == NULL) return 1; return strcmp(astr, bstr); } int str_ncmp(const char *astr, const char *bstr, size_t len) { if (astr == NULL) return bstr == NULL ? 0 : -1; if (bstr == NULL) return 1; return strncasecmp(astr, bstr, len); } int str_ncasecmp(const char *astr, const char *bstr, size_t len) { if (astr == NULL) return bstr == NULL ? 0 : -1; if (bstr == NULL) return 1; return strncmp(astr, bstr, len); } bool str_prefix(const char *astr, const char *bstr) { if (astr == NULL) { bug("Str_prefix: null astr."); return true; } if (bstr == NULL) { bug("Str_prefix: null bstr."); return true; } for (; *astr; astr++, bstr++) { if (tolower(*astr) != tolower(*bstr)) return true; } return false; } bool str_infix(const char *astr, const char *bstr) { int sstr1; int sstr2; int ichar; char c0; if ((c0 = tolower(astr[0])) == '\0') return false; sstr1 = strlen(astr); sstr2 = strlen(bstr); for (ichar = 0; ichar <= sstr2 - sstr1; ichar++) { if (c0 == tolower(bstr[ichar]) && !str_prefix(astr, bstr + ichar)) return false; } return true; } bool str_suffix(const char *astr, const char *bstr) { int sstr1; int sstr2; sstr1 = strlen(astr); sstr2 = strlen(bstr); if (sstr1 <= sstr2 && !str_cmp(astr, bstr + sstr2 - sstr1)) return false; else return true; } const char *Upper(const char *str) { size_t i; static char up[3][MSL * 2]; static int u; if (NullStr(str)) return ""; u++; u %= 3; strcpy(up[u], str); i = skipcol(up[u]); up[u][i] = toupper(up[u][i]); return up[u]; } const char *Lower(const char *str) { size_t i; static char low[3][MSL * 2]; static int l; if (NullStr(str)) return ""; l++; l %= 3; strcpy(low[l], str); i = skipcol(low[l]); low[l][i] = tolower(low[l][i]); return low[l]; } char *capitalize(const char *str) { static char result[5][MSL * 5]; static int i; size_t c; if (NullStr(str)) return ""; i++; i %= 5; strcpy(result[i], strlower(str)); c = skipcol(result[i]); result[i][c] = toupper(result[i][c]); return result[i]; } char *strlower(const char *str) { static char strlow[5][MSL * 5]; static int s; char *result; size_t i; if (NullStr(str)) return ""; s++; s %= 5; result = strlow[s]; for (i = 0; str[i] != NUL; i++) { if (str[i] == COLORCODE) { int k = ansi_skip(&str[i]); while (k-- > 0) result[i] = str[i++]; } else if (str[i] == CUSTOMSTART) { do { result[i] = str[i]; i++; } while (str[i] != NUL && str[i] != CUSTOMEND); } else if (str[i] == MXP_BEGc) { do { result[i] = str[i]; i++; } while (str[i] != NUL && str[i] != MXP_ENDc); } else result[i] = isalpha(str[i]) ? tolower(str[i]) : str[i]; } result[i] = NUL; return result; } char *strupper(const char *str) { static char strup[5][MSL * 5]; static int s; char *result; size_t i; if (NullStr(str)) return ""; s++; s %= 5; result = strup[s]; for (i = 0; str[i] != NUL; i++) { if (str[i] == COLORCODE) { int k = ansi_skip(&str[i]); while (k-- > 0) result[i] = str[i++]; } else if (str[i] == CUSTOMSTART) { do { result[i] = str[i]; i++; } while (str[i] != NUL && str[i] != CUSTOMEND); } else if (str[i] == MXP_BEGc) { do { result[i] = str[i]; i++; } while (str[i] != NUL && str[i] != MXP_ENDc); } else result[i] = isalpha(str[i]) ? toupper(str[i]) : str[i]; } result[i] = NUL; return result; } bool isavowel(char letter) { char c; c = tolower(letter); if (c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u') return true; else return false; } char *aoran(const char *str) { static char temp[MAX_STRING_LENGTH]; if (NullStr(str)) return ""; if (isavowel(str[0]) || (strlen(str) > 1 && tolower(str[0]) == 'y' && !isavowel(str[1]))) strcpy(temp, "an "); else strcpy(temp, "a "); strcat(temp, str); return temp; } void append_file(const char *file, const char *str, bool newline) { FILE *fp; if (NullStr(str) || NullStr(file)) return; if ((fp = file_open(file, "a")) == NULL) { log_error(file); } else { if (newline) fprintf(fp, "%s" LF, str); else fprintf(fp, "%s", str); } file_close(fp); } void bug(const char *str) { char buf[MAX_STRING_LENGTH]; if (fpArea != NULL) { size_t iLine, iChar; char c; iChar = f_tell(fpArea); f_seek(fpArea, 0, SEEK_SET); for (iLine = 0; (size_t) f_tell(fpArea) < iChar; iLine++) { while ((c = f_getc(fpArea)) != '\n' && c != EOF) ; } f_seek(fpArea, iChar, SEEK_SET); logf("[*****] FILE: %s LINE: %d", strArea, iLine); } sprintf(buf, "[*****] BUG: %s", str); if (run_level == RUNLEVEL_MAIN_LOOP) { wiznet(buf, NULL, NULL, WIZ_BUGS, true, 0); } else log_string(buf); return; } void tail_chain(void) { return; } char *casemix(const char *str) { static char out[4][MSL]; static int o; char *result; size_t i; bool wascap = false; if (NullStr(str)) return ""; ++o, o %= 4; result = out[o]; for (i = 0; str[i] != NUL; i++) { if (isalpha(str[i])) { if (wascap) result[i] = tolower(str[i]); else result[i] = toupper(str[i]); wascap = !wascap; } else { result[i] = str[i]; } } result[i] = NUL; return (result); }