Пример #1
0
        /// <summary>
        /// Makes a string look drunk.
        /// </summary>
        /// <param name="inputString"></param>
        /// <param name="ch"></param>
        /// <returns></returns>
        public static string MakeDrunk(string inputString, CharData ch)
        {
            int drunklevel = 0;

            if (!ch.IsNPC())
            {
                drunklevel = ((PC)ch).Drunk;
            }

            // Nothing to do here.
            if (drunklevel == 0)
            {
                return(inputString);
            }

            string output = String.Empty;

            // Check how drunk a person is...
            for (int pos = 0; pos < inputString.Length; pos++)
            {
                char temp = inputString[pos];

                if ((char.ToUpper(temp) >= 'A') && (char.ToUpper(temp) <= 'Z'))
                {
                    int drunkpos = char.ToUpper(temp) - 'A';
                    if (drunklevel > _drunkSubstitution[drunkpos]._minDrunkLevel)
                    {
                        int randomnum = MUDMath.NumberRange(0, _drunkSubstitution[drunkpos]._numReplacements);
                        output += _drunkSubstitution[drunkpos]._replacement[randomnum];
                    }
                    else
                    {
                        output += temp;
                    }
                }
                else
                {
                    if (drunklevel < 4)
                    {
                        output += MUDMath.FuzzyNumber(temp);
                    }
                    else if ((temp >= '0') && (temp <= '9'))
                    {
                        output += MUDMath.NumberRange(0, 9).ToString();
                    }
                    else
                    {
                        output += temp;
                    }
                }
            }
            return(output);
        }
