/// <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; }
/// <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; }