/**************************************************************************** * [S]imulated [M]edieval [A]dventure multi[U]ser [G]ame | * * -----------------------------------------------------------| \\._.// * * SmaugWiz (C) 1998 by Russ Pillsbury (Windows NT version) | (0...0) * * -----------------------------------------------------------| ).:.( * * SMAUG (C) 1994, 1995, 1996 by Derek Snider | {o o} * * -----------------------------------------------------------| / ' ' \ * * SMAUG code team: Thoric, Altrag, Blodkai, Narn, Haus, |~'~.VxvxV.~'~* * Scryn, Swordbearer, Rennard, Tricops, and Gorog. | * * ------------------------------------------------------------------------ * * Merc 2.1 Diku Mud improvments copyright (C) 1992, 1993 by Michael * * Chastain, Michael Quan, and Mitchell Tse. * * Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, * * Michael Seifert, Hans Henrik Staerfeldt, Tom Madsen, and Katja Nyboe. * * ------------------------------------------------------------------------ * * Database management module * ****************************************************************************/ #include "stdafx.h" #include "smaug.h" #include "Smaugx.h" #include "SysData.h" #include "skill.h" #include "social.h" #include "commands.h" #include "mobiles.h" #include "objects.h" #include "rooms.h" #include "deity.h" #include "area.h" #include "boards.h" #include "auction.h" #include "help.h" #include "races.h" #include "class.h" #include "SmaugWizDoc.h" #include "SmaugFiles.h" #include "descriptor.h" #include "character.h" #include "Language.h" #include "Exits.h" #include "ObjectMenu.h" int gAcount; void init_supermob (); // Globals. int nAllocString; int sAllocString; int nAllocPerm; int sAllocPerm; CWizData *first_wiz; CWizData *last_wiz; CHelpData *first_help; CHelpData *last_help; CShopData *first_shop; CShopData *last_shop; CRepairShopData *first_repair; CRepairShopData *last_repair; CTeleportData *first_teleport; CTeleportData *last_teleport; CObjData *extracted_obj_queue; CExtractedCharData *extracted_char_queue; char bug_buf [2*MAX_INPUT_LENGTH]; CCharacter *first_char; CCharacter *last_char; char log_buf [2*MAX_INPUT_LENGTH]; time_info_data time_info; CWeatherData weather_info; int cur_qchars; int nummobsloaded; CAuctionData *auction; // auctions // weaponry short gsn_pugilism; short gsn_long_blades; short gsn_short_blades; short gsn_flexible_arms; short gsn_talonous_arms; short gsn_bludgeons; short gsn_shieldwork; short gsn_missile_weapons; // thief short gsn_detrap; short gsn_backstab; short gsn_circle; short gsn_dodge; short gsn_hide; short gsn_peek; short gsn_pick_lock; short gsn_sneak; short gsn_steal; short gsn_gouge; short gsn_poison_weapon; // thief & warrior short gsn_disarm; short gsn_enhanced_damage; short gsn_kick; short gsn_parry; short gsn_rescue; short gsn_second_attack; short gsn_third_attack; short gsn_fourth_attack; short gsn_fifth_attack; short gsn_dual_wield; short gsn_punch; short gsn_bash; short gsn_stun; short gsn_bashdoor; short gsn_grip; short gsn_berserk; short gsn_hitall; short gsn_tumble; // vampire short gsn_feed; short gsn_bloodlet; short gsn_broach; short gsn_mistwalk; // other short gsn_aid; short gsn_track; short gsn_search; short gsn_dig; short gsn_mount; short gsn_bite; short gsn_claw; short gsn_sting; short gsn_tail; short gsn_scribe; short gsn_brew; short gsn_climb; short gsn_cook; short gsn_scan; short gsn_slice; // spells short gsn_aqua_breath; short gsn_blindness; short gsn_charm_person; short gsn_curse; short gsn_invis; short gsn_mass_invis; short gsn_poison; short gsn_sleep; short gsn_possess; short gsn_fireball; short gsn_chill_touch; short gsn_lightning_bolt; // languages short gsn_common; short gsn_elven; short gsn_dwarven; short gsn_pixie; short gsn_ogre; short gsn_orcish; short gsn_trollish; short gsn_goblin; short gsn_halfling; // for searching short gsn_first_spell; short gsn_first_skill; short gsn_first_weapon; short gsn_first_tongue; short gsn_top_sn; // styles short gsn_style_evasive; short gsn_style_defensive; short gsn_style_standard; short gsn_style_aggressive; short gsn_style_berserk; CAreaData *first_build; CAreaData *last_build; CAreaData *first_bsort; CAreaData *last_bsort; // Locals. int top_affect; int top_ed; int top_exit; int top_shop; int top_repair; int top_vroom; // Semi-locals. BOOL fBootDb, bBootLog; FILE *fpArea; char strArea [MAX_INPUT_LENGTH]; // Local booting procedures. void init_mm (); void load_area (FILE *fp); void load_reserved (); void load_buildlist (); void load_banlist (); void initialize_economy (); void ShowConflicts (CCharacter* ch, CPtrList& List, int low, int hi, BOOL bRoom, BOOL bMob, BOOL bObj); // MUDprogram locals void FixRoomExits (CRoomIndexData& Ri, BOOL bBoot); void remap_slot_numbers (); void shutdown_mud (char *reason) { FILE *fp; if ((fp = fopen (FileTable.GetName (SM_SHUTDOWN_FILE), "a")) != NULL) { fprintf (fp, "%s\n", reason); fclose (fp); } } // Big mama top level function. void boot_db () { short wear, x; TRY { remove (FileTable.GetName (SM_BOOTLOG_FILE)); bBootLog = FALSE; gpDoc->LogString ("Loading SysData configuration...", LOG_BOOT); if (! SysData.Load ()) gpDoc->LogString ("Not found. Creating new configuration.", LOG_BOOT); gpDoc->LogString ("Loading commands", LOG_BOOT); CommandTable.Load (); gpDoc->LogString ("Loading languages", LOG_BOOT); LanguageTable.Load (); gpDoc->LogString ("Loading socials", LOG_BOOT); SocialTable.Load (); gpDoc->LogString ("Loading skill table", LOG_BOOT); load_skill_table (); SkillTable.Sort (); remap_slot_numbers (); // must be after the sort gsn_first_spell = 0; gsn_first_skill = 0; gsn_first_weapon = 0; gsn_first_tongue = 0; gsn_top_sn = SkillTable.GetCount (); for (x = 0; x < SkillTable.GetCount (); x++) if (!gsn_first_spell && SkillTable.GetType (x) == SKILL_SPELL) gsn_first_spell = x; else if (!gsn_first_skill && SkillTable.GetType (x) == SKILL_SKILL) gsn_first_skill = x; else if (!gsn_first_weapon && SkillTable.GetType (x) == SKILL_WEAPON) gsn_first_weapon = x; else if (!gsn_first_tongue && SkillTable.GetType (x) == SKILL_TONGUE) gsn_first_tongue = x; gpDoc->LogString ("Loading classes", LOG_BOOT); ClassTable.Load (); gpDoc->LogString ("Loading races", LOG_BOOT); RaceTable.Load (); gpDoc->LogString ("Loading herb table", LOG_BOOT); load_herb_table (); gpDoc->LogString ("Making wizlist", LOG_BOOT); make_wizlist (); gpDoc->LogString ("Initializing request pipe", LOG_BOOT); init_request_pipe (); fBootDb = TRUE; nummobsloaded = 0; first_char = NULL; last_char = NULL; first_shop = NULL; last_shop = NULL; first_repair = NULL; last_repair = NULL; first_teleport = NULL; last_teleport = NULL; extracted_obj_queue = NULL; extracted_char_queue= NULL; cur_qchars = 0; cur_char = NULL; cur_obj = 0; cur_obj_serial = 0; cur_char_died = FALSE; cur_obj_extracted = FALSE; cur_room = NULL; quitting_char = NULL; loading_char = NULL; saving_char = NULL; auction = new CAuctionData; for (wear = 0; wear < MAX_WEAR; wear++) for (x = 0; x < MAX_LAYERS; x++) save_equipment [wear][x] = NULL; // Init random number generator. gpDoc->LogString ("Initializing random number generator", LOG_BOOT); init_mm (); // Set time and weather. gpDoc->LogString ("Setting time and weather", LOG_BOOT); long lhour, lday, lmonth; lhour = (CurrentTime.GetTotalSeconds () - 650336715) / (PULSE_TICK / PULSE_PER_SECOND); time_info.hour = lhour % 24; lday = lhour / 24; time_info.day = lday % 35; lmonth = lday / 35; time_info.month = lmonth % 17; time_info.year = lmonth / 17; if (time_info.hour < 5) then weather_info.sunlight = SUN_DARK; else if (time_info.hour < 6) then weather_info.sunlight = SUN_RISE; else if (time_info.hour < 19) then weather_info.sunlight = SUN_LIGHT; else if (time_info.hour < 20) then weather_info.sunlight = SUN_SET; else weather_info.sunlight = SUN_DARK; weather_info.change = 0; weather_info.mmhg = 960; if (time_info.month >= 7 && time_info.month <=12) weather_info.mmhg += number_range (1, 50); else weather_info.mmhg += number_range (1, 80); if (weather_info.mmhg <= 980) then weather_info.sky = SKY_LIGHTNING; else if (weather_info.mmhg <= 1000) then weather_info.sky = SKY_RAINING; else if (weather_info.mmhg <= 1020) then weather_info.sky = SKY_CLOUDY; else weather_info.sky = SKY_CLOUDLESS; // Assign gsn's for skills which need them. gpDoc->LogString ("Assigning gsn's", LOG_BOOT); ASSIGN_GSN (gsn_style_evasive, "evasive style"); ASSIGN_GSN (gsn_style_defensive, "defensive style"); ASSIGN_GSN (gsn_style_standard, "standard style"); ASSIGN_GSN (gsn_style_aggressive, "aggressive style"); ASSIGN_GSN (gsn_style_berserk, "berserk style"); ASSIGN_GSN (gsn_pugilism, "pugilism"); ASSIGN_GSN (gsn_long_blades, "long blades"); ASSIGN_GSN (gsn_short_blades, "short blades"); ASSIGN_GSN (gsn_flexible_arms, "flexible arms"); ASSIGN_GSN (gsn_talonous_arms, "talonous arms"); ASSIGN_GSN (gsn_bludgeons, "bludgeons"); ASSIGN_GSN (gsn_missile_weapons,"missile weapons"); ASSIGN_GSN (gsn_shieldwork, "shieldwork"); ASSIGN_GSN (gsn_detrap, "detrap"); ASSIGN_GSN (gsn_backstab, "backstab"); ASSIGN_GSN (gsn_circle, "circle"); ASSIGN_GSN (gsn_tumble, "tumble"); ASSIGN_GSN (gsn_dodge, "dodge"); ASSIGN_GSN (gsn_hide, "hide"); ASSIGN_GSN (gsn_peek, "peek"); ASSIGN_GSN (gsn_pick_lock, "pick lock"); ASSIGN_GSN (gsn_sneak, "sneak"); ASSIGN_GSN (gsn_steal, "steal"); ASSIGN_GSN (gsn_gouge, "gouge"); ASSIGN_GSN (gsn_poison_weapon, "poison weapon"); ASSIGN_GSN (gsn_disarm, "disarm"); ASSIGN_GSN (gsn_enhanced_damage, "enhanced damage"); ASSIGN_GSN (gsn_kick, "kick"); ASSIGN_GSN (gsn_parry, "parry"); ASSIGN_GSN (gsn_rescue, "rescue"); ASSIGN_GSN (gsn_second_attack, "second attack"); ASSIGN_GSN (gsn_third_attack, "third attack"); ASSIGN_GSN (gsn_fourth_attack, "fourth attack"); ASSIGN_GSN (gsn_fifth_attack, "fifth attack"); ASSIGN_GSN (gsn_dual_wield, "dual wield"); ASSIGN_GSN (gsn_punch, "punch"); ASSIGN_GSN (gsn_bash, "bash"); ASSIGN_GSN (gsn_stun, "stun"); ASSIGN_GSN (gsn_bashdoor, "doorbash"); ASSIGN_GSN (gsn_grip, "grip"); ASSIGN_GSN (gsn_berserk, "berserk"); ASSIGN_GSN (gsn_hitall, "hitall"); ASSIGN_GSN (gsn_feed, "feed"); ASSIGN_GSN (gsn_bloodlet, "bloodlet"); ASSIGN_GSN (gsn_broach, "broach"); ASSIGN_GSN (gsn_mistwalk, "mistwalk"); ASSIGN_GSN (gsn_aid, "aid"); ASSIGN_GSN (gsn_track, "track"); ASSIGN_GSN (gsn_search, "search"); ASSIGN_GSN (gsn_dig, "dig"); ASSIGN_GSN (gsn_mount, "mount"); ASSIGN_GSN (gsn_bite, "bite"); ASSIGN_GSN (gsn_claw, "claw"); ASSIGN_GSN (gsn_sting, "sting"); ASSIGN_GSN (gsn_tail, "tail"); ASSIGN_GSN (gsn_scribe, "scribe"); ASSIGN_GSN (gsn_brew, "brew"); ASSIGN_GSN (gsn_climb, "climb"); ASSIGN_GSN (gsn_cook, "cook"); ASSIGN_GSN (gsn_scan, "scan"); ASSIGN_GSN (gsn_slice, "slice"); ASSIGN_GSN (gsn_fireball, "fireball"); ASSIGN_GSN (gsn_chill_touch, "chill touch"); ASSIGN_GSN (gsn_lightning_bolt, "lightning bolt"); ASSIGN_GSN (gsn_aqua_breath, "aqua breath"); ASSIGN_GSN (gsn_blindness, "blindness"); ASSIGN_GSN (gsn_charm_person, "charm person"); ASSIGN_GSN (gsn_curse, "curse"); ASSIGN_GSN (gsn_invis, "invis"); ASSIGN_GSN (gsn_mass_invis, "mass invis"); ASSIGN_GSN (gsn_poison, "poison"); ASSIGN_GSN (gsn_sleep, "sleep"); ASSIGN_GSN (gsn_possess, "possess"); ASSIGN_GSN (gsn_common, "common"); ASSIGN_GSN (gsn_elven, "elven"); ASSIGN_GSN (gsn_dwarven, "dwarven"); ASSIGN_GSN (gsn_pixie, "pixie"); ASSIGN_GSN (gsn_ogre, "ogre"); ASSIGN_GSN (gsn_orcish, "orcish"); ASSIGN_GSN (gsn_trollish, "trollese"); ASSIGN_GSN (gsn_goblin, "goblin"); ASSIGN_GSN (gsn_halfling, "halfling"); // Read in all the area files. FILE *fpList; gpDoc->LogString ("Reading in area files...", LOG_BOOT); if (! (fpList = fopen (FileTable.GetName (SM_AREA_LIST), "r"))) { perror (AREA_LIST); shutdown_mud ("Unable to open area list"); ThrowSmaugException (SE_AREA); } for (;;) { CString Fname = fread_line (fpList); if (strchr (Fname, '$')) break; int pos = Fname.Find (".are"); if (pos > 0) { Fname.GetBufferSetLength (pos); // drop the ".are" CAreaData *pArea = LoadAreaFile (Fname, BOOT); if (pArea) AddArea (pArea); } } fclose (fpList); // initialize supermob. - must be done before reset_area! init_supermob (); CObjectMenu::InitObjectMenu (); // Fix up exits. // Declare db booting over. // Reset all areas once. // Load up the notes file. fix_exits (); fBootDb = FALSE; initialize_economy (); gpDoc->LogString ("Resetting areas...", LOG_BOOT); area_update (); load_buildlist (); BoardList.Load (); load_clans (); load_councils (); load_deities (); load_banlist (); load_reserved( ); load_corpses (); MOBtrigger = TRUE; } CATCH (CException, ex) { bug ("Boot failure. SmaugWiz not started."); TRY ClearDatabase (); CATCH (CSmaugException, ex) { bug ("Error %d: Clearing after boot failure.", ex->m_cause); THROW_LAST (); } END_CATCH THROW_LAST (); } END_CATCH } // Add a character to the list of all characters -Thoric void add_char (CCharacter *ch) { LINK (ch, first_char, last_char); } // Go through all areas, and set up initial economy based on mob // levels and gold void initialize_economy () { CMobIndexData *mob; int idx, gold, rng; gpDoc->LogString ("Initializing economy...", LOG_BOOT); POSITION pos = AreaList.GetHeadPosition (); while (pos) { CAreaData &Area = *AreaList.GetNext (pos); // skip area if they already got some gold if (Area.high_economy > 0 || Area.low_economy > 10000) continue; rng = Area.hi_soft_range - Area.low_soft_range; if (rng) rng /= 2; else rng = 25; gold = rng * rng * 50000; Area.BoostEconomy (gold); for (idx = Area.low_m_vnum; idx < Area.hi_m_vnum; idx++) if ((mob = MobTable.GetMob (idx, fBootDb)) != NULL) Area.BoostEconomy (mob->gold * 10); } } // Translate all room exits from virtual to real. // Has to be done after all rooms are read in. // Check for bad reverse exits. void fix_exits (BOOL bBoot /* = FALSE */) { CRoomIndexData *pRoomIndex; CExitData *pexit, *rev_exit; int iHash; gpDoc->LogString ("Fixing exits...", LOG_BOOT); for (iHash = 0; iHash < MAX_KEY_HASH; iHash++) { pRoomIndex = RoomTable.GetFirstByHash (iHash); while (pRoomIndex) { pRoomIndex->FixExits (bBoot); pRoomIndex = pRoomIndex->GetNext (); } } // Set all the rexit pointers -Thoric for (iHash = 0; iHash < MAX_KEY_HASH; iHash++) { for (pRoomIndex = RoomTable.GetFirstByHash (iHash); pRoomIndex; pRoomIndex = pRoomIndex->GetNext ()) { for (pexit = pRoomIndex->first_exit; pexit; pexit = pexit->GetNext ()) { if (pexit->GetToRoom () && !pexit->rexit) { rev_exit = get_exit_to (pexit->GetToRoom (), rev_dir[pexit->vdir], pRoomIndex->vnum); if (rev_exit) { pexit->rexit = rev_exit; rev_exit->rexit = pexit; } } } } } } /* * (prelude...) This is going to be fun... NOT! * (conclusion) QSort is f*cked! */ int exit_comp (CExitData **xit1, CExitData **xit2) { int d1, d2; d1 = (*xit1)->vdir; d2 = (*xit2)->vdir; if (d1 < d2) return -1; if (d1 > d2) return 1; return 0; } void sort_exits (CRoomIndexData *room) { CExitData *pexit; CExitData *exits [MAX_REXITS]; int x, nexits; nexits = 0; for (pexit = room->first_exit; pexit; pexit = pexit->GetNext ()) { exits [nexits++] = pexit; if (nexits > MAX_REXITS) { bug ("sort_exits: more than %d exits in room... fatal", nexits); return; } } qsort (&exits [0], nexits, sizeof (CExitData *), (int (*) (const void *, const void *)) exit_comp); for (x = 0; x < nexits; x++) { if (x > 0) exits [x]->SetPrev (exits [x-1]); else { exits [x]->SetPrev (NULL); room->first_exit = exits [x]; } if (x >= (nexits - 1)) { exits [x]->SetNext (NULL); room->last_exit = exits [x]; } else exits [x]->SetNext (exits [x+1]); } } void randomize_exits (CRoomIndexData *pRoom, short maxdir) { CExitData *pexit; int nexits, d0, d1, count, door; int vdirs [MAX_REXITS]; nexits = 0; for (pexit = pRoom->first_exit; pexit; pexit = pexit->GetNext ()) vdirs [nexits++] = pexit->vdir; for (d0 = 0; d0 < nexits; d0++) { if (vdirs [d0] > maxdir) continue; count = 0; while (vdirs [(d1 = number_range (d0, nexits - 1))] > maxdir || ++count > 5); if (vdirs[d1] > maxdir) continue; door = vdirs [d0]; vdirs [d0] = vdirs [d1]; vdirs [d1] = door; } count = 0; for (pexit = pRoom->first_exit; pexit; pexit = pexit->GetNext ()) pexit->vdir = vdirs [count++]; sort_exits (pRoom); } // Repopulate areas periodically. void area_update () { try { POSITION pos = AreaList.GetHeadPosition (); while (pos) { CAreaData &Area = *AreaList.GetNext (pos); CCharacter *pch; int reset_age = Area.reset_frequency ? Area.reset_frequency : 15; if ((reset_age == -1 && Area.age == -1) || ++Area.age < (reset_age-1)) continue; // Check for PC's. if (Area.nplayer > 0 && Area.age == (reset_age-1)) { char buf [MAX_STRING_LENGTH]; // Rennard if (! Area.m_Resetmsg.IsEmpty ()) sprintf (buf, "%s\n\r", NCCP Area.m_Resetmsg); else strcpy (buf, "You hear some squeaking sounds...\n\r"); for (pch = first_char; pch; pch = pch->GetNext ()) { if (! pch->IsNpc () && pch->IsAwake () && pch->GetInRoom () && pch->GetInRoom ()->GetArea () == &Area) { set_char_color (AT_RESET, pch); pch->SendText (buf); } } } // Check age and reset. // Note: Mud Academy resets every 3 minutes (not 15). if (Area.nplayer == 0 || Area.age >= reset_age) { CRoomIndexData *pRoomIndex; gpDoc->m_pLog->Printf (LOG_RESET, "Resetting: %s\n", NCCP Area.m_Filename); Area.Reset (); if (reset_age == -1) Area.age = -1; else Area.age = number_range (0, reset_age / 5); pRoomIndex = RoomTable.GetRoom (SysData.m_RoomSchool); if (pRoomIndex != NULL && &Area == pRoomIndex->GetArea () && Area.reset_frequency == 0) Area.age = 15 - 3; } } } catch (...) { CSwException ex; ex.Printf ("area_update Exception."); throw ex; } } // Create an instance of a mobile. CCharacter *create_mobile (CMobIndexData *pMobIndex) { CCharacter *mob; if (!pMobIndex) { bug ("Create_mobile: NULL pMobIndex."); ThrowSmaugException (SE_MOBILE); } mob = new CCharacter; mob->InitChar (); mob->SetMobIndex (pMobIndex); mob->SetEditor (NULL); mob->SetName (pMobIndex->GetPlayerName ()); mob->SetShortDescr (pMobIndex->GetShortDescr ()); mob->SetLongDescr (pMobIndex->GetLongDescr ()); mob->SetDescription (pMobIndex->GetDescription ()); mob->SetSpecialMobFunction (pMobIndex->spec_fun); mob->mpscriptpos = 0; mob->SetLevel (number_fuzzy (pMobIndex->level)); mob->SetMobInvisLevel (pMobIndex->GetMobInvisLevel ()); mob->SetActFlags (pMobIndex->GetActFlags ()); mob->SetAffectFlags (pMobIndex->GetAffectFlags ()); mob->SetAlignment (pMobIndex->alignment); mob->SetSex (pMobIndex->sex); if (!pMobIndex->ac) mob->SetArmor (pMobIndex->ac); else mob->SetArmor (interpolate (mob->GetLevel (), 100, -100)); if (!pMobIndex->hitnodice) mob->SetMaxHp (mob->GetLevel () * 8 + number_range ( mob->GetLevel () * mob->GetLevel () / 4, mob->GetLevel () * mob->GetLevel ())); else mob->SetMaxHp (pMobIndex->hitnodice * number_range (1, pMobIndex->hitsizedice) + pMobIndex->hitplus); mob->SetHp (mob->GetMaxHp ()); mob->SetGold (pMobIndex->gold); mob->SetExp (pMobIndex->exp); mob->SetPosition (pMobIndex->position); mob->defposition = pMobIndex->defposition; mob->barenumdie = pMobIndex->damnodice; mob->baresizedie = pMobIndex->damsizedice; mob->mobthac0 = pMobIndex->mobthac0; mob->hitplus = pMobIndex->hitplus; mob->damplus = pMobIndex->damplus; mob->perm_str = pMobIndex->perm_str; mob->perm_dex = pMobIndex->perm_dex; mob->perm_wis = pMobIndex->perm_wis; mob->perm_int = pMobIndex->perm_int; mob->perm_con = pMobIndex->perm_con; mob->perm_cha = pMobIndex->perm_cha; mob->perm_lck = pMobIndex->perm_lck; mob->SetHitroll (pMobIndex->hitroll); mob->SetDamroll (pMobIndex->damroll); mob->SetRace (pMobIndex->race); mob->SetClass (pMobIndex->m_Class); mob->SetXFlags (pMobIndex->xflags); mob->saving_poison_death = pMobIndex->saving_poison_death; mob->saving_wand = pMobIndex->saving_wand; mob->saving_para_petri = pMobIndex->saving_para_petri; mob->saving_breath = pMobIndex->saving_breath; mob->saving_spell_staff = pMobIndex->saving_spell_staff; mob->SetHeight (pMobIndex->height); mob->SetCarryWeight (pMobIndex->weight); mob->SetResistFlags (pMobIndex->resistant); mob->SetImmuneFlags (pMobIndex->immune); mob->SetSusceptFlags (pMobIndex->susceptible); mob->SetAttackFlags (pMobIndex->GetAttackFlags ()); mob->SetDefenseFlags (pMobIndex->GetDefenseFlags ()); mob->numattacks = pMobIndex->numattacks; mob->SetSpeaksFlags (pMobIndex->GetSpeaksFlags ()); mob->SetSpeaking (pMobIndex->GetSpeaking ()); // Insert in list. add_char (mob); pMobIndex->count++; nummobsloaded++; return mob; } // Create an instance of an object. CObjData *create_object (CObjIndexData *pObjIndex, int level) { CObjData *obj; if (!pObjIndex) { bug ("Create_object: NULL pObjIndex."); ThrowSmaugException (SE_OBJECT); } obj = new CObjData; obj->pIndexData = pObjIndex; obj->in_room = NULL; obj->level = level; obj->wear_loc = -1; obj->count = 1; cur_obj_serial = UMAX ((cur_obj_serial + 1) & (BV30-1), 1); obj->serial = obj->pIndexData->serial = cur_obj_serial; obj->SetName (pObjIndex->GetName ()); obj->SetShortDescr (pObjIndex->GetShortDescr ()); obj->SetDescription (pObjIndex->GetDescription ()); obj->SetActionDescr (pObjIndex->GetActionDescr ()); obj->item_type = pObjIndex->item_type; obj->m_ExtraFlags = pObjIndex->m_ExtraFlags; obj->wear_flags = pObjIndex->wear_flags; obj->SetAntiClassFlags (pObjIndex->GetAntiClassFlags ()); 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->value[5] = pObjIndex->value[5]; obj->weight = pObjIndex->weight; obj->cost = pObjIndex->cost; // Mess with object properties. switch (obj->item_type) { default: bug ("Read_object: vnum %d bad type.", pObjIndex->vnum); bug ("------------------------> ", obj->item_type); break; case ITEM_LIGHT: case ITEM_TREASURE: case ITEM_FURNITURE: case ITEM_TRASH: case ITEM_CONTAINER: case ITEM_DRINK_CON: case ITEM_KEY: case ITEM_KEYRING: case ITEM_ODOR: break; case ITEM_COOK: case ITEM_FOOD: // optional food condition (rotting food) -Thoric // value1 is the max condition of the food // value4 is the optional initial condition if (obj->value [4]) obj->timer = obj->value [4]; else obj->timer = obj->value [1]; break; case ITEM_BOAT: case ITEM_CORPSE_NPC: case ITEM_CORPSE_PC: case ITEM_FOUNTAIN: case ITEM_BLOOD: case ITEM_BLOODSTAIN: case ITEM_SCRAPS: case ITEM_PIPE: case ITEM_HERB_CON: case ITEM_HERB: case ITEM_INCENSE: case ITEM_FIRE: case ITEM_BOOK: case ITEM_SWITCH: case ITEM_LEVER: case ITEM_PULLCHAIN: case ITEM_BUTTON: case ITEM_DIAL: case ITEM_RUNE: case ITEM_RUNEPOUCH: case ITEM_MATCH: case ITEM_TRAP: case ITEM_MAP: case ITEM_PORTAL: case ITEM_PAPER: case ITEM_PEN: case ITEM_TINDER: case ITEM_LOCKPICK: case ITEM_SPIKE: case ITEM_DISEASE: case ITEM_OIL: case ITEM_FUEL: case ITEM_QUIVER: case ITEM_SHOVEL: break; case ITEM_SALVE: obj->value [3] = number_fuzzy (obj->value [3]); break; case ITEM_SCROLL: obj->value [0] = number_fuzzy (obj->value [0]); break; case ITEM_WAND: case ITEM_STAFF: obj->value [0] = number_fuzzy (obj->value [0]); obj->value [1] = number_fuzzy (obj->value [1]); obj->value [2] = obj->value [1]; break; case ITEM_WEAPON: case ITEM_MISSILE_WEAPON: case ITEM_PROJECTILE: if (obj->value [1] && obj->value [2]) obj->value [2] *= obj->value [1]; else { obj->value [1] = number_fuzzy (number_fuzzy (1 * level / 4 + 2)); obj->value [2] = number_fuzzy (number_fuzzy (3 * level / 4 + 6)); } if (obj->value [0] == 0) obj->value [0] = INIT_WEAPON_CONDITION; break; case ITEM_ARMOR: if (obj->value [0] == 0) obj->value [0] = number_fuzzy (level / 4 + 2); if (obj->value [1] == 0) obj->value [1] = obj->value [0]; break; case ITEM_POTION: case ITEM_PILL: obj->value [0] = number_fuzzy (number_fuzzy (obj->value [0])); break; case ITEM_MONEY: obj->value [0] = obj->cost; if (obj->value [0] == 0) obj->value [0] = 1; break; } pObjIndex->m_ObjList.AddTail (obj); ++pObjIndex->count; return obj; } // Get an extra description from a list. char *GetExtraDescr (const char *name, CPtrList &EList) { POSITION pos = EList.GetHeadPosition (); while (pos) { CExtraDescrData &Ed = *(CExtraDescrData*) EList.GetNext (pos); if (is_name (name, Ed.keyword)) return Ed.description; } return NULL; } // Added lots of EOF checks, as most of the file crashes are based on them. // If an area file encounters EOF, the fread_* functions will shutdown the // MUD, as all area files should be read in in full or bad things will // happen during the game. Any files loaded in without fBootDb which // encounter EOF will return what they have read so far. These files // should include player files, and in-progress areas that are not loaded // upon bootup. // -- Altrag // This whole scheme has been redone, using exception handling - Rustry // Read a letter from a file. char fread_letter (FILE *fp) { char c; do { if (feof (fp)) { bug ("fread_letter: EOF encountered on read.\n\r"); if (fBootDb) ThrowSmaugException (SE_BOOT); return '\0'; } c = getc (fp); } while (isspace (c)); return c; } // Read a number from a file. int ParseNumber (char*& pLine) { int number; BOOL sign; char c; do c = *pLine++; while (isspace (c)); number = 0; sign = FALSE; if (c == '+') { c = *pLine++; } else if (c == '-') { sign = TRUE; c = *pLine++; } if (!isdigit (c)) { bug ("ParseNumber: bad format. (%c)", c); if (fBootDb) ThrowSmaugException (SE_BOOT); return 0; } while (isdigit (c)) { number = number * 10 + c - '0'; c = *pLine++; } if (sign) number = 0 - number; if (c == '|') number += ParseNumber (pLine); else if (c != ' ') --pLine; return number; } // custom str_dup using new char *str_dup (char const *str) { static char *ret; if (!str) return NULL; ret = new char [strlen (str) + 1]; strcpy (ret, str); return ret; } // Read a string from a buffer char *ParseString (char*& pLine, FILE* fp) { char buf [MAX_STRING_LENGTH]; char *plast; char c; plast = buf; buf [0] = '\0'; int Count = 0; // Skip blanks. // Read first char. do c = *pLine++; while (isspace (c)); if ((*plast++ = c) == '~') return STRALLOC (""); for (;;) { if (Count >= (MAX_STRING_LENGTH - 1)) { bug ("ParseString: string too long"); *plast = '\0'; return STRALLOC (buf); } switch (*plast = *pLine++) { default: ++plast; ++Count; break; case '\0': *plast++ = '\r'; *plast++ = '\n'; Count += 2; // get another line (don't trim leading spaces) pLine = fread_line (fp, FALSE); break; case '\r': if (*pLine == '\n') { ++plast; ++Count; } break; case '~': *plast = '\0'; return STRALLOC (buf); } } } // Read a CString from a buffer CString ParseCString (char*& pLine, FILE* fp) { char buf [MAX_STRING_LENGTH]; char *plast; char c; plast = buf; buf [0] = '\0'; int Count = 0; // Skip blanks. // Read first char. do c = *pLine++; while (isspace (c)); if (c == '~') return buf; *plast++ = c; for (;;) { if (Count >= (MAX_STRING_LENGTH - 1)) { bug ("ParseString: string too long"); *plast = '\0'; return buf; } switch (*plast = *pLine++) { default: ++plast; ++Count; break; case '\0': *plast++ = '\r'; *plast++ = '\n'; Count += 2; // get another line (don't trim leading spaces) pLine = fread_line (fp, FALSE); break; case '\r': if (*pLine == '\n') { ++plast; ++Count; } break; case '~': *plast = '\0'; return buf; } } } // Read a string from buffer using str_dup (ie: no string hashing) char *ParseStringNohash (char* str, FILE* fp) { char buf [MAX_STRING_LENGTH]; char *plast; char c; plast = buf; buf [0] = '\0'; int Count = 0; // Skip blanks. // Read first char. do c = *str++; while (isspace (c)); if ((*plast++ = c) == '~') return str_dup (""); for (;;) { if (Count >= (MAX_STRING_LENGTH - 1)) { bug ("ParseStringNohash: string too long"); *plast = '\0'; return str_dup (buf); } switch (*plast = *str++) { default: ++plast; ++Count; break; case '\0': *plast++ = '\r'; *plast++ = '\n'; Count += 2; break; case '~': *plast = '\0'; return str_dup (buf); } } } // Read a string from file fp using str_dup (ie: no string hashing) char *fread_string_nohash (FILE *fp) { char buf[MAX_STRING_LENGTH]; char *plast; char c; int ln; plast = buf; buf [0] = '\0'; ln = 0; // Skip blanks. // Read first char. do { if (feof (fp)) { bug ("fread_string_no_hash: EOF encountered on read.\n\r"); if (fBootDb) ThrowSmaugException (SE_BOOT); return str_dup (""); } c = getc (fp); } while (isspace (c)); if ((*plast++ = c) == '~') return str_dup (""); for (;;) { if (ln >= (MAX_STRING_LENGTH - 1)) { bug ("fread_string_no_hash: string too long"); *plast = '\0'; return str_dup (buf); } switch (*plast = getc (fp)) { default: plast++; ln++; break; case EOF: bug ("Fread_string_no_hash: EOF"); if (fBootDb) ThrowSmaugException (SE_BOOT); *plast = '\0'; return str_dup (buf); break; case '\n': plast++; ln++; *plast++ = '\r'; ln++; break; case '\r': break; case '~': *plast = '\0'; return str_dup (buf); } } } // Read to end of line into static buffer -Thoric // bTrim (default) says to trim leading spaces char *fread_line (FILE *fp, BOOL bTrim /* = TRUE */) { int len; static char line [MAX_STRING_LENGTH]; char *ptr; do { ptr = line; if (! fgets (line, MAX_STRING_LENGTH-1, fp)) { if (feof (fp)) { if (fBootDb) { bug ("fread_line: EOF encountered on read.\n\r"); ThrowSmaugException (SE_BOOT); } strcpy (line, ""); return line; } else { bug ("fread_line: line too long"); if (fBootDb) ThrowSmaugException (SE_BOOT); break; } } ++gAcount; if (bTrim) { while (isspace (*ptr)) ++ptr; } } while ((len = strlen (ptr)) < 2); ptr [len-1] = 0; // null the '\n' return ptr; } // Read one word (into static buffer). char *ParseWord (char*& pLine) { static char word [MAX_INPUT_LENGTH]; char *pWord; char cFirst; if (! *pLine) return pLine; do cFirst = *pLine++; while (isspace (cFirst)); if (cFirst == '\'' || cFirst == '"') pWord = word; else { word [0] = cFirst; pWord = word+1; cFirst = ' '; } for (; pWord < word + MAX_INPUT_LENGTH; pWord++) { *pWord = *pLine++; if ((cFirst == ' ' ? isspace (*pWord) : *pWord == cFirst) || *pWord == 0) { if (cFirst == ' ') --pLine; *pWord = '\0'; return word; } } bug ("Fread_word: word too long"); ThrowSmaugException (SE_BOOT); return NULL; } char* ParseLine (char* pLine) { while (isspace (*pLine)) ++pLine; return pLine; } void ScanToEnd (FILE* fp, const char* end) { char *word, *pLine; // So we don't get so many bug messages when something // messes up --Shaddai do { if (feof (fp)) return; pLine = fread_line (fp); word = ParseWord (pLine); } while (! strcmp (word, end)); } void do_memory (CCharacter *ch, char *argument) { char arg [MAX_INPUT_LENGTH]; int hash; CParseinfo Inf; argument = one_argument (argument, arg); ch->SendTextf ("Affects %5d Areas %5d\n\r", top_affect, AreaList.GetCount ()); ch->SendTextf ("ExtDes %5d Exits %5d\n\r", top_ed, top_exit); ch->SendTextf ("Helps %5d Resets %5d\n\r", HelpList.GetCount (), gResetCount); ch->SendTextf ("IdxMobs %5d Mobs %5d\n\r", MobTable.GetCount (), nummobsloaded); ch->SendTextf ("IdxObjs %5d Objs %5d (%d)\n\r", OIdxTable.GetCount (), Inf.GetCount (COUNT_OBJS), Inf.GetCount (COUNT_TOTAL)); ch->SendTextf ("Rooms %5d VRooms %5d\n\r", RoomTable.GetCount (), top_vroom); ch->SendTextf ("Shops %5d RepShps %5d\n\r", top_shop, top_repair); ch->SendTextf ("CurOq's %5d CurCq's %5d\n\r", ExtractedObjList.GetCount (), cur_qchars); ch->SendTextf ("Players %5d Maxplrs %5d\n\r", DList.GetCount (), SysData.MaxPlayers); ch->SendTextf ("MaxEver %5d Topsn %5d (%d)\n\r", SysData.AlltimeMax, SkillTable.GetCount (), MAX_SKILL); ch->SendTextf ("MaxEver time recorded at: %s\n\r", SysData.pTimeOfMax); if (!str_cmp (arg, "check")) { #ifdef HASHSTR ch->SendText (check_hash (argument)); #else ch->SendText ("Hash strings not enabled.\n\r"); #endif return; } if (!str_cmp (arg, "showhigh")) { #ifdef HASHSTR show_high_hash (atoi (argument)); #else ch->SendText ("Hash strings not enabled.\n\r"); #endif return; } if (argument[0] != '\0') hash = atoi (argument); else hash = -1; if (!str_cmp (arg, "hash")) { #ifdef HASHSTR ch->SendTextf ("Hash statistics:\n\r%s", hash_stats ()); if (hash != -1) hash_dump (hash); #else ch->SendText ("Hash strings not enabled.\n\r"); #endif } } // Stick a little fuzz on a number. int number_fuzzy (int number) { switch (number_bits (2)) { case 0: number -= 1; break; case 3: number += 1; break; } return UMAX (1, number); } // Generate a random number. int number_range (int from, int to) { if ((to = to - from + 1) <= 1) return from; return (number_mm () % to) + from; } // Generate a percentile roll. int number_percent (void) { return number_mm () % 100; } // Generate a random door. int number_door (void) { int door; while ((door = number_mm () & (16-1)) > 9) ; return door; } int number_bits (int width) { return number_mm () & ((1 << width) - 1); } // I've gotten too many bad reports on OS-supplied random number generators. // This is the Mitchell-Moore algorithm from Knuth Volume II. // Best to leave the constants alone unless you've read Knuth. // -- Furey static int rgiState [2+55]; void init_mm () { int *piState; int iState; piState = &rgiState [2]; piState [-2] = 55 - 55; piState [-1] = 55 - 24; piState [0] = ((int) CurrentTime.GetTotalSeconds ()) & ((1 << 30) - 1); piState [1] = 1; for (iState = 2; iState < 55; iState++) { piState [iState] = (piState [iState-1] + piState [iState-2]) & ((1 << 30) - 1); } } int number_mm () { 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; } // Roll some dice. -Thoric 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; } // Simple linear interpolation. int interpolate (int level, int value_00, int value_32) { return value_00 + level * (value_32 - value_00) / 32; } // Removes the tildes from a string. // Used for player-entered strings that go into disk files. void smash_tilde (char *str) { for (; *str != '\0'; str++) if (*str == '~') *str = '-'; } // Encodes the tildes in a string. -Thoric // Used for player-entered strings that go into disk files. void hide_tilde (char *str) { for (; *str != '\0'; str++) if (*str == '~') *str = HIDDEN_TILDE; } char *show_tilde (char *str) { static char buf [MAX_STRING_LENGTH]; char *bufptr; bufptr = buf; for (; *str != '\0'; str++, bufptr++) { if (*str == HIDDEN_TILDE) *bufptr = '~'; else *bufptr = *str; } *bufptr = '\0'; return buf; } // Compare strings, case insensitive. // Return TRUE if different // (compatibility with historical functions). BOOL str_cmp (const char *astr, const char *bstr) { if (! astr || ! bstr) { bug ("str_cmp: astr (%s) bstr (%s)\n", astr, bstr); return TRUE; } return stricmp (astr, bstr) != 0; // for (; *astr || *bstr; astr++, bstr++) { // if (LOWER (*astr) != LOWER (*bstr)) // return TRUE; // } // // return FALSE; } // Compare strings, case insensitive, for prefix matching. // Return TRUE if astr not a prefix of bstr // (compatibility with historical functions). BOOL str_prefix (const char *astr, const char *bstr) { if (!astr) { bug ("Strn_cmp: null astr."); return TRUE; } if (!bstr) { bug ("Strn_cmp: null bstr."); return TRUE; } for (; *astr; astr++, bstr++) { if (LOWER (*astr) != LOWER (*bstr)) return TRUE; } return FALSE; } // Compare strings, case insensitive, for match anywhere. // Returns TRUE is astr not part of bstr. // (compatibility with historical functions). BOOL str_infix (const char *astr, const char *bstr) { int sstr1; int sstr2; int ichar; char c0; if ((c0 = LOWER (astr[0])) == '\0') return FALSE; sstr1 = strlen (astr); sstr2 = strlen (bstr); for (ichar = 0; ichar <= sstr2 - sstr1; ichar++) if (c0 == LOWER (bstr[ichar]) && !str_prefix (astr, bstr + ichar)) return FALSE; return TRUE; } // Compare strings, case insensitive, for suffix matching. // Return TRUE if astr not a suffix of bstr // (compatibility with historical functions). 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; } // Returns an initial-capped string. char *capitalize (const char *str) { static char strcap [MAX_STRING_LENGTH]; int i; for (i = 0; str [i] != '\0'; i++) strcap [i] = LOWER (str [i]); strcap [i] = '\0'; strcap [0] = UPPER (strcap [0]); return strcap; } // Returns a lowercase string. char *strlower (const char *str) { static char strlow [MAX_STRING_LENGTH]; int i; for (i = 0; str [i] != '\0'; i++) strlow [i] = LOWER (str [i]); strlow [i] = '\0'; return strlow; } // Returns an uppercase string. char *strupper (const char *str) { static char strup [MAX_STRING_LENGTH]; int i; for (i = 0; str [i] != '\0'; i++) strup [i] = UPPER (str [i]); strup [i] = '\0'; return strup; } // Returns TRUE or FALSE if a letter is a vowel -Thoric 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; } // Shove either "a " or "an " onto the beginning of a string -Thoric char *aoran (const char *str) { static char temp [MAX_STRING_LENGTH]; if (!str) { bug ("Aoran (): NULL 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; } // Append a string to a file. void append_file (CCharacter *ch, const char *file, char *str) { FILE *fp; if (ch->IsNpc () || str[0] == '\0') return; fclose (fpLOG); if ((fp = fopen (file, "a")) == NULL) { perror (file); ch->SendText ("Could not open the file!\n\r"); } else { fprintf (fp, "[%5d] %s: %s\n", ch->GetInRoom () ? ch->GetInRoom ()->vnum : 0, ch->GetName (), str); fclose (fp); } fpLOG = fopen (FileTable.GetName (SM_NULL_FILE), "r"); } // Append a string to a file. void append_to_file (const char *file, char *str) { FILE *fp; if ((fp = fopen (file, "a")) == NULL) perror (file); else { fprintf (fp, "%s\n", str); fclose (fp); } } // Reports a bug. void bug (const char *str, ...) { char buf [MAX_STRING_LENGTH]; FILE *fp; struct stat fst; if (fpArea) { sprintf (buf, "FILE: %s LINE: %d", strArea, gAcount); gpDoc->LogString (buf, LOG_BUG); // if exists if (stat (FileTable.GetName (SM_SHUTDOWN_FILE), &fst) != -1) { if ((fp = fopen (FileTable.GetName (SM_SHUTDOWN_FILE), "a"))) { fprintf (fp, "%s\n", buf); fclose (fp); } } } strcpy (buf, "BUG: "); va_list param; va_start (param, str); vsprintf (buf + strlen (buf), str, param); va_end (param); gpDoc->LogString (buf, LOG_BUG); // Due to SmaugWiz changes, this code may be executed when fpLog is // NULL. When this happens we really only want to print to stderr, // which we have already done, so we skip the bug file. if (fpLOG) { fclose (fpLOG); if ((fp = fopen (FileTable.GetName (SM_BUG_FILE), "a"))) { fprintf (fp, "%s\n", buf); fclose (fp); } fpLOG = fopen (FileTable.GetName (SM_NULL_FILE), "r"); } } // Add a string to the boot-up log -Thoric void BootLog (const char *str, ...) { char buf [MAX_STRING_LENGTH]; FILE *fp; static char *BlMsg = "---------------------[ Boot Log ]--------------------\n"; va_list param; strcpy (buf, "BOOT: "); va_start (param, str); vsprintf (buf+strlen (buf), str, param); va_end (param); fclose (fpLOG); if ((fp = fopen (FileTable.GetName (SM_BOOTLOG_FILE), "a"))) { // If this is the first boot log call, put in a header if (! bBootLog) { fprintf (fp, BlMsg); bBootLog = TRUE; } fprintf (fp, "%s\n", buf); fclose (fp); } fpLOG = fopen (FileTable.GetName (SM_NULL_FILE), "r"); gpDoc->LogString (buf, LOG_BOOT); } // Dump a text file to a player, a line at a time -Thoric void show_file (CCharacter *ch, const char *filename) { FILE *fp; char buf [MAX_STRING_LENGTH]; int c; int num = 0; if ((fp = fopen (filename, "r"))) { while (!feof (fp)) { while ((buf [num] = fgetc (fp)) != EOF && buf [num] != '\n' && buf [num] != '\r' && num < (MAX_STRING_LENGTH-2)) num++; c = fgetc (fp); if ((c != '\n' && c != '\r') || c == buf [num]) ungetc (c, fp); buf [num++] = '\n'; buf [num++] = '\r'; buf [num ] = '\0'; send_to_pager (buf, ch); num = 0; } fclose (fp); } } // Show the boot log file -Thoric void do_dmesg (CCharacter *ch, char *argument) { set_pager_color (AT_LOG, ch); show_file (ch, FileTable.GetName (SM_BOOTLOG_FILE)); } // wizlist builder! -Thoric void towizfile (const char *line) { int filler, xx; char outline [MAX_STRING_LENGTH]; FILE *fp; outline [0] = '\0'; if (line && line[0] != '\0') { filler = (78-strlen (line)); if (filler < 1) filler = 1; filler /= 2; for (xx = 0; xx < filler; xx++) strcat (outline, " "); strcat (outline, line); } strcat (outline, "\n\r"); fp = fopen (FileTable.GetName (SM_WIZLIST_FILE), "a"); if (fp) { fputs (outline, fp); fclose (fp); } } void add_to_wizlist (const char *name, int level) { CWizData *wiz, *tmp; #ifdef _DEBUG gpDoc->LogString ("Adding to wizlist..."); #endif wiz = new CWizData; wiz->name = str_dup (name); wiz->level = level; if (! first_wiz) { wiz->SetLast (NULL); wiz->SetNext (NULL); first_wiz = wiz; last_wiz = wiz; return; } // insert sort, of sorts for (tmp = first_wiz; tmp; tmp = tmp->GetNext ()) if (level > tmp->level) { if (!tmp->GetLast ()) first_wiz = wiz; else tmp->GetLast ()->SetNext (wiz); wiz->SetLast (tmp->GetLast ()); wiz->SetNext (tmp); tmp->SetLast (wiz); return; } wiz->SetLast (last_wiz); wiz->SetNext (NULL); last_wiz->SetNext (wiz); last_wiz = wiz; } // Wizlist builder -Thoric void make_wizlist () { FILE *fp; char *word, *pLine; int ilevel, iflags; CWizData *wiz, *wiznext; char buf [MAX_STRING_LENGTH]; first_wiz = last_wiz = NULL; WIN32_FIND_DATA Fd; HANDLE Dh = FindFirstFile (FileTable.MakeName (SD_GOD_DIR, "*"), &Fd); if (Dh == INVALID_HANDLE_VALUE) then return; BOOL bFirst = TRUE; for (;;) { if (! bFirst) if (! FindNextFile (Dh, &Fd)) then break; // done bFirst = FALSE; CString fWiz = Fd.cFileName; if (fWiz.GetAt (0) == '.') then continue; CString Fname = FileTable.MakeName (SD_GOD_DIR, fWiz); fp = fopen (Fname, "r"); if (fp) { if (! feof (fp)) { pLine = fread_line (fp); word = ParseWord (pLine); } else word = "End"; ilevel = ParseNumber (pLine); pLine = fread_line (fp); word = ParseWord (pLine); if (! str_cmp (word, "Pcflags")) iflags = ParseNumber (pLine); else iflags = 0; fclose (fp); if (IS_SET (iflags, PCFLAG_RETIRED)) ilevel = MAX_LEVEL - 15; if (IS_SET (iflags, PCFLAG_GUEST)) ilevel = MAX_LEVEL - 16; add_to_wizlist (fWiz, ilevel); } } FindClose (Dh); remove (FileTable.GetName (SM_WIZLIST_FILE)); sprintf (buf, " Masters of the %s!", SysData.GetLongTitle ()); towizfile (buf); ilevel = 65535; buf [0] = '\0'; for (wiz = first_wiz; wiz; wiz = wiz->GetNext ()) { if (wiz->level < ilevel) { if (buf [0]) { towizfile (buf); buf [0] = '\0'; } towizfile (""); ilevel = wiz->level; switch (ilevel) { case MAX_LEVEL - 0: towizfile (" Supreme Entity"); break; case MAX_LEVEL - 1: towizfile (" Infinite"); break; case MAX_LEVEL - 2: towizfile (" Eternal"); break; case MAX_LEVEL - 3: towizfile (" Ancient"); break; case MAX_LEVEL - 4: towizfile (" Exalted Gods"); break; case MAX_LEVEL - 5: towizfile (" Ascendant Gods"); break; case MAX_LEVEL - 6: towizfile (" Greater Gods"); break; case MAX_LEVEL - 7: towizfile (" Gods"); break; case MAX_LEVEL - 8: towizfile (" Lesser Gods"); break; case MAX_LEVEL - 9: towizfile (" Immortals"); break; case MAX_LEVEL - 10: towizfile (" Demi Gods"); break; case MAX_LEVEL - 11: towizfile (" Saviors"); break; case MAX_LEVEL - 12: towizfile (" Creators"); break; case MAX_LEVEL - 13: towizfile (" Acolytes"); break; case MAX_LEVEL - 14: towizfile (" Neophytes"); break; case MAX_LEVEL - 15: towizfile (" Retired"); break; case MAX_LEVEL - 16: towizfile (" Guests"); break; default: towizfile (" Servants"); break; } } if (strlen (buf) + strlen (wiz->name) > 76) { towizfile (buf); buf [0] = '\0'; } strcat (buf, " "); strcat (buf, wiz->name); if (strlen (buf) > 70) { towizfile (buf); buf [0] = '\0'; } } if (buf [0]) towizfile (buf); for (wiz = first_wiz; wiz; wiz = wiznext) { wiznext = wiz->GetNext (); delete wiz; } first_wiz = last_wiz = NULL; } void do_makewizlist (CCharacter *ch, char *argument) { make_wizlist (); } // mud prog functions // This routine reads in scripts of MUDprograms from a file int mprog_name_to_type (const char* name) { if (!str_cmp (name, "in_file_prog")) return IN_FILE_PROG; if (!str_cmp (name, "act_prog")) return ACT_PROG; if (!str_cmp (name, "speech_prog")) return SPEECH_PROG; if (!str_cmp (name, "rand_prog")) return RAND_PROG; if (!str_cmp (name, "fight_prog")) return FIGHT_PROG; if (!str_cmp (name, "hitprcnt_prog")) return HITPRCNT_PROG; if (!str_cmp (name, "death_prog")) return DEATH_PROG; if (!str_cmp (name, "entry_prog")) return ENTRY_PROG; if (!str_cmp (name, "greet_prog")) return GREET_PROG; if (!str_cmp (name, "all_greet_prog")) return ALL_GREET_PROG; if (!str_cmp (name, "give_prog")) return GIVE_PROG; if (!str_cmp (name, "bribe_prog")) return BRIBE_PROG; if (!str_cmp (name, "time_prog")) return TIME_PROG; if (!str_cmp (name, "hour_prog")) return HOUR_PROG; if (!str_cmp (name, "wear_prog")) return WEAR_PROG; if (!str_cmp (name, "remove_prog")) return REMOVE_PROG; if (!str_cmp (name, "sac_prog")) return SAC_PROG; if (!str_cmp (name, "look_prog")) return LOOK_PROG; if (!str_cmp (name, "exa_prog")) return EXA_PROG; if (!str_cmp (name, "zap_prog")) return ZAP_PROG; if (!str_cmp (name, "get_prog")) return GET_PROG; if (!str_cmp (name, "drop_prog")) return DROP_PROG; if (!str_cmp (name, "damage_prog")) return DAMAGE_PROG; if (!str_cmp (name, "repair_prog")) return REPAIR_PROG; if (!str_cmp (name, "greet_prog")) return GREET_PROG; if (!str_cmp (name, "randiw_prog")) return RANDIW_PROG; if (!str_cmp (name, "speechiw_prog")) return SPEECHIW_PROG; if (!str_cmp (name, "pull_prog")) return PULL_PROG; if (!str_cmp (name, "push_prog")) return PUSH_PROG; if (!str_cmp (name, "sleep_prog")) return SLEEP_PROG; if (!str_cmp (name, "rest_prog")) return REST_PROG; if (!str_cmp (name, "rfight_prog")) return FIGHT_PROG; if (!str_cmp (name, "enter_prog")) return ENTRY_PROG; if (!str_cmp (name, "leave_prog")) return LEAVE_PROG; if (!str_cmp (name, "rdeath_prog")) return DEATH_PROG; if (!str_cmp (name, "script_prog")) return SCRIPT_PROG; if (!str_cmp (name, "use_prog")) return USE_PROG; return ERROR_PROG; } BOOL delete_obj (CObjIndexData *obj) { return TRUE; } BOOL delete_mob (CMobIndexData *mob) { return TRUE; } // Creates a simple exit with no fields filled but rvnum and optionally // to_room and vnum. -Thoric // Exits are inserted into the linked list based on vdir. CExitData *make_exit (CRoomIndexData *pRoomIndex, CRoomIndexData *to_room, short door) { CExitData *pexit, *texit; BOOL broke; pexit = new CExitData; pexit->vdir = door; pexit->rvnum = pRoomIndex->vnum; pexit->SetToRoom (to_room); pexit->distance = 1; if (to_room) { pexit->vnum = to_room->vnum; texit = get_exit_to (to_room, rev_dir[door], pRoomIndex->vnum); if (texit) { // assign reverse exit pointers texit->rexit = pexit; pexit->rexit = texit; } } broke = FALSE; for (texit = pRoomIndex->first_exit; texit; texit = texit->GetNext ()) if (door < texit->vdir) { broke = TRUE; break; } if (!pRoomIndex->first_exit) pRoomIndex->first_exit = pexit; else { // keep exits in incremental order - insert exit into list if (broke && texit) { if (!texit->GetPrev ()) pRoomIndex->first_exit = pexit; else texit->GetPrev ()->SetNext (pexit); pexit->SetPrev (texit->GetPrev ()); pexit->SetNext (texit); texit->SetPrev (pexit); top_exit++; return pexit; } pRoomIndex->last_exit->SetNext (pexit); } pexit->SetNext (NULL); pexit->SetPrev (pRoomIndex->last_exit); pRoomIndex->last_exit = pexit; top_exit++; return pexit; } void fix_area_exits (CAreaData *tarea) { CRoomIndexData *pRoomIndex; CExitData *pexit, *rev_exit; int rnum; BOOL fexit; for (rnum = tarea->low_r_vnum; rnum <= tarea->hi_r_vnum; rnum++) { if ((pRoomIndex = RoomTable.GetRoom (rnum)) == NULL) continue; fexit = FALSE; pexit = pRoomIndex->first_exit; for (; pexit; pexit = pexit->GetNext ()) { fexit = TRUE; pexit->rvnum = pRoomIndex->vnum; if (pexit->vnum <= 0) pexit->SetToRoom (NULL); else pexit->SetToRoom (RoomTable.GetRoom (pexit->vnum)); } if (!fexit) pRoomIndex->SetNoMob (); } for (rnum = tarea->low_r_vnum; rnum <= tarea->hi_r_vnum; rnum++) { if ((pRoomIndex = RoomTable.GetRoom (rnum)) == NULL) continue; pexit = pRoomIndex->first_exit; for (; pexit; pexit = pexit->GetNext ()) { if (pexit->GetToRoom () && !pexit->rexit) { rev_exit = get_exit_to (pexit->GetToRoom (), rev_dir [pexit->vdir], pRoomIndex->vnum); if (rev_exit) { pexit->rexit = rev_exit; rev_exit->rexit = pexit; } } } } } CAreaData *LoadAreaFile (const CString Fname, BOOL bBoot /* = FALSE */, CAreaData* pArea /* = NULL */, BOOL bBuild /* = FALSE */) { strcpy (strArea, FileTable.MakeAreaName (Fname, bBuild)); if (! (fpArea = fopen (strArea, "r"))) { perror (strArea); bug ("load_area: error loading file (can't open)"); bug (strArea); return NULL; } BOOL bNewArea = pArea == NULL; CString Word; char *pLine = NULL; gAcount = 0; pLine = fread_line (fpArea); Word = ParseWord (pLine); if (Word != "#VERSION") { bug ("%s: No Version Found.", strArea); fclose (fpArea); if (bBoot) ThrowSmaugException (SE_AREA); return NULL; } int Version = ParseNumber (pLine); if (Version != SW_CURRENT_AV) { bug ("%s: Cannot load Version %d Areas.", strArea, Version); fclose (fpArea); if (bBoot) ThrowSmaugException (SE_AREA); return NULL; } pLine = fread_line (fpArea); Word = ParseWord (pLine); if (Word == "#HELPS") { if (bBoot) LoadAllHelp (fpArea); return NULL; } if (Word != "#AREA") { bug ("%s: No Area name Found.", strArea); fclose (fpArea); if (bBoot) ThrowSmaugException (SE_AREA); return NULL; } CString AreaName = ParseCString (pLine, fpArea); if (bNewArea) pArea = new CAreaData (Fname, AreaName, Version); // hack to get around passing bBoot all over the place BOOL oldBootFlag = fBootDb; fBootDb = bBoot; pArea->Load (fpArea, gAcount); fBootDb = oldBootFlag; fclose (fpArea); fpArea = NULL; if (! pArea->IsLoaded ()) { gpDoc->m_pLog->Printf (LOG_ALWAYS, "(%s)\n", NCCP Fname); delete pArea; return NULL; } gpDoc->m_pLog->Printf (LOG_ALWAYS, "%-14s: Rooms: %5d - %-5d Objs: %5d - %-5d Mobs: %5d - %d\n", NCCP pArea->m_Filename, pArea->low_r_vnum, pArea->hi_r_vnum, pArea->low_o_vnum, pArea->hi_o_vnum, pArea->low_m_vnum, pArea->hi_m_vnum); return pArea; } void AddArea (CAreaData* pArea) { AreaList.AddTail (pArea); sort_area (pArea, FALSE); } void load_reserved () { FILE *fp; CString Fname = FileTable.MakeName (SD_SYSTEM_DIR, "reserved.lst"); if (! (fp = fopen (Fname, "r"))) return; gpDoc->LogString ("Loading reserved names", LOG_BOOT); for ( ; ; ) { if (feof (fp)) { bug ("Load_reserved: no $ found."); fclose (fp); return; } CString Rname = fread_string_nohash (fp); if (Rname [0] == '$') break; ReservedNamesList.AddTail (Rname); } fclose (fp); } // Build list of in_progress areas. Do not load areas. // define AREA_READ if you want it to build area names rather than reading // them out of the area files. -- Altrag void load_buildlist () { FILE *fp; char buf [MAX_STRING_LENGTH]; CAreaData *pArea; char line [81]; char word [81]; int low, hi; int mlow, mhi, olow, ohi, rlow, rhi; char temp; WIN32_FIND_DATA Fd; HANDLE Dh = FindFirstFile (FileTable.MakeName (SD_GOD_DIR, "*"), &Fd); if (Dh == INVALID_HANDLE_VALUE) then return; gpDoc->LogString ("Loading gods...", LOG_BUILD); BOOL bFirst = TRUE; for (;;) { if (! bFirst) if (! FindNextFile (Dh, &Fd)) then break; // done bFirst = FALSE; CString Auth = Fd.cFileName; if (Auth.GetAt (0) == '.') then continue; CString Fname = FileTable.MakeName (SD_GOD_DIR, Auth); if (! (fp = fopen (Fname, "r"))) { bug ("Load_buildlist: invalid file: %s", NCCP Fname); continue; } gpDoc->LogString (Auth, LOG_BUILD); BOOL bGoodGod = TRUE; rlow=rhi=olow=ohi=mlow=mhi=0; while (!feof (fp) && !ferror (fp)) { low = hi = 0; word [0] = 0; line [0] = 0; if ((temp = fgetc (fp)) != EOF) ungetc (temp, fp); else break; fgets (line, 80, fp); sscanf (line, "%s %d %d", word, &low, &hi); if (! strcmp (word, "Level")) { if (low < LEVEL_IMMORTAL) { gpDoc->LogStringf (LOG_NORMAL, LEVEL_LOG, "%s: God file with level %d < %d", NCCP Auth, low, LEVEL_IMMORTAL); bGoodGod = FALSE; break; } } if (!strcmp (word, "RoomRange")) rlow = low, rhi = hi; else if (!strcmp (word, "MobRange")) mlow = low, mhi = hi; else if (!strcmp (word, "ObjRange")) olow = low, ohi = hi; } fclose (fp); if (bGoodGod && rlow && rhi) { CString Aname = FileTable.MakeBuildName (Auth); if (! (fp = fopen (Aname, "r"))) { bug ("Load_buildlist: cannot open area file for read"); perror (Aname); continue; } sprintf (buf, "{PROTO} %s's area in progress", NCCP Auth); pArea = new CAreaData (Aname, buf, SW_CURRENT_AV); pArea->m_Author = Auth; fclose (fp); pArea->low_r_vnum = rlow; pArea->hi_r_vnum = rhi; pArea->low_m_vnum = mlow; pArea->hi_m_vnum = mhi; pArea->low_o_vnum = olow; pArea->hi_o_vnum = ohi; pArea->low_soft_range = -1; pArea->hi_soft_range = -1; pArea->low_hard_range = -1; pArea->hi_hard_range = -1; BuildList.AddTail (pArea); gpDoc->m_pLog->Printf (LOG_ALWAYS, "%-14s: Rooms: %5d - %-5d Objs: %5d - %-5d " "Mobs: %5d - %-5d\n", NCCP pArea->m_Filename, pArea->low_r_vnum, pArea->hi_r_vnum, pArea->low_o_vnum, pArea->hi_o_vnum, pArea->low_m_vnum, pArea->hi_m_vnum); sort_area (pArea, TRUE); } } FindClose (Dh); } // Sort by room vnums -Altrag & Thoric void sort_area (CAreaData *pArea, BOOL bProto) { if (!pArea) { bug ("Sort_area: NULL pArea"); return; } CPtrList &List = bProto ? BuildList.SortList : AreaList.SortList; POSITION CurrPos, pos = List.GetHeadPosition (); while (pos) { CurrPos = pos; CAreaData &Ar = *(CAreaData*) List.GetNext (pos); if (pArea->low_r_vnum < Ar.low_r_vnum) { List.InsertBefore (CurrPos, pArea); return; } } List.AddTail (pArea); } // Display vnums currently assigned to areas -Altrag & Thoric // Sorted, and flagged if loaded. void show_vnums (CCharacter *ch, int low, int high, BOOL bProto, BOOL shownl, char *loadst, char *notloadst) { int count, loaded; count = loaded = 0; set_pager_color (AT_PLAIN, ch); CPtrList &List = bProto ? BuildList.SortList : AreaList.SortList; POSITION pos = List.GetHeadPosition (); while (pos) { CAreaData &Ar = *(CAreaData*) List.GetNext (pos); if (Ar.IsDeleted ()) continue; if (Ar.low_r_vnum < low) continue; if (Ar.hi_r_vnum > high) break; if (Ar.IsLoaded ()) ++loaded; else if (! shownl) continue; pager_printf (ch, "%-15s| Rooms: %5d - %-5d" " Objs: %5d - %-5d Mobs: %5d - %-5d%s\n\r", (Ar.m_Filename.IsEmpty () ? "(invalid)" : NCCP Ar.m_Filename), Ar.low_r_vnum, Ar.hi_r_vnum, Ar.low_o_vnum, Ar.hi_o_vnum, Ar.low_m_vnum, Ar.hi_m_vnum, Ar.IsLoaded () ? loadst : notloadst); ++count; } pager_printf (ch, "Areas listed: %d Loaded: %d\n\r", count, loaded); } void show_znums (CCharacter *ch, int low, int high, BOOL bProto, BOOL shownl, char *loadst, char *notloadst) { int count, loaded; count = loaded = 0; set_pager_color (AT_PLAIN, ch); CPtrList &List = bProto ? BuildList.SortList : AreaList.SortList; POSITION pos = List.GetHeadPosition (); while (pos) { CAreaData &Ar = *(CAreaData*) List.GetNext (pos); if (Ar.IsDeleted ()) continue; if (Ar.low_r_vnum < low) continue; if (Ar.hi_r_vnum > high) break; if (Ar.IsLoaded ()) ++loaded; else if (! shownl) continue; pager_printf (ch, "&G%-22s&Y| &W%5d - %-5d &Y|" " &W%5d - %-5d &Y| &W%5d - %-5d%s &Y|\n\r", (Ar.m_Filename.IsEmpty () ? "(invalid)" : NCCP Ar.m_Filename), Ar.low_r_vnum, Ar.hi_r_vnum, Ar.low_o_vnum, Ar.hi_o_vnum, Ar.low_m_vnum, Ar.hi_m_vnum, Ar.IsLoaded () ? loadst : notloadst); ++count; } pager_printf (ch, "Areas listed: %d Loaded: %d\n\r", count, loaded); } // Shows prototype vnums ranges, and if loaded void do_vnums (CCharacter *ch, char *argument) { char arg1[MAX_INPUT_LENGTH]; char arg2[MAX_INPUT_LENGTH]; int low, high; argument = one_argument (argument, arg1); argument = one_argument (argument, arg2); low = 0; high = 2097152000; // was 32766 if (arg1 [0] != '\0') { low = atoi (arg1); if (arg2 [0] != '\0') high = atoi (arg2); } show_vnums (ch, low, high, TRUE, TRUE, " *", ""); } /* * Shows installed areas, sorted. Mark unloaded areas with an X */ void do_zones (CCharacter *ch, char *argument) { char arg1[MAX_INPUT_LENGTH]; char arg2[MAX_INPUT_LENGTH]; int low, high; argument = one_argument (argument, arg1); argument = one_argument (argument, arg2); low = 0; high = 2097152000; // was 32766 if (arg1[0] != '\0') { low = atoi (arg1); if (arg2[0] != '\0') high = atoi (arg2); } send_to_pager("\n\r &c&GZones &Y| &GRooms &Y| &GObjs &Y| &GMobs &Y| \n\r", ch); send_to_pager("----------------------+---------------+---------------+---------------+\n\r", ch); show_znums (ch, low, high, FALSE, TRUE, "", " X"); } // Show prototype areas, sorted. Only show loaded areas void do_newzones (CCharacter *ch, char *argument) { char arg1[MAX_INPUT_LENGTH]; char arg2[MAX_INPUT_LENGTH]; int low, high; argument = one_argument (argument, arg1); argument = one_argument (argument, arg2); low = 0; high = 2097152000; // was 32766 if (arg1[0] != '\0') { low = atoi (arg1); if (arg2[0] != '\0') high = atoi (arg2); } send_to_pager("\n\r &c&GZones &Y| &GRooms &Y| &GObjs &Y| &GMobs &Y| \n\r", ch); send_to_pager("----------------------+---------------+---------------+---------------+\n\r", ch); show_znums (ch, low, high, TRUE, FALSE, "", " X"); } void load_banlist () { CBanData *pban; FILE *fp; int number; if (! (fp = fopen (FileTable.GetName (SM_BAN_LIST), "r"))) return; gpDoc->LogString ("Loading bans...", LOG_BOOT); for (;;) { if (feof (fp)) { bug ("Load_banlist: no -1 found."); fclose (fp); return; } char *pLine = fread_line (fp); number = ParseNumber (pLine); if (number == -1) { fclose (fp); return; } pban = new CBanData; pban->level = number; pban->name = ParseStringNohash (pLine, fp); if (*pLine++ == '~') pban->ban_time = ParseStringNohash (pLine, fp); else pban->ban_time = str_dup ("(unrecorded)"); LINK (pban, first_ban, last_ban); } } void ClearDatabase () { // Take 'em out in reverse order CObjectMenu::UnInitObjectMenu (); // The ban list CBanData *pNban, *pBan = first_ban; while (pBan) { pNban = pBan->GetNext (); delete pBan; pBan = pNban; } first_ban = last_ban = NULL; // The council list CCouncilData *pNcouncil, *pCouncil = first_council; while (pCouncil) { pNcouncil = pCouncil->GetNext (); delete pCouncil; pCouncil = pNcouncil; } first_council = last_council = NULL; // The deity list CDeityData *pNdeity, *pDeity = first_deity; while (pDeity) { pNdeity = pDeity->GetNext (); delete pDeity; pDeity = pNdeity; } first_deity = last_deity = NULL; // The clan list ClanList.RemoveAll (); // The board list BoardList.RemoveAll (); // The build list BuildList.RemoveAll (); // The Area list AreaList.RemoveAll (); // The auction delete auction; auction = NULL; // The wiz list CWizData *pNwiz, *pWiz = first_wiz; while (pWiz) { pNwiz = pWiz->GetNext (); delete pWiz; pWiz = pNwiz; } // The herb table HerbTable.RemoveAll (); // The class table ClassTable.RemoveAll (); // The skill table SkillTable.RemoveAll (); // The Race Table RaceTable.RemoveAll (); // Socials SocialTable.RemoveAll (); // Languages LanguageTable.RemoveAll (); // The Command table CommandTable.RemoveAll (); // These are things loaded with the areas, which are not // deleted when an area is deleted. // Repair Shops CRepairShopData *pNrshop, *prShop = first_repair; while (prShop) { pNrshop = prShop->GetNext (); delete prShop; prShop = pNrshop; } first_repair = last_repair = NULL; // Other Shops CShopData *pNshop, *pShop = first_shop; while (pShop) { pNshop = pShop->GetNext (); delete pShop; pShop = pNshop; } first_shop = last_shop = NULL; // Rooms, mobs, and objects should be all deleted, but // we will make sure here. RoomTable.RemoveAll (); MobTable.RemoveAll (); OIdxTable.RemoveAll (); ExtractedObjList.RemoveAll (); // Mob Act List CActProgData *pNact, *pAct = mob_act_list; while (pAct) { pNact = pAct->GetNext (); delete pAct; pAct = pNact; } mob_act_list = NULL; // The Help list HelpList.RemoveAll (); // The rest are misc or items created while running the game, and // which do not link into any of the lists used by boot items. // These should be all the NPC characters CCharacter *pNch, *pCh = first_char; while (pCh) { pNch = pCh->GetNext (); delete pCh; pCh = pNch; } first_char = last_char = NULL; CTeleportData *pNtel, *pTele = first_teleport; while (pTele) { pNtel = pTele->GetNext (); delete pTele; pTele = pNtel; } first_teleport = last_teleport = NULL; CRoomIndexData *pRoom, *pNroom; for (int hash = 0; hash < MAX_VROOMS; ++hash) { pRoom = GetVRoomFromHash (hash); while (pRoom) { pNroom = pRoom->GetNext (); delete pRoom; pRoom = pNroom; } } SysData.Empty (); DeleteAllHash (); } // Check to make sure range of vnums is free - Scryn 2/27/96 void do_check_vnums (CCharacter *ch, char *argument) { char buf [MAX_STRING_LENGTH]; char arg1 [MAX_STRING_LENGTH]; char arg2 [MAX_STRING_LENGTH]; int low_range, high_range; BOOL bRoom = FALSE, bMob = FALSE, bObj = FALSE, bAll = FALSE; argument = one_argument (argument, arg1); argument = one_argument (argument, arg2); if (arg1[0] == '\0') { ch->SendText ("Please specify room, mob, object, or all as your " "first argument.\n\r"); return; } if (!str_cmp (arg1, "room")) bRoom = TRUE; else if (!str_cmp (arg1, "mob")) bMob = TRUE; else if (!str_cmp (arg1, "object")) bObj = TRUE; else if (!str_cmp (arg1, "all")) bAll = TRUE; else { ch->SendText ("Please specify room, mob, or object as your " "first argument.\n\r"); return; } if (arg2 [0] == '\0') { ch->SendText ("Please specify the low end of the range to " "be searched.\n\r"); return; } if (argument [0] == '\0') { ch->SendText ("Please specify the high end of the range to " "be searched.\n\r"); return; } low_range = atoi (arg2); high_range = atoi (argument); if (low_range < 1 || low_range > 2097152000) { // was 32767 ch->SendText ("Invalid argument for bottom of range.\n\r"); return; } if (high_range < 1 || high_range > 2097152000) { ch->SendText ("Invalid argument for top of range.\n\r"); return; } if (high_range < low_range) { ch->SendText ("Bottom of range must be below top of range.\n\r"); return; } if (bAll) { sprintf (buf, "room %d %d", low_range, high_range); do_check_vnums (ch, buf); sprintf (buf, "mob %d %d", low_range, high_range); do_check_vnums (ch, buf); sprintf (buf, "object %d %d", low_range, high_range); do_check_vnums (ch, buf); return; } set_char_color (AT_PLAIN, ch); ShowConflicts (ch, AreaList.SortList, low_range, high_range, bRoom, bMob, bObj); ShowConflicts (ch, BuildList.SortList, low_range, high_range, bRoom, bMob, bObj); } void ShowConflicts (CCharacter* ch, CPtrList& List, int low, int hi, BOOL bRoom, BOOL bMob, BOOL bObj) { POSITION pos = List.GetHeadPosition (); while (pos) { CAreaData &Ar = *(CAreaData*) List.GetNext (pos); if (Ar.IsDeleted ()) continue; BOOL bConflict = FALSE; if (bRoom) { if (low < Ar.low_r_vnum && Ar.low_r_vnum < hi) bConflict = TRUE; if (low < Ar.hi_r_vnum && Ar.hi_r_vnum < hi) bConflict = TRUE; if ((low >= Ar.low_r_vnum) && (low <= Ar.hi_r_vnum)) bConflict = TRUE; if ((hi <= Ar.hi_r_vnum) && (hi >= Ar.low_r_vnum)) bConflict = TRUE; } if (bMob) { if (low < Ar.low_m_vnum && Ar.low_m_vnum < hi) bConflict = TRUE; if (low < Ar.hi_m_vnum && Ar.hi_m_vnum < hi) bConflict = TRUE; if ((low >= Ar.low_m_vnum) && (low <= Ar.hi_m_vnum)) bConflict = TRUE; if ((hi <= Ar.hi_m_vnum) && (hi >= Ar.low_m_vnum)) bConflict = TRUE; } if (bObj) { if (low < Ar.low_o_vnum && Ar.low_o_vnum < hi) bConflict = TRUE; if (low < Ar.hi_o_vnum && Ar.hi_o_vnum < hi) bConflict = TRUE; if ((low >= Ar.low_o_vnum) && (low <= Ar.hi_o_vnum)) bConflict = TRUE; if ((hi <= Ar.hi_o_vnum) && (hi >= Ar.low_o_vnum)) bConflict = TRUE; } CString Msg, Msg2; if (bConflict) { Msg.Format ("Conflict:%-15s| ", (Ar.m_Filename.IsEmpty () ? "(invalid)" : NCCP Ar.m_Filename)); if (bRoom) Msg2.Format ("Rooms: %5d - %-5d\n\r", Ar.low_r_vnum, Ar.hi_r_vnum); if (bMob) Msg2.Format ("Mobs: %5d - %-5d\n\r", Ar.low_m_vnum, Ar.hi_m_vnum); if (bObj) Msg2.Format ("Objects: %5d - %-5d\n\r", Ar.low_o_vnum, Ar.hi_o_vnum); Msg += Msg2; ch->SendText (Msg); } } } void remap_slot_numbers () { CSkill *pSkill; CSmaugAffect *pAff; char tmp [32]; int sn; gpDoc->LogString ("Remapping slots to sns", LOG_BOOT); for (sn = 0; sn < SkillTable.GetCount (); ++sn) { if (pSkill = SkillTable.GetSkill (sn)) { for (pAff = pSkill->GetAffects (); pAff; pAff = pAff->GetNext ()) if (pAff->location == APPLY_WEAPONSPELL || pAff->location == APPLY_WEARSPELL || pAff->location == APPLY_REMOVESPELL || pAff->location == APPLY_STRIPSN || pAff->location == APPLY_RECURRINGSPELL) { sprintf (tmp, "%d", slot_lookup (atoi (pAff->modifier))); delete pAff->modifier; pAff->modifier = str_dup (tmp); } } } }