Пример #2
0
        /// <summary>
        /// Resets a room, reloading according to resets.
        /// </summary>
        /// <param name="notInitial"></param>
        /// <returns></returns>
        public bool ResetRoom(int notInitial)
        {
            Exit     exit = null;
            CharData mobile;
            CharData lastMob = null;
            int      level   = 0;
            bool     last    = true;
            // Added for debugging.
            string text = String.Empty;

            foreach (Reset reset in Area.Resets)
            {
                if (!reset.IsRoomReset(this))
                {
                    continue;
                }
                Object      obj;
                Object      lastObj;
                MobTemplate mobIndex;
                ObjTemplate objTemplate;
                Room        room;

                switch (reset.Command)
                {
                default:
                    Log.Error("RoomIndex.Reset(): bad command %c.", reset.Command);
                    break;

                case 'M':
                    mobIndex = Database.GetMobTemplate(reset.Arg1);
                    if (!mobIndex)
                    {
                        Log.Error("RoomIndex.Reset(): 'M': bad mob index number {0} for arg1.", reset.Arg1);
                        continue;
                    }

                    room = GetRoom(reset.Arg3);
                    if (!room)
                    {
                        Log.Error("RoomIndex.Reset(): 'R': bad room index number {0} for arg3.", reset.Arg3);
                        continue;
                    }

                    if ((mobIndex.HasSpecFun("spec_cast_ghost")) &&
                        (Database.SystemData.WeatherData.Sunlight > SunType.night) &&
                        (Database.SystemData.WeatherData.Sunlight < SunType.moonrise))
                    {
                        last = false;
                        continue;
                    }

                    level = Macros.Range(0, mobIndex.Level - 2, Limits.LEVEL_HERO);

                    if (mobIndex.NumActive >= reset.Arg2)
                    {
                        last = false;
                        break;
                    }
                    mobile = Database.CreateMobile(mobIndex);

                    // Check for pet shop.
                    Room prevRoom = GetRoom(room.IndexNumber - 1);
                    if (prevRoom && prevRoom.HasFlag(ROOM_PET_SHOP))
                    {
                        mobile.SetActionBit(MobTemplate.ACT_PET);
                    }

                    if (room.IsDark())
                    {
                        mobile.SetAffectBit(Affect.AFFECT_INFRAVISION);
                    }

                    mobile.AddToRoom(room);
                    mobile.LoadRoomIndexNumber = room.IndexNumber;

                    // This code makes mounts make their mounters mount them.
                    if (reset.Arg0 == -1 && lastMob)
                    {
                        // If set to be mounted.
                        String[] keywords = mobile.Name.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
                        Command.Mount(lastMob, keywords);
                    }

                    lastMob = mobile;

                    level = Macros.Range(0, mobile.Level - 2, Limits.LEVEL_HERO);
                    last  = true;
                    break;

                case 'F':
                    mobIndex = Database.GetMobTemplate(reset.Arg1);
                    if (!mobIndex)
                    {
                        Log.Error("RoomIndex.Reset(): 'F': bad mob index number {0} for arg1.", reset.Arg1);
                        continue;
                    }

                    room = GetRoom(reset.Arg3);
                    if (!room)
                    {
                        Log.Error("RoomIndex.Reset(): 'F': bad room index number {0} for arg3.", reset.Arg3);
                        continue;
                    }

                    if (mobIndex.HasSpecFun("spec_cast_ghost") && (Database.SystemData.WeatherData.Sunlight > SunType.night) &&
                        (Database.SystemData.WeatherData.Sunlight < SunType.moonrise))
                    {
                        last = false;
                        continue;
                    }

                    level = Macros.Range(0, mobIndex.Level - 2, Limits.LEVEL_HERO);

                    if (mobIndex.NumActive >= reset.Arg2)
                    {
                        last = false;
                        break;
                    }
                    mobile = Database.CreateMobile(mobIndex);

                    Room prev = GetRoom(room.IndexNumber - 1);
                    if (prev && prev.HasFlag(ROOM_PET_SHOP))
                    {
                        mobile.SetActionBit(MobTemplate.ACT_PET);
                    }

                    if (room.IsDark())
                    {
                        mobile.SetAffectBit(Affect.AFFECT_INFRAVISION);
                    }

                    // Set following bit. Can't have a message sent because
                    // there is no valid room number (causes a segmentation fault)
                    CharData.AddFollowerWithoutMessage(mobile, lastMob);

                    lastMob = mobile;
                    mobile.AddToRoom(room);
                    mobile.LoadRoomIndexNumber = room.IndexNumber;
                    level = Macros.Range(0, mobile.Level - 2, Limits.LEVEL_HERO);
                    last  = true;
                    break;

                case 'O':
                    if (notInitial != 0)
                    {
                        last = false;
                        continue;
                    }
                    objTemplate = Database.GetObjTemplate(reset.Arg1);
                    if (!objTemplate)
                    {
                        Log.Error("RoomIndex.Reset(): 'O': bad obj index number {0} for arg1.", reset.Arg1);
                        continue;
                    }

                    room = GetRoom(reset.Arg3);
                    if (!room)
                    {
                        Log.Error("RoomIndex.Reset(): 'O': bad room index number {0} for arg3.", reset.Arg3);
                        continue;
                    }

                    if (Area.NumPlayers > 0 || room._contents.Count != 0 && (Object.CountObjectInList(objTemplate, room._contents) > 0))
                    {
                        last = false;
                        break;
                    }
                    // check if is unique/arti
                    if (Database.IsArtifact(objTemplate.IndexNumber))
                    {
                        text += "RoomIndex.Reset(): Artifact found: " + objTemplate.Name + " (" + objTemplate.IndexNumber + ")";
                        Log.Trace(text);
                    }     //end if artiact

                    obj = Database.CreateObject(objTemplate, MUDMath.FuzzyNumber(level));
                    if (obj != null)
                    {
                        obj.Cost = 0;
                        obj.AddToRoom(this);
                        last = true;
                    }
                    else
                    {
                        Log.Error("RoomIndex.Reset(): Unable to Database.CreateObject {0}", reset.Arg3);
                    }
                    break;

                case 'P':
                    if (notInitial != 0)
                    {
                        last = false;
                        continue;
                    }
                    objTemplate = Database.GetObjTemplate(reset.Arg1);
                    if (!objTemplate)
                    {
                        Log.Error("RoomIndex.Reset(): 'P': bad obj index number {0} for arg3.", reset.Arg1);
                        continue;
                    }

                    ObjTemplate targetObjTemplate = Database.GetObjTemplate(reset.Arg3);
                    if (!targetObjTemplate)
                    {
                        Log.Error("RoomIndex.Reset(): 'P': bad obj index number {0} for arg3.", reset.Arg3);
                        continue;
                    }

                    if (Area.NumPlayers > 0 || !(lastObj = Object.GetFirstObjectOfTemplateType(targetObjTemplate)) ||
                        lastObj.Contains.Count != 0 && (Object.CountObjectInList(objTemplate, lastObj.Contains) > 0))
                    {
                        last = false;
                        break;
                    }
                    // check if is unique/arti
                    if (Database.IsArtifact(objTemplate.IndexNumber))
                    {
                        text += "RoomIndex.Reset(): Artifact found: " + objTemplate.Name + " (" + objTemplate.IndexNumber + ")";
                        Log.Trace(text);
                    }     //end if artifact

                    obj = Database.CreateObject(objTemplate, MUDMath.FuzzyNumber(lastObj.Level));
                    lastObj.AddToObject(obj);
                    last = true;

                    // Ensure that the container gets Reset.
                    if ((lastObj.ItemType == ObjTemplate.ObjectType.container) || (lastObj.ItemType == ObjTemplate.ObjectType.drink_container))
                    {
                        lastObj.Values[1] = lastObj.ObjIndexData.Values[1];
                    }
                    break;

                case 'G':
                case 'E':
                    if (notInitial != 0)
                    {
                        last = false;
                        continue;
                    }
                    objTemplate = Database.GetObjTemplate(reset.Arg1);
                    if (!objTemplate)
                    {
                        Log.Error("RoomIndex.Reset(): 'E' or 'G': bad obj index number {0} for arg1.", reset.Arg1);
                        continue;
                    }

                    if (!last)
                    {
                        break;
                    }

                    if (!lastMob)
                    {
                        Log.Error("RoomIndex.Reset(): 'E' or 'G': null mob for index number {0} for arg1.", reset.Arg1);
                        last = false;
                        break;
                    }
                    // check if is unique/arti
                    if (Database.IsArtifact(objTemplate.IndexNumber))
                    {
                        text += "RoomIndex.Reset(): Artifact found: " + objTemplate.Name + " (" + objTemplate.IndexNumber + ")";
                        Log.Trace(text);
                    }                                    //end if artifact

                    if (lastMob.MobileTemplate.ShopData) /* Shop-keeper? */
                    {
                        int olevel;

                        switch (objTemplate.ItemType)
                        {
                        default:
                            olevel = 0;
                            break;

                        case ObjTemplate.ObjectType.pill:
                            olevel = MUDMath.NumberRange(0, 10);
                            break;

                        case ObjTemplate.ObjectType.potion:
                            olevel = MUDMath.NumberRange(0, 10);
                            break;

                        case ObjTemplate.ObjectType.scroll:
                            olevel = MUDMath.NumberRange(5, 15);
                            break;

                        case ObjTemplate.ObjectType.wand:
                            olevel = MUDMath.NumberRange(10, 20);
                            break;

                        case ObjTemplate.ObjectType.staff:
                            olevel = MUDMath.NumberRange(15, 25);
                            break;

                        case ObjTemplate.ObjectType.armor:
                            olevel = MUDMath.NumberRange(5, 15);
                            break;

                        case ObjTemplate.ObjectType.other:
                            olevel = MUDMath.NumberRange(5, 15);
                            break;

                        case ObjTemplate.ObjectType.clothing:
                            olevel = MUDMath.NumberRange(5, 15);
                            break;

                        case ObjTemplate.ObjectType.weapon:
                            if (reset.Command == 'G')
                            {
                                olevel = MUDMath.NumberRange(5, 15);
                            }
                            else
                            {
                                olevel = MUDMath.FuzzyNumber(level);
                            }
                            break;
                        }

                        obj = Database.CreateObject(objTemplate, olevel);
                        if (reset.Command == 'G')
                        {
                            obj.AddFlag(ObjTemplate.ITEM_INVENTORY);
                        }
                    }
                    else
                    {
                        obj = Database.CreateObject(objTemplate, MUDMath.FuzzyNumber(level));
                    }
                    obj.ObjToChar(lastMob);
                    if (reset.Command == 'E')
                    {
                        lastMob.EquipObject(ref obj, (ObjTemplate.WearLocation)reset.Arg3);
                    }
                    last = true;
                    break;

                case 'D':
                    if (reset.Arg2 < 0 || reset.Arg2 >= Limits.MAX_DIRECTION || !(exit = ExitData[reset.Arg2]) ||
                        !exit.HasFlag(Exit.ExitFlag.is_door))
                    {
                        Log.Error("RoomIndex.Reset(): 'D': exit {0} not door for arg2.", reset.Arg2);
                    }

                    switch (reset.Arg3)
                    {
                    default:
                        Log.Error("RoomIndex.Reset(): 'D': bad 'locks': {0} for arg3.", reset.Arg3);
                        break;

                    case 0:
                        break;

                    case 1:
                        exit.AddFlag(Exit.ExitFlag.closed);
                        break;

                    case 2:
                        exit.AddFlag(Exit.ExitFlag.closed | Exit.ExitFlag.locked);
                        break;

                    case 4:
                        exit.AddFlag(Exit.ExitFlag.secret);
                        break;

                    case 5:
                        exit.AddFlag(Exit.ExitFlag.secret | Exit.ExitFlag.closed);
                        break;

                    case 6:
                        exit.AddFlag(Exit.ExitFlag.secret | Exit.ExitFlag.closed | Exit.ExitFlag.locked);
                        break;

                    case 8:
                        exit.AddFlag(Exit.ExitFlag.blocked);
                        break;

                    case 9:
                        exit.AddFlag(Exit.ExitFlag.blocked | Exit.ExitFlag.closed);
                        break;

                    case 10:
                        exit.AddFlag(Exit.ExitFlag.blocked | Exit.ExitFlag.closed | Exit.ExitFlag.locked);
                        break;

                    case 12:
                        exit.AddFlag(Exit.ExitFlag.blocked | Exit.ExitFlag.secret);
                        break;

                    case 13:
                        exit.AddFlag(Exit.ExitFlag.blocked | Exit.ExitFlag.secret | Exit.ExitFlag.closed);
                        break;

                    case 14:
                        exit.AddFlag(Exit.ExitFlag.blocked | Exit.ExitFlag.secret | Exit.ExitFlag.closed | Exit.ExitFlag.locked);
                        break;
                    }
                    break;

                case 'R':
                    Log.Trace("Unsupported randomize room exits call.  Please implement this.");
                    break;
                }
            }

            return(true);
        }
