/// <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> /// Command to fly in a particular direction. /// </summary> /// <param name="ch"></param> /// <param name="str"></param> public static void Fly(CharData ch, string[] str) { if( ch == null ) return; Room troom; Exit texit; if (ch.Fighting || ch.CurrentPosition == Position.fighting) { ch.SendText("&+cNot &+Wwhile &+cyou&+Wr fi&+cghting...&n\r\n"); return; } if (ch.Riding) { if (!ch.Riding.CanFly()) { ch.SendText("Your mount can't fly.\r\n"); return; } } if (str.Length == 0 && ch.CanFly()) { ch.SendText("Yep, you're flying. Maybe you want to fly up or fly down."); return; } if (str.Length == 0 && !ch.CanFly()) { ch.SendText("Alas you are landbound.\r\n"); return; } if (!MUDString.IsPrefixOf(str[0], "up")) { if (!ch.CanFly()) { ch.SendText("You cannot fly.\r\n"); return; } if (!ch.InRoom.IsFlyable()) { ch.SendText("You cannot fly here.\r\n"); return; } if (ch.InRoom.TerrainType == TerrainType.plane_of_air) { ch.SendText("That's not really an option here.\r\n"); return; } if (ch.FlightLevel < CharData.FlyLevel.high) { SocketConnection.Act("$n&n flies up higher.", ch, null, null, SocketConnection.MessageTarget.room); ch.FlightLevel++; SocketConnection.Act("$n&n flies in from below.", ch, null, null, SocketConnection.MessageTarget.room); ch.SendText("You fly up.\r\n"); CommandType.Interpret(ch, "look auto"); foreach (CharData follower in ch.InRoom.People) { if (follower == ch) { continue; } if (follower.Master == ch && follower.CanFly() && follower.FlightLevel == (ch.FlightLevel - 1) && follower.CurrentPosition == Position.standing && follower.CanMove()) { if (follower.FlightLevel < CharData.FlyLevel.high) { SocketConnection.Act("$n&n flies up.", follower, null, null, SocketConnection.MessageTarget.room); follower.FlightLevel++; follower.SendText("You fly up.\r\n"); SocketConnection.Act("$n&n flies in from below.", follower, null, null, SocketConnection.MessageTarget.room); } } } } else { // If in a zone then fly out. if (!ch.InRoom.Area.HasFlag(Area.AREA_WORLDMAP)) { int lower = ch.InRoom.Area.LowRoomIndexNumber; int higher = ch.InRoom.Area.HighRoomIndexNumber; int iroom; for (iroom = lower; iroom <= higher; iroom++) { troom = Room.GetRoom(iroom); if (!troom) continue; // Now check all exits. int i; for (i = 0; i < Limits.MAX_DIRECTION; i++) { texit = troom.ExitData[i]; if (!texit || !(texit.TargetRoom)) continue; if (texit.TargetRoom.Area.HasFlag(Area.AREA_WORLDMAP)) { // Found a way out. Should check for exit zone being flyable. ch.SendText("You fly up.\r\n"); SocketConnection.Act("$n&n flies up higher.", ch, null, null, SocketConnection.MessageTarget.room); ch.RemoveFromRoom(); ch.AddToRoom(Room.GetRoom(texit.IndexNumber)); ch.FlightLevel = CharData.FlyLevel.low; CommandType.Interpret(ch, "look auto"); return; } } } ch.SendText("You can't fly out of this zone.\r\n"); // Glitch or no exits to worldmap. } ch.SendText("If you were any higher you'd be Woody Harrelson.\r\n"); } } else if (!MUDString.IsPrefixOf(str[0], "down")) { if (ch.FlightLevel > 0) { SocketConnection.Act("$n&n flies down lower.", ch, null, null, SocketConnection.MessageTarget.room); ch.FlightLevel--; SocketConnection.Act("$n&n flies in from above.", ch, null, null, SocketConnection.MessageTarget.room); if (ch.FlightLevel == 0) { ch.SendText("You fly down to the ground.\r\n"); } else { ch.SendText("You fly down.\r\n"); } CommandType.Interpret(ch, "look auto"); foreach (CharData follower in ch.InRoom.People) { if (follower == ch) { continue; } if (follower.Master == ch && follower.CanFly() && follower.CurrentPosition == Position.standing && follower.CanMove()) { SocketConnection.Act("$n&n flies down.", follower, null, null, SocketConnection.MessageTarget.room); follower.FlightLevel--; follower.SendText("You fly down.\r\n"); SocketConnection.Act("$n&n flies in from above.", follower, null, null, SocketConnection.MessageTarget.room); } } } else { ch.SendText("You're already on the ground.\r\n"); } } else if (!MUDString.IsPrefixOf(str[0], "land")) { if (ch.FlightLevel > 0) { SocketConnection.Act("$n&n flies down lower.", ch, null, null, SocketConnection.MessageTarget.room); for (; ch.FlightLevel > 0; ch.FlightLevel--) { SocketConnection.Act("$n&n flies down lower.", ch, null, null, SocketConnection.MessageTarget.room); } ch.FlightLevel = 0; SocketConnection.Act("$n&n flies in from above.", ch, null, null, SocketConnection.MessageTarget.room); ch.SendText("You fly down to the ground.\r\n"); CommandType.Interpret(ch, "look auto"); foreach (CharData follower in ch.InRoom.People) { if (follower == ch) { continue; } if (follower.Master == ch && follower.CanFly() && follower.FlightLevel == (ch.FlightLevel + 1) && follower.CurrentPosition == Position.standing && follower.CanMove()) { for (; follower.FlightLevel > 0; follower.FlightLevel--) { SocketConnection.Act("$n&n flies down lower.", follower, null, null, SocketConnection.MessageTarget.room); } follower.FlightLevel = 0; follower.SendText("You fly down to the ground.\r\n"); SocketConnection.Act("$n&n flies in from above.", follower, null, null, SocketConnection.MessageTarget.room); } } } else { ch.SendText("You're already on the ground.\r\n"); } } else { ch.SendText("Fly where?\r\n"); } return; }
/// <summary> /// Check for falling. Called from room update and movement. /// </summary> /// <param name="room"></param> /// <param name="target"></param> /// <param name="ch"></param> public static void CheckFall( Room room, Room target, CharData ch ) { int chance; if( !room || !target || !ch ) return; if( room.TerrainType != TerrainType.air && room.TerrainType != TerrainType.plane_of_air && room.TerrainType != TerrainType.underground_no_ground ) { if( MUDMath.NumberPercent() > room.FallChance ) return; } if( ch.CanFly() || ch.IsAffected( Affect.AFFECT_LEVITATE ) ) return; if( ch.InRoom.People != null ) { SocketConnection.Act( "You are falling down!", ch, null, null, SocketConnection.MessageTarget.character ); SocketConnection.Act( "$n&n falls away.", ch, null, null, SocketConnection.MessageTarget.room ); } ch.RemoveFromRoom(); ch.AddToRoom( target ); if( !ch.HasSkill( "safe_fall" ) ) chance = 0; else if( ch.IsNPC() ) chance = ( ( ch.Level * 3 ) / 2 ) + 15; else chance = ( (PC)ch ).SkillAptitude[ "safe fall" ]; // People with high agility have a small chance to safe fall, and those with // the skill already get a bonus. chance += ( ch.GetCurrAgi() / 20 ); // Minimum 1% chance of a bad fall. if( chance > 99 ) { chance = 99; } // Safe fall added by Xangis if( target.FallChance == 0 || !target.ExitData[ 5 ] || !target.ExitData[ 5 ].TargetRoom ) { if( MUDMath.NumberPercent() < chance ) { // Decent chance of skill increase - people don't fall very often. ch.PracticeSkill( "safe fall" ); ch.PracticeSkill( "safe fall" ); ch.PracticeSkill( "safe fall" ); ch.PracticeSkill( "safe fall" ); ch.SendText( "You fall to the ground!\r\n" ); if( MUDMath.NumberPercent() < chance ) { SocketConnection.Act( "$n&n falls from above and lands gracefully.", ch, null, null, SocketConnection.MessageTarget.room ); ch.SendText( "You land gracefully, avoiding any injury.\r\n" ); } else { SocketConnection.Act( "$n&n falls from above and lands on $s arse.", ch, null, null, SocketConnection.MessageTarget.room ); if( Race.MAX_SIZE > 0 && !ch.IsNPC() ) { Combat.InflictDamage(ch, ch, MUDMath.NumberRange(2, 4), String.Empty, ObjTemplate.WearLocation.none, AttackType.DamageType.none); ch.CurrentPosition = Position.sitting; ch.WaitState( 3 ); } } } else { ch.SendText( "You slam into the ground!\r\n" ); ch.CurrentPosition = Position.sitting; ch.WaitState( 8 ); SocketConnection.Act( "$n&n comes crashing in from above.", ch, null, null, SocketConnection.MessageTarget.room ); if( Race.MAX_SIZE > 0 && !ch.IsNPC() ) { Combat.InflictDamage( ch, ch, ( ( MUDMath.NumberPercent() * (int)ch.CurrentSize ) / Race.MAX_SIZE ), String.Empty, ObjTemplate.WearLocation.none, AttackType.DamageType.none); } } } else if( ch && ch.InRoom ) { if( ch.InRoom.People.Count > 0 ) { SocketConnection.Act( "$n&n falls by.", ch, null, null, SocketConnection.MessageTarget.room ); } } return; }
/// <summary> /// Attempt to trip a creature. Attacker must make a successful attack in order to succeed. /// </summary> /// <param name="ch"></param> /// <param name="victim"></param> void Trip(CharData ch, CharData victim) { if (victim.CanFly()) { return; } if (victim.Riding) { if (victim.Riding.CanFly()) { return; } SocketConnection.Act("$n trips your mount and you crash to the &n&+yground&n!", ch, null, victim, SocketConnection.MessageTarget.victim); SocketConnection.Act("You trip $N's mount and $N is thrown off!", ch, null, victim, SocketConnection.MessageTarget.character); SocketConnection.Act("$n trips $N's mount and $N falls off!", ch, null, victim, SocketConnection.MessageTarget.room_vict); victim.Riding.Rider = null; victim.Riding = null; ch.WaitState(2 * Event.TICK_COMBAT); victim.WaitState(2 * Event.TICK_COMBAT); victim.CurrentPosition = Position.resting; return; } if (victim.Wait == 0) { SocketConnection.Act("You trip $N and $N goes down!", ch, null, victim, SocketConnection.MessageTarget.character); SocketConnection.Act("$n trips you and you topple like a pile of bricks!", ch, null, victim, SocketConnection.MessageTarget.victim); SocketConnection.Act("$n trips $N and $N's face meets the &nearth&n!", ch, null, victim, SocketConnection.MessageTarget.room_vict); ch.WaitState(2 * Event.TICK_COMBAT); victim.WaitState(2 * Event.TICK_COMBAT); victim.CurrentPosition = Position.resting; } return; }
/// <summary> /// Show a character to another character. This is the abbreviated version used in "look room" /// </summary> /// <param name="victim"></param> /// <param name="ch"></param> public static void ShowCharacterToCharacterAbbreviated(CharData victim, CharData ch) { string text = String.Empty; if (!victim || !ch) { Log.Error("ShowCharacterToCharacter0(): null ch or victim.", 0); return; } if (victim.Rider && victim.Rider.InRoom == ch.InRoom) { return; } // If invis, show char invis symbol first. if (victim.IsAffected(Affect.AFFECT_INVISIBLE)) { text += "&+L*&n "; } // Show the player's description. if (((!ch.IsNPC() && victim.CurrentPosition == Position.standing) || (victim.IsNPC() && victim.MobileTemplate != null && victim.CurrentPosition == victim.MobileTemplate.DefaultPosition)) && (!String.IsNullOrEmpty(victim.FullDescription)) && !victim.Riding) { // Added long description does not have \r\n removed. We may want to. text += victim.Description + "&n"; } else { // Show the player's name. text += victim.ShowNameTo(ch, true) + "&n"; // Show the player's title. // Show the player's race, only if PC, and on the same side of the racewar or a god. if (!victim.IsNPC() && ((PC)victim).Title.Length > 0) { if (MUDString.StringsNotEqual(((PC)victim).Title, " &n") && (ch.IsNPC())) { text += ((PC)victim).Title; } if (victim.IsGuild() && (ch.IsNPC())) { text += " " + ((PC)victim).GuildMembership.WhoName; } if (!ch.IsRacewar(victim) || victim.IsImmortal() || ch.IsImmortal()) { text += " (" + Race.RaceList[victim.GetRace()].ColorName + ")"; } } // Show the player's condition. text += " is "; if (victim.CurrentPosition == Position.standing && victim.CanFly()) { text += "flying"; } else { text += Position.PositionString(victim.CurrentPosition); } text += " here"; if (victim.Fighting != null) { text += "&n fighting "; if (victim.Fighting == ch) { text += "&nyou!"; } else if (victim.InRoom == victim.Fighting.InRoom) { text += victim.Fighting.ShowNameTo(ch, false); } else { text += "&nsomeone who left??"; } } if (victim.Riding && victim.Riding.InRoom == victim.InRoom) { text += "&n, mounted on " + victim.Riding.ShowNameTo(ch, false); } text += "&n."; } if (victim.IsAffected(Affect.AFFECT_CASTING)) { text += "&n&+y (casting)&n"; } if (victim.IsAffected(Affect.AFFECT_MINOR_PARA)) { text += "&n (&+Yparalyzed)&n"; } if (!victim.IsNPC() && victim.HasActionBit(PC.PLAYER_WIZINVIS) && victim.GetTrust() <= ch.GetTrust()) { text += " &n&+g*&n"; } if (victim.IsAffected(Affect.AFFECT_HIDE) && (ch.IsAffected(Affect.AFFECT_DETECT_HIDDEN) || ch.HasInnate(Race.RACE_DETECT_HIDDEN))) { text += " &n(&+LHiding&n)"; } if (victim.IsAffected(Affect.AFFECT_CHARM) && ch.HasActionBit(PC.PLAYER_GODMODE)) { text += " &n(&n&+mCharmed&n)"; } if ((victim.IsAffected(Affect.AFFECT_PASS_DOOR) || victim.HasInnate(Race.RACE_PASSDOOR)) && ch.HasActionBit(PC.PLAYER_GODMODE)) { text += " &n(&+WTranslucent&n)"; } if ((victim.GetRace() == Race.RACE_UNDEAD || victim.GetRace() == Race.RACE_VAMPIRE) && (ch.IsAffected( Affect.AFFECT_DETECT_UNDEAD) || ch.HasActionBit(PC.PLAYER_GODMODE))) { text += " &n(&+WPale&n)"; } if (victim.IsAffected(Affect.AFFECT_FAERIE_FIRE)) { text += " &n(&n&+mFa&+Me&n&+mr&+Mie&+L Aura&n)"; } if (victim.IsEvil() && (ch.IsAffected(Affect.AFFECT_DETECT_EVIL) || ch.HasInnate(Race.RACE_DETECT_ALIGN) || ch.IsClass(CharClass.Names.paladin) || ch.IsClass(CharClass.Names.antipaladin))) { text += " &n(&+rBlood&+L Aura&n)"; } if (victim.IsGood() && (ch.IsAffected(Affect.AFFECT_DETECT_GOOD) || ch.HasInnate(Race.RACE_DETECT_ALIGN) || ch.IsClass(CharClass.Names.paladin) || ch.IsClass(CharClass.Names.antipaladin))) { text += " &n(&+CLight&+L Aura&n)"; } if (victim.IsAffected(Affect.AFFECT_SANCTUARY)) { text += " &n(&+WWhite&+L Aura&n)"; } if (!victim.IsNPC() && victim.HasActionBit(PC.PLAYER_AFK)) { text += " &n&+b(&+RAFK&n&+b)&n"; } if (!victim.IsNPC() && victim.HasActionBit(PC.PLAYER_BOTTING)) { text += " &n&+b(&+YBot&n&+b)&n"; } text += "\r\n"; ch.SendText(text); return; }