/// <summary> /// Resets a single area. /// </summary> public static void ResetArea(Area area) { if (area == null) { return; } Room room; int indexNumber; area.DefenderSquads = 0; area.NumDefendersDispatched = 0; for (indexNumber = area.LowRoomIndexNumber; indexNumber <= area.HighRoomIndexNumber; indexNumber++) { if (indexNumber == 0) { continue; } room = Room.GetRoom(indexNumber); if (room && room.Area == area) { room.ResetRoom(area.TimesReset); } } area.AgeInSeconds = MUDMath.NumberRange(-Event.AREA_RESET_VARIABILITY, Event.AREA_RESET_VARIABILITY); area.TimesReset++; return; }
/// <summary> /// Provides an override to get the character's current repop point, or the default repop /// point if they don't have a current home set. /// </summary> /// <returns></returns> public override Room GetRepopPoint() { if (CurrentHome != 0) { return(Room.GetRoom(CurrentHome)); } return(base.GetRepopPoint()); }
/// <summary> /// Returns a random room on one of the maps. /// Argument: 0 = any map /// 1 = Surface map 1 /// 2 = Surface map 2 /// 3 = Underdark map 1 /// 4 = Underdark map 2 /// 5 = Underdark map 3 /// </summary> /// <param name="map"></param> /// <returns></returns> public static Room GetRandomMapRoom(Area map) { if (Room.Count < 1) { throw new IndexOutOfRangeException("No rooms loaded, cannot get a random map room."); } if (map == null) { List <Area> zones = new List <Area>(); foreach (Area area in Database.AreaList) { if (area.HasFlag(Area.AREA_WORLDMAP) && area.Rooms.Count > 0) { zones.Add(area); } } if (zones.Count < 1) { throw new IndexOutOfRangeException("GetRandomMapRoom(): No zones found with AREA_WORLDMAP flag set."); } int val = MUDMath.NumberRange(0, (zones.Count - 1)); map = zones[val]; } int max = map.Rooms.Count; if (max < 1) { throw new IndexOutOfRangeException("GetRandomMapRoom(): No rooms found in target zone."); } int target = MUDMath.NumberRange(0, (map.Rooms.Count - 1)); Room room = Room.GetRoom(target); if (!room || room.WorldmapTerrainType == 92 || room.WorldmapTerrainType == 101 || room.WorldmapTerrainType == 102 || room.WorldmapTerrainType == 116 || room.WorldmapTerrainType == 130 || room.WorldmapTerrainType == 131 || room.WorldmapTerrainType == 132 || room.WorldmapTerrainType == 136 || room.WorldmapTerrainType == 137 || room.HasFlag(RoomTemplate.ROOM_PRIVATE) || room.HasFlag(RoomTemplate.ROOM_SOLITARY) || room.HasFlag(RoomTemplate.ROOM_NO_TELEPORT) || room.TerrainType == TerrainType.underground_impassable) { room = GetRandomMapRoom(map); } return(room); }
/// <summary> /// Find a door based on its name. /// </summary> /// <param name="ch"></param> /// <param name="argument"></param> /// <returns></returns> public static Room FindRoom(CharData ch, string argument) { Exit.Direction dir = FindExit(ch, argument); if (dir == Exit.Direction.invalid) { SocketConnection.Act("I see no door $T here.", ch, null, argument, SocketConnection.MessageTarget.character); return(null); } if (ch.InRoom.ExitData[(int)dir]) { Room room = Room.GetRoom(ch.InRoom.ExitData[(int)dir].IndexNumber); return(room); } return(null); }
/// <summary> /// Random room generation function. /// </summary> /// <returns></returns> public static Room GetRandomRoom() { Room room; for ( ; ;) { room = Room.GetRoom(MUDMath.NumberRange(0, 65535)); if (room) { if (!room.HasFlag(RoomTemplate.ROOM_PRIVATE) && !room.HasFlag(RoomTemplate.ROOM_SOLITARY)) { break; } } } return(room); }
public static void ReturnToLoad(CharData ch) { if (!ch || !ch.InRoom) { return; } if (ch.InRoom.Area != Room.GetRoom(ch.LoadRoomIndexNumber).Area) { return; } Exit.Direction dir = FindPath(ch.InRoom.IndexNumber, ch.LoadRoomIndexNumber, ch, -40000, true); if (dir == Exit.Direction.invalid) { return; } if (ch.InRoom.ExitData[(int)dir].HasFlag(Exit.ExitFlag.closed) && !ch.IsAffected(Affect.AFFECT_PASS_DOOR) && !ch.HasInnate(Race.RACE_PASSDOOR)) { CommandType.Interpret(ch, "unlock " + dir.ToString()); CommandType.Interpret(ch, "open " + dir.ToString()); return; } ch.Move(dir); if (!ch.InRoom) { string text = "Return_to_load: no ch._inRoom! Mob #" + ch.MobileTemplate.IndexNumber + ", _name: " + ch.Name + ". Placing mob in limbo (mob.AddToRoom())."; Log.Error(text, 0); ch.AddToRoom(Room.GetRoom(StaticRooms.GetRoomNumber("ROOM_NUMBER_LIMBO"))); ImmortalChat.SendImmortalChat(ch, ImmortalChat.IMMTALK_SPAM, 0, text); return; } return; }
// Dispatches a guard to hunt down the player that has committed a crime and // has the guard capture them. static void DispatchGuard(CharData ch) { CharData mob = Database.CreateMobile(Database.GetMobTemplate(ch.InRoom.Area.DefenderTemplateNumber)); mob.AddToRoom(Room.GetRoom(ch.InRoom.Area.BarracksRoom)); if (!mob.HasActionBit(MobTemplate.ACT_MEMORY)) { mob.SetActionBit(MobTemplate.ACT_MEMORY); } if (!mob.HasActionBit(MobTemplate.ACT_HUNTER)) { if (mob.HasActionBit(MobTemplate.ACT_SENTINEL)) { mob.RemoveActionBit(MobTemplate.ACT_SENTINEL); } } mob.SetAffectBit(Affect.AFFECT_JUSTICE_TRACKER); mob.MobileTemplate.AddSpecFun("spec_justice_guard"); Combat.StartGrudge(mob, ch, false); return; }
/// <summary> /// Tracking code. /// </summary> /// <param name="ch"></param> public static void HuntVictim(CharData ch) { if (!ch || !ch.Hunting || !ch.IsAffected(Affect.AFFECT_TRACK)) { return; } if (ch.CurrentPosition != Position.standing) { if (ch.IsAffected(Affect.AFFECT_TRACK)) { ch.SendText("You abort your tracking effort.\r\n"); ch.RemoveAffect(Affect.AFFECT_TRACK); Combat.StopHunting(ch); } return; } CharData tmp = null; try { /* * Make sure the victim still exists. */ bool found = false; foreach (CharData it in Database.CharList) { ch = it; if (ch.Hunting != null && ch.Hunting.Who == tmp) { found = true; } } if (!found || !CharData.CanSee(ch, ch.Hunting.Who)) { if (!ch.IsAffected(Affect.AFFECT_TRACK)) { CommandType.Interpret(ch, "say Damn! My prey is gone!"); } else { ch.SendText("The trail seems to disappear.\r\n"); ch.RemoveAffect(Affect.AFFECT_TRACK); } Combat.StopHunting(ch); return; } if (ch.InRoom == ch.Hunting.Who.InRoom) { if (ch.Fighting) { return; } FoundPrey(ch, ch.Hunting.Who); return; } ch.WaitState(Skill.SkillList["track"].Delay); Exit.Direction dir = FindPath(ch.InRoom.IndexNumber, ch.Hunting.Who.InRoom.IndexNumber, ch, -40000, true); if (dir == Exit.Direction.invalid) { if (!ch.IsAffected(Affect.AFFECT_TRACK)) { SocketConnection.Act("$n&n says 'Damn! Lost $M!'", ch, null, ch.Hunting.Who, SocketConnection.MessageTarget.room); } else { ch.SendText("You lose the trail.\r\n"); ch.RemoveAffect(Affect.AFFECT_TRACK); Combat.StopHunting(ch); } return; } /* * Give a random direction if the mob misses the die roll. */ if (MUDMath.NumberPercent() > 75) /* @ 25% */ { do { dir = Database.RandomDoor(); }while (!(ch.InRoom.ExitData[(int)dir]) || !(ch.InRoom.ExitData[(int)dir].TargetRoom)); } if (ch.InRoom.ExitData[(int)dir].HasFlag(Exit.ExitFlag.closed)) { CommandType.Interpret(ch, "open " + dir.ToString()); return; } ImmortalChat.SendImmortalChat(null, ImmortalChat.IMMTALK_HUNTING, 0, String.Format("{0}&n leaves room {1} to the {2}.", ch.ShortDescription, ch.InRoom.IndexNumber, dir.ToString())); if (ch.IsAffected(Affect.AFFECT_TRACK)) { SocketConnection.Act(String.Format("You sense $N&n's trail {0} from here...", dir.ToString()), ch, null, ch.Hunting.Who, SocketConnection.MessageTarget.character); } ch.Move(dir); if (ch.IsAffected(Affect.AFFECT_TRACK)) { SocketConnection.Act("$n&n peers around looking for tracks.", ch, null, null, SocketConnection.MessageTarget.room); } if (!ch.Hunting) { if (!ch.InRoom) { string text = String.Empty; text = String.Format("Hunt_victim: no ch.in_room! Mob #{0}, _name: {1}. Placing mob in limbo (ch.AddToRoom()).", ch.MobileTemplate.IndexNumber, ch.Name); Log.Error(text, 0); ch.AddToRoom(Room.GetRoom(StaticRooms.GetRoomNumber("ROOM_NUMBER_LIMBO"))); text = String.Format("{0}&n has gone to limbo while hunting {1}.", ch.ShortDescription, ch.Hunting.Name); ImmortalChat.SendImmortalChat(null, ImmortalChat.IMMTALK_HUNTING, 0, text); return; } CommandType.Interpret(ch, "say Damn! Lost my prey!"); return; } if (ch.InRoom == ch.Hunting.Who.InRoom) { FoundPrey(ch, ch.Hunting.Who); } return; } catch (Exception ex) { Log.Error("Exception in HuntVictim: " + ex.ToString()); } }
/// <summary> /// Tracking mob has found the person its after. Attack or react accordingly. /// </summary> /// <param name="ch"></param> /// <param name="victim"></param> public static void FoundPrey(CharData ch, CharData victim) { string victname = String.Empty; string text = String.Empty; string lbuf = String.Empty; if (!victim) { Log.Error("FoundPrey: null victim", 0); return; } if (!victim.InRoom) { Log.Error("FoundPrey: null victim._inRoom", 0); return; } ImmortalChat.SendImmortalChat(null, ImmortalChat.IMMTALK_HUNTING, 0, string.Format("{0}&n has found {1}.", ch.ShortDescription, victim.Name)); if (ch.IsAffected(Affect.AFFECT_TRACK)) { ch.RemoveAffect(Affect.AFFECT_TRACK); Combat.StopHunting(ch); return; } if (ch.IsAffected(Affect.AFFECT_JUSTICE_TRACKER)) { /* Give Justice the ability to ground flying culprits */ if (victim.FlightLevel != 0) { SocketConnection.Act("$n&n forces you to land!", ch, null, victim, SocketConnection.MessageTarget.victim); SocketConnection.Act("$n&n forces $N&n to land!", ch, null, victim, SocketConnection.MessageTarget.room_vict); victim.FlightLevel = 0; } SocketConnection.Act("$n&n says, 'Stop, $N&n, you're under ARREST!'", ch, null, victim, SocketConnection.MessageTarget.character); SocketConnection.Act("$n&n says, 'Stop, $N&n, you're under ARREST!'", ch, null, victim, SocketConnection.MessageTarget.room); SocketConnection.Act("$n&n chains you up.", ch, null, victim, SocketConnection.MessageTarget.character); SocketConnection.Act("$n&n binds $N&n so $E can't move.", ch, null, victim, SocketConnection.MessageTarget.room); victim.SetAffectBit(Affect.AFFECT_BOUND); victim.RemoveFromRoom(); if (ch.InRoom.Area.JailRoom != 0) { victim.AddToRoom(Room.GetRoom(victim.InRoom.Area.JailRoom)); } else { victim.SendText("Justice is broken in this town - there is no jail and you're screwed.\r\n"); } Combat.StopHunting(ch); return; } victname = victim.IsNPC() ? victim.ShortDescription : victim.Name; if (ch.FlightLevel != victim.FlightLevel) { if (ch.CanFly()) { if (ch.FlightLevel < victim.FlightLevel && ch.FlightLevel < CharData.FlyLevel.high) { Command.Fly(ch, new string[] { "up" }); } else { Command.Fly(ch, new string[] { "down" }); } } else { SocketConnection.Act("$n peers around looking for something.", ch, null, null, SocketConnection.MessageTarget.room); } return; } if (!CharData.CanSee(ch, victim)) { if (MUDMath.NumberPercent() < 90) { return; } switch (MUDMath.NumberBits(5)) { case 0: text = String.Format("You can't hide forever, {0}!", victname); Command.Say(ch, new string[] { text }); break; case 1: SocketConnection.Act("$n&n sniffs around the room.", ch, null, victim, SocketConnection.MessageTarget.room); text = "I can smell your blood!"; Command.Say(ch, new string[] { text }); break; case 2: text = String.Format("I'm going to tear {0} apart!", victname); Command.Yell(ch, new string[] { text }); break; case 3: Command.Say(ch, new string[] { "Just wait until I find you..." }); break; default: SocketConnection.Act("$p peers about looking for something.", ch, null, null, SocketConnection.MessageTarget.room); break; } return; } if (ch.InRoom.HasFlag(RoomTemplate.ROOM_SAFE) && ch.IsNPC()) { text = String.Format("Hunting mob {0} found a safe room {1}.", ch.MobileTemplate.IndexNumber, ch.InRoom.IndexNumber); Log.Trace(text); return; } if (ch.CurrentPosition > Position.kneeling) { switch (MUDMath.NumberBits(5)) { case 0: text = String.Format("I will eat your heart, {0}!", victname); Command.Say(ch, new string[] { text }); break; case 1: text = String.Format("You want a piece of me, {0}?", victname); Command.Say(ch, new string[] { text }); break; case 2: text = String.Format("How does your flesh taste {0}, like chicken?", victname); Command.Say(ch, new string[] { text }); break; case 3: SocketConnection.Act("$n&n howls gleefully and lunges at $N&n!", ch, null, victim, SocketConnection.MessageTarget.everyone_but_victim); SocketConnection.Act("$n&n howls gleefully and lunges at you!", ch, null, victim, SocketConnection.MessageTarget.victim); break; case 4: SocketConnection.Act("$n&n charges headlong into $N&n!", ch, null, victim, SocketConnection.MessageTarget.everyone_but_victim); SocketConnection.Act("$n&n charges headlong into you!", ch, null, victim, SocketConnection.MessageTarget.victim); break; default: break; } Combat.StopHunting(ch); Combat.CheckAggressive(victim, ch); if (ch.Fighting) { return; } // Backstab if able, otherwise just kill them. // Kill if they don't have the skill or if they don't have a stabber. if (!ch.HasSkill("backstab")) { Combat.CombatRound(ch, victim, String.Empty); } else if (!Combat.Backstab(ch, victim)) { Combat.CombatRound(ch, victim, String.Empty); } } return; }
public static Exit.Direction FindPath(int inRoomIndexNumber, int outRoomIndexNumber, CharData ch, int depth, bool inZone) { RoomTemplate herep; RoomTemplate startp; Exit exitp; RoomQ tmp_q; RoomQ q_head; RoomQ q_tail; HashHeader x_room = null; bool throughDoors; int i; int tmp_room; int count = 0; // TODO: Re-enable this. return(Exit.Direction.invalid); if (depth < 0) { throughDoors = true; depth = -depth; } else { throughDoors = false; } startp = Room.GetRoom(inRoomIndexNumber); InitHashTable(x_room, sizeof(int), 2048); //HashEnter(x_room, inRoomIndexNumber, null); /* initialize queue */ q_head = new RoomQ(); q_tail = q_head; q_tail.RoomNR = inRoomIndexNumber; q_tail.NextQ = null; while (q_head != null) { herep = Room.GetRoom(q_head.RoomNR); /* for each room test all directions */ if (herep.Area == startp.Area || inZone == false) { /* * only look in this zone... * saves cpu time and makes world safer for players */ for (i = 0; i < Limits.MAX_DIRECTION; i++) { exitp = herep.ExitData[i]; if (ExitOk(exitp) != 0 && (throughDoors ? GO_OK_SMARTER : Macros.IsSet((int)Room.GetRoom(q_head.RoomNR).ExitData[i].ExitFlags, (int)Exit.ExitFlag.closed))) { /* next room */ tmp_room = herep.ExitData[i].TargetRoom.IndexNumber; if (tmp_room != outRoomIndexNumber) { /* * shall we add room to queue ? * count determines total breadth and depth */ if (!hash_find(x_room, tmp_room) && (count < depth)) /* && !IS_SET( RM_FLAGS(tmp_room), DEATH ) ) */ { ++count; /* mark room as visted and put on queue */ tmp_q = new RoomQ(); tmp_q.RoomNR = tmp_room; tmp_q.NextQ = null; q_tail.NextQ = tmp_q; q_tail = tmp_q; /* Ancestor for first layer is the direction */ /*HashEnter(x_room, tmp_room, * ((long)hash_find(x_room, q_head.RoomNR) == -1) * ? (Object)(i + 1) * : hash_find(x_room, q_head.RoomNR));*/ } } else { /* have reached our goal so free queue */ tmp_room = q_head.RoomNR; for (; q_head != null; q_head = tmp_q) { tmp_q = q_head.NextQ; q_head = null; } /* return direction if first layer */ /*if ((long)hash_find(x_room, tmp_room) == -1) * { * if (x_room.Buckets) * { * // junk left over from a previous track * DestroyHashTable(x_room, null); * } * return (i);*/ //} //else { /* else return the Ancestor */ //long j; /*j = (long)hash_find(x_room, tmp_room); * if (x_room.Buckets) * { * // junk left over from a previous track * DestroyHashTable(x_room, null); * } * return (-1 + j);*/ } } } } } /* free queue head and point to next entry */ tmp_q = q_head.NextQ; q_head = null; q_head = tmp_q; } /* couldn't find path */ /*if (x_room.Buckets) * { * // junk left over from a previous track * DestroyHashTable(x_room, null); * }*/ return(Exit.Direction.invalid); }
/// <summary> /// Alert and dispatch the guards when an enemy has entered the area. /// </summary> /// <param name="ch"></param> static void StartInvasion(CharData ch) { SocketConnection socket; int count; CharData mob; string lbuf; // if there are no protector mobs, who cares if someone walks in. if (ch.InRoom.Area.DefenderTemplateNumber == 0 || ch.InRoom.Area.DefendersPerSquad == 0) { lbuf = String.Format("Start_invasion: no defender mobs"); ImmortalChat.SendImmortalChat(null, ImmortalChat.IMMTALK_SPAM, 0, lbuf); return; } // any town can only dispatch 5 batches of guards. if (ch.InRoom.Area.NumDefendersDispatched >= (ch.InRoom.Area.DefendersPerSquad * 5)) { // if( ch.in_room.area.dispatched >= (ch.in_room.area.defender_num * // ch.in_room.area.squads )) { lbuf = String.Format("Start_invasion: dispatched all defender mobs, disregarding"); ImmortalChat.SendImmortalChat(null, ImmortalChat.IMMTALK_SPAM, 0, lbuf); // return; } // warn of invasion foreach (SocketConnection it in Database.SocketList) { socket = it; if (socket.ConnectionStatus == SocketConnection.ConnectionState.playing && socket.Character.InRoom.Area == ch.InRoom.Area) { socket.Character.SendText("&+RYou hear the guards sound the invasion alarm!\r\n"); } } // create and dispatch defenders for (count = 0; count < ch.InRoom.Area.DefendersPerSquad; ++count) { if (ch.InRoom.Area.NumDefendersDispatched >= ch.InRoom.Area.DefendersPerSquad * 5) { break; } mob = Database.CreateMobile(Database.GetMobTemplate(ch.InRoom.Area.DefenderTemplateNumber)); mob.AddToRoom(Room.GetRoom(ch.InRoom.Area.BarracksRoom)); if (!mob.HasActionBit(MobTemplate.ACT_MEMORY)) { mob.SetActionBit(MobTemplate.ACT_MEMORY); } if (!mob.HasActionBit(MobTemplate.ACT_HUNTER)) { mob.SetActionBit(MobTemplate.ACT_HUNTER); } if (mob.HasActionBit(MobTemplate.ACT_SENTINEL)) { mob.RemoveActionBit(MobTemplate.ACT_SENTINEL); } mob.MobileTemplate.AddSpecFun("spec_justice_guard"); Combat.StartGrudge(mob, ch, false); ch.InRoom.Area.NumDefendersDispatched++; } ch.InRoom.Area.DefenderSquads++; return; }
/// <summary> /// Loads the entire MUD database including all classes, races, areas, helps, sytem data, etc. /// </summary> public void LoadDatabase() { DatabaseIsBooting = true; Log.Trace(DateTime.Now.ToShortDateString() + " BOOT: -------------------------[ Boot Log ]-------------------------"); Log.Trace("Validating that player directories exist."); for (Char letter = 'a'; letter <= 'z'; letter++) { String directory = FileLocation.PlayerDirectory + letter; if (!Directory.Exists(directory)) { Log.Trace("Creating directory: " + directory + "."); Directory.CreateDirectory(directory); } } Log.Trace("Player directories validated."); Log.Trace("Loading Database.SystemData."); Sysdata.Load(); SystemData.CurrentTime = DateTime.Now; SystemData.GameBootTime = SystemData.CurrentTime; // Set time and weather. Log.Trace("Setting time and weather."); SystemData.SetWeather(); Log.Trace("Loading static rooms."); StaticRooms.Load(); Log.Trace("Loaded " + StaticRooms.Count + " static rooms."); Log.Trace("Loading spells."); Spell.LoadSpells(); Log.Trace("Loaded " + Spell.SpellList.Count + " spells."); Log.Trace("Loading skills."); Skill.LoadSkills(); Log.Trace("Loaded " + Skill.SkillList.Count + " skills."); Log.Trace("Loading races."); Race.LoadRaces(); Log.Trace("Loaded " + Race.Count + " races."); Log.Trace("Initializing skill Levels."); { int cclass; foreach (KeyValuePair <String, Skill> kvp in Skill.SkillList) { for (cclass = 0; cclass < CharClass.ClassList.Length; cclass++) { kvp.Value.ClassAvailability[cclass] = Limits.LEVEL_LESSER_GOD; } } foreach (KeyValuePair <String, Spell> kvp in Spell.SpellList) { for (cclass = 0; cclass < CharClass.ClassList.Length; cclass++) { kvp.Value.SpellCircle[cclass] = Limits.MAX_CIRCLE + 3; } } } Log.Trace("Loading classes."); CharClass.LoadClasses(true); Log.Trace("Loaded " + CharClass.Count + " classes."); Log.Trace("Assigning spell circles."); AssignSpellCircles(); Log.Trace("Assigned spell circles."); Log.Trace("Loading socials."); SocialList = Socials.Load(); Log.Trace("Loaded " + Social.Count + " socials."); Log.Trace("Loading bans."); LoadBans(); Log.Trace("Loaded " + BanList.Count + " bans."); Log.Trace("Loading help entries."); HelpList = Help.Load(FileLocation.SystemDirectory + FileLocation.HelpFile); Log.Trace("Loaded " + Help.Count + " help entries."); Log.Trace("Loading screens."); Screen.Load(FileLocation.SystemDirectory + FileLocation.ScreenFile, FileLocation.BlankSystemFileDirectory + FileLocation.ScreenFile); Log.Trace("Loaded " + Screen.Count + " screens."); // Chatbots have to be loaded before mobs. Log.Trace("Loading chatbots."); ChatterBot.Load(); Log.Trace("Loaded " + ChatterBot.Count + " chatbots."); // Read in all the area files. Log.Trace("Reading in area files..."); LoadAreaFiles(); Log.Trace("Loaded " + Area.Count + " areas."); string buf = String.Format("Loaded {0} mobs, {1} objects, {2} rooms, {3} shops, {4} helps, {5} resets, and {6} quests.", MobTemplate.Count, ObjTemplate.Count, Room.Count, Shop.Count, Help.Count, Reset.Count, QuestData.Count); Log.Trace(buf); Log.Trace("Loading guilds."); Guild.LoadGuilds(); Log.Trace("Loaded " + Guild.Count + " guilds."); Log.Trace("Loading corpses."); CorpseList = CorpseData.Load(); Log.Trace("Loaded " + CorpseData.Count + " corpses."); Log.Trace("Loading crimes."); Crime.Load(); Log.Trace("Loaded " + Crime.Count + " crimes."); Log.Trace("Loading fraglist."); FraglistData.Fraglist.Load(); Log.Trace("Loading issues."); Issue.Load(); Log.Trace("Loaded " + Issue.Count + " issues."); Log.Trace("Loading bounties."); Bounty.Load(); Log.Trace("Loaded " + Bounty.Count + " bounties."); Log.Trace("Initializing movement parameters."); Movement.Initialize(); Log.Trace("Movement parameters initialized."); // Only compile spells that have attached code. Otherwise use default handlers. Log.Trace("Compiling spells."); int good = 0; int bad = 0; foreach (KeyValuePair <String, Spell> kvp in Spell.SpellList) { if (!String.IsNullOrEmpty(kvp.Value.Code)) { if (!SpellFunction.CompileSpell(kvp.Value)) { ++bad; } else { ++good; } } } Log.Trace("Done compiling spells. " + good + " were successful, " + bad + " failed."); // Links up exits and makes rooms runtime-ready so we can access them. Log.Trace("Linking exits."); LinkExits(); // This has to be after LinkExits(). Log.Trace("Loading zone connections."); ZoneConnectionList = ZoneConnection.Load(); // Link zones together based on file. foreach (ZoneConnection connection in ZoneConnectionList) { RoomTemplate room1 = Room.GetRoom(connection.FirstRoomNumber); RoomTemplate room2 = Room.GetRoom(connection.SecondRoomNumber); Exit.Direction direction = connection.FirstToSecondDirection; if (room1 != null && room2 != null && direction != Exit.Direction.invalid) { Exit exit = new Exit(); exit.TargetRoom = room2; exit.IndexNumber = connection.SecondRoomNumber; room1.ExitData[(int)direction] = exit; exit = new Exit(); exit.TargetRoom = room1; exit.IndexNumber = connection.FirstRoomNumber; room2.ExitData[(int)Exit.ReverseDirection(direction)] = exit; Log.Trace("Connected " + room1.Area.Name + " to " + room2.Area.Name + " at " + room1.IndexNumber); } else { Log.Error("Unable to connect room " + connection.FirstRoomNumber + " to " + connection.SecondRoomNumber + " in direction " + connection.FirstToSecondDirection); } } Log.Trace("Loaded " + ZoneConnectionList.Count + " zone connections."); DatabaseIsBooting = false; Log.Trace("Resetting areas."); AreaUpdate(); Log.Trace("Creating events."); Event.CreateEvent(Event.EventType.save_corpses, Event.TICK_SAVE_CORPSES, null, null, null); Event.CreateEvent(Event.EventType.save_sysdata, Event.TICK_SAVE_SYSDATA, null, null, null); Event.CreateEvent(Event.EventType.violence_update, Event.TICK_COMBAT_UPDATE, null, null, null); Event.CreateEvent(Event.EventType.area_update, Event.TICK_AREA, null, null, null); Event.CreateEvent(Event.EventType.room_update, Event.TICK_ROOM, null, null, null); Event.CreateEvent(Event.EventType.object_special, Event.TICK_OBJECT, null, null, null); Event.CreateEvent(Event.EventType.mobile_update, Event.TICK_MOBILE, null, null, null); Event.CreateEvent(Event.EventType.weather_update, Event.TICK_WEATHER, null, null, null); Event.CreateEvent(Event.EventType.char_update, Event.TICK_CHAR_UPDATE, null, null, null); Event.CreateEvent(Event.EventType.object_update, Event.TICK_OBJ_UPDATE, null, null, null); Event.CreateEvent(Event.EventType.aggression_update, Event.TICK_AGGRESS, null, null, null); Event.CreateEvent(Event.EventType.memorize_update, Event.TICK_MEMORIZE, null, null, null); Event.CreateEvent(Event.EventType.hit_gain, Event.TICK_HITGAIN, null, null, null); Event.CreateEvent(Event.EventType.mana_gain, Event.TICK_MANAGAIN, null, null, null); Event.CreateEvent(Event.EventType.move_gain, Event.TICK_MOVEGAIN, null, null, null); Event.CreateEvent(Event.EventType.heartbeat, Event.TICK_WEATHER, null, null, null); return; }
/// <summary> /// Links all room exits to the the appropriate _targetType room data. Reports any problems with /// nonexistant rooms or one-way exits. This must be done once and only once after all rooms are /// loaded. /// </summary> static void LinkExits() { Exit exit; Exit reverseExit; Room toRoom; int door; // First we have to convert into runtime rooms. foreach (Area area in AreaList) { for (int i = 0; i < area.Rooms.Count; i++) { area.Rooms[i] = new Room(area.Rooms[i]); } } foreach (Area area in AreaList) { foreach (Room room in area.Rooms) { // Set exit data. for (door = 0; door < Limits.MAX_DIRECTION; door++) { exit = room.ExitData[door]; if (exit != null) { if (exit.IndexNumber <= 0) { exit.TargetRoom = null; } else { exit.TargetRoom = Room.GetRoom(exit.IndexNumber); if (exit.TargetRoom == null) { string buf = String.Format("Room {0} in zone {1} has an exit in direction {2} to room {3}. Room {3} was not found.", room.IndexNumber, SocketConnection.RemoveANSICodes(room.Area.Name), door.ToString(), exit.IndexNumber); Log.Error(buf); // NOTE: We do not delete the exit data here because most non-linkable exits are due to // attached zones not loading. If we delete the exit data, that means that the zone link // will be irrevocably lost if we re-save the zone. However, if we leave the exit data // intact, when the missing zone is re-loaded in a future boot the exit should self-heal. } } } } } } foreach (Area area in AreaList) { foreach (RoomTemplate room in area.Rooms) { for (door = 0; door < Limits.MAX_DIRECTION; door++) { if ((exit = room.ExitData[door]) && (toRoom = Room.GetRoom(exit.IndexNumber)) && (reverseExit = toRoom.GetExit(Exit.ReverseDirection((Exit.Direction)door))) && reverseExit.TargetRoom != room) { String buf = String.Format("Database.LinkExits(): Mismatched Exit - Room {0} Exit {1} to Room {2} in zone {3}: Target room's {4} Exit points to Room {5}.", room.IndexNumber, door.ToString(), toRoom.IndexNumber, SocketConnection.RemoveANSICodes(room.Area.Name), Exit.ReverseDirection((Exit.Direction)door).ToString(), (!reverseExit.TargetRoom) ? 0 : reverseExit.TargetRoom.IndexNumber); Log.Info(buf); } } } } return; }