Пример #3
0
        /// <summary>
        /// Create an instance of a mobile from the provided template.
        /// </summary>
        /// <param name="mobTemplate"></param>
        /// <returns></returns>
        public static CharData CreateMobile(MobTemplate mobTemplate)
        {
            int count;

            if (!mobTemplate)
            {
                Log.Error("CreateMobile: null MobTemplate.", 0);
                throw new NullReferenceException();
            }

            CharData mob = new CharData();

            mob.MobileTemplate       = mobTemplate;
            mob.Followers            = null;
            mob.Name                 = mobTemplate.PlayerName;
            mob.ShortDescription     = mobTemplate.ShortDescription;
            mob.FullDescription      = mobTemplate.FullDescription;
            mob.Description          = mobTemplate.Description;
            mob.SpecialFunction      = mobTemplate.SpecFun;
            mob.SpecialFunctionNames = mobTemplate.SpecFunNames;
            mob.CharacterClass       = mobTemplate.CharacterClass;
            mob.Level                = MUDMath.FuzzyNumber(mobTemplate.Level);
            mob.ActionFlags          = mobTemplate.ActionFlags;
            mob.CurrentPosition      = mobTemplate.DefaultPosition;
            mob.ChatterBotName       = mobTemplate.ChatterBotName;
            // TODO: Look up the chatter bot name and load a runtime bot into the variable.
            mob.ChatBot = null;
            for (count = 0; count < Limits.NUM_AFFECT_VECTORS; ++count)
            {
                mob.AffectedBy[count] = mobTemplate.AffectedBy[count];
            }
            mob.Alignment = mobTemplate.Alignment;
            mob.Gender    = mobTemplate.Gender;
            mob.SetPermRace(mobTemplate.Race);
            mob.CurrentSize = Race.RaceList[mob.GetRace()].DefaultSize;
            if (mob.HasActionBit(MobTemplate.ACT_SIZEMINUS))
            {
                mob.CurrentSize--;
            }
            if (mob.HasActionBit(MobTemplate.ACT_SIZEPLUS))
            {
                mob.CurrentSize++;
            }

            mob.CastingSpell         = 0;
            mob.CastingTime          = 0;
            mob.PermStrength         = MUDMath.Dice(2, 46) + 8;
            mob.PermIntelligence     = MUDMath.Dice(2, 46) + 8;
            mob.PermWisdom           = MUDMath.Dice(2, 46) + 8;
            mob.PermDexterity        = MUDMath.Dice(2, 46) + 8;
            mob.PermConstitution     = MUDMath.Dice(2, 46) + 7;
            mob.PermAgility          = MUDMath.Dice(2, 46) + 8;
            mob.PermCharisma         = MUDMath.Dice(2, 46) + 8;
            mob.PermPower            = MUDMath.Dice(2, 46) + 8;
            mob.PermLuck             = MUDMath.Dice(2, 46) + 8;
            mob.ModifiedStrength     = 0;
            mob.ModifiedIntelligence = 0;
            mob.ModifiedWisdom       = 0;
            mob.ModifiedDexterity    = 0;
            mob.ModifiedConstitution = 0;
            mob.ModifiedAgility      = 0;
            mob.ModifiedCharisma     = 0;
            mob.ModifiedPower        = 0;
            mob.ModifiedLuck         = 0;
            mob.Resistant            = mobTemplate.Resistant;
            mob.Immune      = mobTemplate.Immune;
            mob.Susceptible = mobTemplate.Susceptible;
            mob.Vulnerable  = mobTemplate.Vulnerable;
            mob.MaxMana     = mob.Level * 10;
            if (Race.RaceList[mobTemplate.Race].Coins)
            {
                int level = mobTemplate.Level;
                mob.ReceiveCopper(MUDMath.Dice(12, level) / 32);
                mob.ReceiveSilver(MUDMath.Dice(9, level) / 32);
                mob.ReceiveGold(MUDMath.Dice(5, level) / 32);
                mob.ReceivePlatinum(MUDMath.Dice(2, level) / 32);
            }
            else
            {
                mob.SetCoins(0, 0, 0, 0);
            }
            mob.ArmorPoints = MUDMath.Interpolate(mob.Level, 100, -100);

            // * MOB HITPOINTS *
            //
            // Was level d 8, upped it to level d 13
            // considering mobs *still* won't have as many hitpoints as some players until
            // at least level 10, this shouldn't be too big an upgrade.
            //
            // Mob hitpoints are not based on constitution *unless* they have a
            // constitution modifier from an item, spell, or other affect

            // In light of recent player dissatisfaction with the
            // mob hitpoints, I'm implementing a log curve, using
            //  hp = exp( 2.15135 + level*0.151231)
            // This will will result in the following hp matrix:
            //     Level    Hitpoints
            //      20        175
            //      30        803
            //      40        3643
            //      50        16528
            //      55        35207
            //      60        75000
            mob.MaxHitpoints = MUDMath.Dice(mob.Level, 13) + 1;
            // Mob hps are non-linear above level 10.
            if (mob.Level > 20)
            {
                int upper = (int)Math.Exp(1.85 + mob.Level * 0.151231);
                int lower = (int)Math.Exp(1.80 + mob.Level * 0.151231);
                mob.MaxHitpoints += MUDMath.NumberRange(lower, upper);
            }
            else if (mob.Level > 10)
            {
                mob.MaxHitpoints += MUDMath.NumberRange(mob.Level * 2, ((mob.Level - 8) ^ 2 * mob.Level) / 2);
            }

            // Demons/devils/dragons gain an extra 30 hitpoints per level (+1500 at lvl 50).
            if (mob.GetRace() == Race.RACE_DEMON || mob.GetRace() == Race.RACE_DEVIL || mob.GetRace() == Race.RACE_DRAGON)
            {
                mob.MaxHitpoints += (mob.Level * 30);
            }

            mob.Hitpoints = mob.GetMaxHit();

            // Horses get more moves, necessary for mounts.
            if (Race.RaceList[mob.GetRace()].Name.Equals("Horse", StringComparison.CurrentCultureIgnoreCase))
            {
                mob.MaxMoves     = 290 + MUDMath.Dice(4, 5);
                mob.CurrentMoves = mob.MaxMoves;
            }
            mob.LoadRoomIndexNumber = 0;

            // Insert in list.
            CharList.Add(mob);
            // Increment count of in-game instances of mob.
            mobTemplate.NumActive++;
            return(mob);
        }
