/// <summary> /// Check whether the being entering the area is an enemy and needs to be dealt with. /// </summary> /// <param name="ch"></param> public static void CheckInvader(CharData ch) { string lbuf; if (ch == null || ch.IsNPC() || ch.IsImmortal()) { return; } if (ch.InRoom == null || ch.InRoom.Area == null || ch.InRoom.Area.JusticeType == 0) { return; } switch (ch.GetRacewarSide()) { case Race.RacewarSide.good: if (ch.InRoom.Area.JusticeType == JusticeType.chaotic_evil || ch.InRoom.Area.JusticeType == JusticeType.chaotic_evil_only || ch.InRoom.Area.JusticeType == JusticeType.chaotic_neutral_only || ch.InRoom.Area.JusticeType == JusticeType.evil_only || ch.InRoom.Area.JusticeType == JusticeType.neutral_only || ch.InRoom.Area.JusticeType == JusticeType.evil) { lbuf = String.Format("Check_invader: {0} invading !good justice", ch.Name); ImmortalChat.SendImmortalChat(null, ImmortalChat.IMMTALK_SPAM, 0, lbuf); StartInvasion(ch); } return; case Race.RacewarSide.evil: if (ch.InRoom.Area.JusticeType == JusticeType.chaotic_good || ch.InRoom.Area.JusticeType == JusticeType.chaotic_good_only || ch.InRoom.Area.JusticeType == JusticeType.chaotic_neutral_only || ch.InRoom.Area.JusticeType == JusticeType.good_only || ch.InRoom.Area.JusticeType == JusticeType.neutral_only || ch.InRoom.Area.JusticeType == JusticeType.good) { lbuf = String.Format("Check_invader: {0} invading !evil justice", ch.Name); ImmortalChat.SendImmortalChat(null, ImmortalChat.IMMTALK_SPAM, 0, lbuf); StartInvasion(ch); } return; case Race.RacewarSide.neutral: if (ch.InRoom.Area.JusticeType == JusticeType.chaotic_good_only || ch.InRoom.Area.JusticeType == JusticeType.chaotic_evil_only || ch.InRoom.Area.JusticeType == JusticeType.evil_only || ch.InRoom.Area.JusticeType == JusticeType.good_only) { lbuf = String.Format("Check_invader: {0} invading !neutral justice", ch.Name); ImmortalChat.SendImmortalChat(null, ImmortalChat.IMMTALK_SPAM, 0, lbuf); StartInvasion(ch); } return; } return; }
/// <summary> /// Logs the error message to the source with the specified _name. /// </summary> /// <remarks> /// See summary. /// </remarks> /// <param name="message">The message to log.</param> /// <param name="name">The name for the message.</param> public static void Error(string message, string name) { lock (_syncRoot) { // log message. LogEntry le = new LogEntry(message, name); le.EventType = LogEntry.LogType.Error; WriteLogLine(le); ImmortalChat.SendImmortalChat(null, ImmortalChat.IMMTALK_DEBUG, Limits.LEVEL_OVERLORD, message); } }
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; }
/// <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; }
/// <summary> /// Code to check if someone just fragged. /// Will also have to add to race, class, and guild frag tables in /// addition to the master frag table. This does not update any /// lists yet and instead only updates the totals. /// </summary> /// <param name="ch"></param> /// <param name="victim"></param> public static void CheckForFrag(CharData ch, CharData victim) { // NPC's don't participate in fragging, can't frag yourself, // have to be within 10 levels, no same side frags, no frags // from races not participating in racewars, have to be level // 20 to frag, and have to be a valid class. // Check to see if kill qualifies for a frag. if (ch.IsNPC()) { return; } if (victim.IsNPC()) { return; } if (ch == victim) { return; } if (ch.GetRacewarSide() == Race.RacewarSide.neutral) { return; } if (!ch.IsRacewar(victim)) { return; } if (ch.IsImmortal()) { return; } if (victim.IsImmortal()) { return; } if (victim.Level < 20) { return; } if (ch.Level < 20) { return; } if ((ch.Level - 10) > victim.Level) { return; } if (ch.IsClass(CharClass.Names.none) || victim.IsClass(CharClass.Names.none)) { return; } if (victim.GetOrigRace() > Limits.MAX_PC_RACE) { return; } // Give frag to ch. ((PC)ch).Frags++; // Protect against polymorphed character race frags. if (ch.GetOrigRace() < Limits.MAX_PC_RACE) { _fraglist._totalFragsByRaceAndClass[ch.GetOrigRace()][(int)ch.CharacterClass.ClassNumber]++; _fraglist._totalFragsBySide[(int)ch.GetRacewarSide()]++; } if (((PC)ch).GuildMembership != null) { ((PC)ch).GuildMembership.Frags++; } // Take frag from victim. ((PC)victim).Frags--; // Protect against polymorphed character race frags if (victim.GetOrigRace() < Limits.MAX_PC_RACE) { _fraglist._totalFragsByRaceAndClass[victim.GetOrigRace()][(int)victim.CharacterClass.ClassNumber]--; _fraglist._totalFragsBySide[(int)victim.GetRacewarSide()]--; } if (((PC)victim).GuildMembership != null) { ((PC)victim).GuildMembership.Frags--; } ch.SendText("&+WYou gain a frag!&n\r\n"); victim.SendText("&+WYou lose a frag!&n\r\n"); string text = ch.Name + " has fragged " + victim.Name + " in room " + ch.InRoom.IndexNumber + "."; ImmortalChat.SendImmortalChat(ch, ImmortalChat.IMMTALK_DEATHS, Limits.LEVEL_AVATAR, text); Log.Trace(text); // Check to see if either person goes up or down on their particular lists. if (((PC)ch).Frags > 0) { SortFraglist(ch, _fraglist._topFrags); SortFraglist(ch, _fraglist._topRaceFrags[ch.GetOrigRace()]); SortFraglist(ch, _fraglist._topClassFrags[(int)ch.CharacterClass.ClassNumber]); } else if (((PC)ch).Frags < 0) { SortFraglist(ch, _fraglist._bottomFrags); SortFraglist(ch, _fraglist._bottomRaceFrags[ch.GetOrigRace()]); SortFraglist(ch, _fraglist._bottomClassFrags[(int)ch.CharacterClass.ClassNumber]); } if (((PC)victim).Frags > 0) { SortFraglist(victim, _fraglist._topFrags); SortFraglist(victim, _fraglist._topRaceFrags[victim.GetOrigRace()]); SortFraglist(victim, _fraglist._topClassFrags[(int)victim.CharacterClass.ClassNumber]); } else if (((PC)victim).Frags < 0) { SortFraglist(victim, _fraglist._bottomFrags); SortFraglist(victim, _fraglist._bottomRaceFrags[victim.GetOrigRace()]); SortFraglist(victim, _fraglist._bottomClassFrags[(int)victim.CharacterClass.ClassNumber]); } _fraglist.Save(); return; }
/// <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> /// Repopulate areas periodically. /// /// Also gradually replenishes a town's guard store if guards have been killed. /// </summary> static public void AreaUpdate() { int numPlayers = 0; foreach (Area area in AreaList) { CharData roomChar; if (area.NumDefendersDispatched > 0) { area.NumDefendersDispatched--; } // Increment the area's age in seconds. area.AgeInSeconds += Event.TICK_AREA; // Reset area normally. if (area.AreaResetMode == Area.ResetMode.normal && area.TimesReset != 0) { continue; } // Reset area only when empty of players if (area.AreaResetMode == Area.ResetMode.empty_of_players && area.NumPlayers > 0) { String text = String.Format("{0} not being Reset, {1} players are present.", area.Filename, area.NumPlayers); ImmortalChat.SendImmortalChat(null, ImmortalChat.IMMTALK_RESETS, Limits.LEVEL_OVERLORD, text); Log.Trace(text); continue; } // Reset area only when no objects are still in the area. if (area.AreaResetMode == Area.ResetMode.empty_of_objects) { foreach (Room room in area.Rooms) { foreach (Object obj in room.Contents) { if (obj.HasWearFlag(ObjTemplate.WEARABLE_CARRY)) { String buf = String.Format("{0} not being Reset, at least one takeable object is present.", area.Filename); ImmortalChat.SendImmortalChat(null, ImmortalChat.IMMTALK_RESETS, Limits.LEVEL_OVERLORD, buf); Log.Trace(buf); continue; } } } } // Reset area only when no mobiles are alive in the area. if (area.AreaResetMode == Area.ResetMode.empty_of_mobiles) { foreach (Room room in area.Rooms) { foreach (CharData ch in room.People) { if (ch.IsNPC()) { String buf = String.Format("{0} not being Reset, at least one mobile is present.", area.Filename); ImmortalChat.SendImmortalChat(null, ImmortalChat.IMMTALK_RESETS, Limits.LEVEL_OVERLORD, buf); Log.Trace(buf); continue; } } } } // Reset area only when all quests are completed. if (area.AreaResetMode == Area.ResetMode.all_quests_completed) { foreach (QuestTemplate qst in area.Quests) { foreach (QuestData quest in qst.Quests) { foreach (QuestItem item in quest.Receive) { if (item.Completed == false) { String buf = String.Format("{0} not being Reset, at least one quest has not been completed.", area.Filename); ImmortalChat.SendImmortalChat(null, ImmortalChat.IMMTALK_RESETS, Limits.LEVEL_OVERLORD, buf); Log.Trace(buf); continue; } } } } } if ((area.AgeInSeconds / 60) < area.MinutesBetweenResets && area.TimesReset != 0) { continue; } foreach (CharData cd in CharList) { roomChar = cd; if (!roomChar.IsNPC() && roomChar.InRoom != null && roomChar.InRoom.Area == area) { numPlayers++; } } // Check for PC's and notify them if necessary. if (area.NumPlayers > 0) { foreach (CharData chd in CharList) { roomChar = chd; if (!roomChar.IsNPC() && roomChar.IsAwake() && roomChar.InRoom && roomChar.InRoom.Area == area && !String.IsNullOrEmpty(area.ResetMessage)) { roomChar.SendText(String.Format("{0}\r\n", area.ResetMessage)); } } } // Check age and Reset. String outbuf = String.Format("{0} has just been Reset after {1} minutes.", area.Filename, (area.AgeInSeconds / 60)); ImmortalChat.SendImmortalChat(null, ImmortalChat.IMMTALK_RESETS, Limits.LEVEL_OVERLORD, outbuf); ResetArea(area); } return; }