Пример #4
0
        /// <summary>
        /// Updates the weather and game hour.  Also updates things that depend on the game hour.
        ///
        /// Weather depends on the time of year.
        /// </summary>
        public void UpdateWeather()
        {
            string text = String.Empty;

            UpdatePlayerCount();

            switch (++GameHour)
            {
            case 4:
                WeatherData.Sunlight = SunType.moonset;
                if (WeatherData.MoonPhase != MoonPhase.new_moon)
                {
                    text = "&+cThe &+Cmoon&n&+c slowly &+Lvanishes&n&+c from the horizon.&n\r\n";
                }
                break;

            case 6:
                WeatherData.Sunlight = SunType.sunrise;
                text = "&+cThe first &+Clights&n&+c of &+md&+Maw&n&+mn &n&+cilluminate the&+C sky&n.\r\n";
                WeatherData.Temperature += MUDMath.FuzzyNumber(10);
                break;

            case 7:
                WeatherData.Sunlight = SunType.daytime;
                text = "&+MA new day has begun as the &+Ysun&+M rises&n.&n\r\n";
                if (GameMonth <= 4 || GameMonth >= 15)
                {
                    WeatherData.Temperature = MUDMath.FuzzyNumber(20);
                }
                else
                {
                    WeatherData.Temperature = MUDMath.FuzzyNumber(50);
                }
                break;

            case 12:
                text = "&+cThe &+Ysun&n &+cnow hangs at high noon&n.\r\n";
                WeatherData.Temperature += MUDMath.FuzzyNumber(20);
                break;

            case 19:
                WeatherData.Sunlight = SunType.sunset;
                text = "&+mThe &+Ysun&n&+m slowly slips off the &+Mhorizon&n.\r\n";
                WeatherData.Temperature -= MUDMath.FuzzyNumber(20);
                break;

            case 20:
                WeatherData.Sunlight = SunType.night;
                text = "&+LThe night begins as darkness settles across the lands&n.\r\n";
                WeatherData.Temperature -= MUDMath.FuzzyNumber(10);
                break;

            case Limits.HOURS_PER_DAY:
                WeatherData.Sunlight     = SunType.moonrise;
                WeatherData.Temperature -= MUDMath.FuzzyNumber(10);
                GameHour = 0;
                GameDay++;

                // Moon stuff
                WeatherData.Moonday++;

                if (WeatherData.Moonday >= LUNAR_CYCLE_DAYS)
                {
                    WeatherData.MoonPhase = MoonPhase.new_moon;
                    WeatherData.Moonday   = 0;
                }
                else
                {
                    if (WeatherData.Moonday < (LUNAR_CYCLE_DAYS / 8))
                    {
                        WeatherData.MoonPhase = MoonPhase.new_moon;
                    }
                    else if (WeatherData.Moonday < (LUNAR_CYCLE_DAYS / 4))
                    {
                        WeatherData.MoonPhase = MoonPhase.quarter;
                    }
                    else if (WeatherData.Moonday < (LUNAR_CYCLE_DAYS * 3 / 8))
                    {
                        WeatherData.MoonPhase = MoonPhase.half;
                    }
                    else if (WeatherData.Moonday < (LUNAR_CYCLE_DAYS / 2))
                    {
                        WeatherData.MoonPhase = MoonPhase.three_quarter;
                    }
                    else if (WeatherData.Moonday < (LUNAR_CYCLE_DAYS * 5 / 8))
                    {
                        WeatherData.MoonPhase = MoonPhase.full;
                    }
                    else if (WeatherData.Moonday < (LUNAR_CYCLE_DAYS * 3 / 4))
                    {
                        WeatherData.MoonPhase = MoonPhase.three_quarter;
                    }
                    else if (WeatherData.Moonday < (LUNAR_CYCLE_DAYS * 7 / 8))
                    {
                        WeatherData.MoonPhase = MoonPhase.half;
                    }
                    else if (WeatherData.Moonday < (LUNAR_CYCLE_DAYS))
                    {
                        WeatherData.MoonPhase = MoonPhase.quarter;
                    }
                }

                switch (WeatherData.MoonPhase)
                {
                default:
                    break;

                case MoonPhase.new_moon:
                    text += "&+LThe night sky is overshadowed by an uncommon darkness.&n\r\n";
                    break;

                case MoonPhase.full:
                    text += "&n&+LThe &+Cmoon&n&+L rises full, casting a &n&+wsi&+Wlv&n&+wer &n&+cglow&+L across the entire sky.&n\r\n";
                    break;

                case MoonPhase.three_quarter:
                    text += "&n&+LThe &+Cmoon&n&+L ascends, a small &n&+csliver&+L absent against the night sky.&n\r\n";
                    break;

                case MoonPhase.half:
                    text += "&n&+LA giant half-circle, the &+Cmoon&n&+L rises against the blanket of night.&n\r\n";
                    break;

                case MoonPhase.quarter:
                    text += "&n&+LThe &+Cmoon&n&+L rises, a &n&+wsi&+Wlv&n&+wer &+csliver&n&+L against the dark firmament.&n\r\n";
                    break;
                }
                break;
            }

            if (GameDay >= Limits.DAYS_PER_MONTH)
            {
                GameDay = 0;
                GameMonth++;
            }

            if (GameMonth >= Limits.MONTHS_PER_YEAR)
            {
                GameMonth = 0;
                GameYear++;
            }

            // Weather change.
            WeatherData.WindDirection += MUDMath.NumberRange(0, 2) - 1;

            int diff = 0;

            if (GameMonth >= 9 && GameMonth <= 16)
            {
                diff = WeatherData.BarometricPressure > 985 ? -2 : 2;
            }
            else
            {
                diff = WeatherData.BarometricPressure > 1015 ? -2 : 2;
            }

            WeatherData.Change += diff * MUDMath.Dice(1, 4) + MUDMath.Dice(2, 6) - MUDMath.Dice(2, 6);
            WeatherData.Change  = Math.Max(WeatherData.Change, -12);
            WeatherData.Change  = Math.Min(WeatherData.Change, 12);

            WeatherData.BarometricPressure += WeatherData.Change;
            WeatherData.BarometricPressure  = Math.Max(WeatherData.BarometricPressure, 960);
            WeatherData.BarometricPressure  = Math.Min(WeatherData.BarometricPressure, 1040);

            switch (WeatherData.Sky)
            {
            default:
                Log.Error("WeatherUpdate: bad sky {0}.", WeatherData.Sky);
                WeatherData.Sky = SkyType.clear;
                break;

            case SkyType.clear:
                if (WeatherData.BarometricPressure < 990 || (WeatherData.BarometricPressure < 1010 && MUDMath.NumberBits(2) == 0))
                {
                    if (GameMonth <= 3 || GameMonth >= 11)
                    {
                        text += "&+wA few &+Wf&n&+wl&+Wa&n&+wk&+We&n&+ws of &+Ws&n&+wn&+Wo&n&+ww&+w are falling&n.\r\n";
                        WeatherData.Temperature -= 10;
                    }
                    else
                    {
                        text += "&+LStorm clouds &n&+mthunder&+L in the distance&n.\r\n";
                    }
                    WeatherData.Sky        = SkyType.cloudy;
                    WeatherData.WindSpeed += 10;
                }
                break;

            case SkyType.cloudy:
                if (WeatherData.BarometricPressure < 970 || (WeatherData.BarometricPressure < 990 && MUDMath.NumberBits(2) == 0))
                {
                    if (GameMonth <= 3 || GameMonth >= 11)
                    {
                        text += "&+wThe &+Wharsh s&n&+wn&+Wo&n&+ww-&+Lstorm&n&+w makes visibility difficult&n.\r\n";
                        WeatherData.Temperature -= 10;
                    }
                    else
                    {
                        text += "&+cSmall drops of &+Crain&n&+w m&+Wis&n&+wt the air&n.\r\n";
                    }
                    WeatherData.Sky        = SkyType.rain;
                    WeatherData.WindSpeed += 10;
                }

                if (WeatherData.BarometricPressure > 1030 && MUDMath.NumberBits(2) == 0)
                {
                    if (GameMonth <= 3 || GameMonth >= 11)
                    {
                        text += "&+wThe &+Wsnow&n&+w-&+Lstorm&n&+w seems to settle&n.\r\n";
                        WeatherData.Temperature += 10;
                    }
                    else
                    {
                        text += "&+cThe &+Cclouds&n&+c disappear from the skyline&n.\r\n";
                    }
                    WeatherData.Sky        = SkyType.clear;
                    WeatherData.WindSpeed -= 10;
                }
                break;

            case SkyType.rain:
                if (WeatherData.BarometricPressure < 970 && MUDMath.NumberBits(2) == 0)
                {
                    if (GameMonth <= 3 || GameMonth >= 11)
                    {
                        text += "&+wThe &+Wsnow-&+cstorm&n&+w has evolved into a full &+Cblizzard&n.\r\n";
                        WeatherData.Temperature -= 30;
                    }
                    else
                    {
                        text += "&+WLightning flashes across the sky&n.\r\n";
                    }
                    WeatherData.Sky        = SkyType.thunderstorm;
                    WeatherData.WindSpeed += 10;
                }

                if (WeatherData.BarometricPressure > 1030 || (WeatherData.BarometricPressure > 1010 && MUDMath.NumberBits(2) == 0))
                {
                    if (GameMonth <= 3 || GameMonth >= 11)
                    {
                        text += "&+wThe &+Ws&n&+wn&+Wo&n&+ww seems to be letting up&n.\r\n";
                        WeatherData.Temperature += 30;
                    }
                    else
                    {
                        text += "&+cThe &+Crain&n&+c slows to a drizzle then quits&n.\r\n";
                    }
                    WeatherData.Sky        = SkyType.cloudy;
                    WeatherData.WindSpeed -= 10;
                }
                break;

            case SkyType.thunderstorm:
                if (WeatherData.BarometricPressure > 1010 || (WeatherData.BarometricPressure > 990 && MUDMath.NumberBits(2) == 0))
                {
                    if (GameMonth <= 3 || GameMonth >= 11)
                    {
                        text += "&+wThe &+Wblizzard&n&+w subsides&n.\r\n";
                        WeatherData.Temperature += 10;
                    }
                    else
                    {
                        text += "&n&+wThe &+Lthunder &N&+wand &+Clightning&n&+w has stopped&N.\r\n";
                    }
                    WeatherData.Sky        = SkyType.rain;
                    WeatherData.WindSpeed -= 10;
                    break;
                }
                break;
            }

            if (text.Length > 0)
            {
                foreach (SocketConnection socket in Database.SocketList)
                {
                    if (socket.ConnectionStatus == SocketConnection.ConnectionState.playing &&
                        socket.Character.IsOutside() && !socket.Character.IsUnderground() &&
                        socket.Character.IsAwake() && !socket.Character.InRoom.HasFlag(RoomTemplate.ROOM_NO_PRECIP))
                    {
                        socket.Character.SendText(text);
                    }
                }
            }

            foreach (SocketConnection playerSocket in Database.SocketList)
            {
                if ((playerSocket.ConnectionStatus == SocketConnection.ConnectionState.playing) &&
                    !playerSocket.Character.IsNPC())
                {
                    if (((PC)playerSocket.Character).FirstaidTimer > 0)
                    {
                        ((PC)playerSocket.Character).FirstaidTimer -= 1;
                    }
                }
            }

            return;
        }