Esempio n. 1
0
        /// <summary>
        /// Player track command.
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="str"></param>
        public static void TrackCommand(CharData ch, string[] str)
        {
            if( ch == null ) return;

            CharData victim;

            if (ch.IsAffected(Affect.AFFECT_TRACK))
            {
                ch.SendText("You stop tracking.\r\n");
                Combat.StopHunting(ch);
                ch.RemoveAffect(Affect.AFFECT_TRACK);
                return;
            }

            if (!ch.HasSkill("track"))
            {
                ch.SendText("You couldn't track an &+Lelephant&n in your own bedroom.\r\n");
                return;
            }

            if (str.Length == 0)
            {
                ch.SendText("Whom are you trying to track?\r\n");
                return;
            }

            if (ch.Riding)
            {
                ch.SendText("You can't sniff a trail mounted.\r\n");
                return;
            }

            if (ch.FlightLevel != 0)
            {
                ch.SendText("You find tracks on the _ground_!\r\n");
                return;
            }

            if (ch.InRoom.IsWater())
            {
                ch.SendText("You can't track through water.\r\n");
                return;
            }

            if (ch.CurrentPosition != Position.standing)
            {
                if (ch.CurrentPosition == Position.fighting)
                    ch.SendText("You're too busy fighting .\r\n");
                else
                    ch.SendText("You must be standing to track!\r\n");
                return;
            }

            /* only imps can hunt to different areas */
            bool area = (ch.GetTrust() < Limits.LEVEL_OVERLORD);

            if (area)
            {
                victim = ch.GetCharInArea(str[0]);
            }
            else
            {
                victim = ch.GetCharWorld(str[0]);
            }

            if (!victim || (!victim.IsNPC() && (ch.IsRacewar(victim)) && !ch.IsImmortal()))
            {
                ch.SendText("You can't find a trail of anyone like that.\r\n");
                return;
            }

            if (ch.InRoom == victim.InRoom)
            {
                SocketConnection.Act("You're already in $N&n's room!", ch, null, victim, SocketConnection.MessageTarget.character);
                return;
            }

            /*
            * Deduct some movement.
            */
            if (ch.CurrentMoves > 2)
            {
                ch.CurrentMoves -= 3;
            }
            else
            {
                ch.SendText("You're too exhausted to hunt anyone!\r\n");
                return;
            }

            SocketConnection.Act("$n carefully sniffs the air.", ch, null, null, SocketConnection.MessageTarget.room);
            ch.WaitState(Skill.SkillList["track"].Delay);
            Exit.Direction direction = Track.FindPath(ch.InRoom.IndexNumber, victim.InRoom.IndexNumber, ch, -40000, area);

            if (direction == Exit.Direction.invalid)
            {
                SocketConnection.Act("You can't sense $N&n's trail from here.",
                     ch, null, victim, SocketConnection.MessageTarget.character);
                return;
            }

            /*
            * Give a random direction if the player misses the die roll.
            */
            if ((ch.IsNPC() && MUDMath.NumberPercent() > 75)  /* NPC @ 25% */
                    || (!ch.IsNPC() && MUDMath.NumberPercent() >   /* PC @ norm */
                         ((PC)ch).SkillAptitude["track"]))
            {
                do
                {
                    direction = Database.RandomDoor();
                }
                while (!(ch.InRoom.ExitData[(int)direction]) || !(ch.InRoom.ExitData[(int)direction].TargetRoom));
            }

            ch.PracticeSkill("track");

            /*
            * Display the results of the search.
            */
            ch.SetAffectBit(Affect.AFFECT_TRACK);
            string buf = String.Format("You sense $N&n's trail {0} from here...", direction.ToString());
            SocketConnection.Act(buf, ch, null, victim, SocketConnection.MessageTarget.character);
            if (ch.CurrentPosition == Position.standing)
            {
                ch.Move(direction);
            }
            Combat.StartHunting(ch, victim);

            return;
        }
Esempio n. 2
0
        /// <summary>
        /// Lets a player go visible if they want to.
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="str"></param>
        public static void Visible(CharData ch, string[] str)
        {
            if( ch == null ) return;

            if (!ch.IsAffected(Affect.AFFECT_INVISIBLE) && !ch.IsAffected(Affect.AFFECT_MINOR_INVIS) &&
                !ch.IsAffected(Affect.AFFECT_DUERGAR_HIDE))
            {
                ch.SendText("You already stick out like a &+Rsore thumb&n.\r\n" );
                return;
            }

            ch.RemoveAffect(Affect.AFFECT_INVISIBLE);
            ch.RemoveAffect(Affect.AFFECT_MINOR_INVIS);
            ch.RemoveAffect(Affect.AFFECT_DUERGAR_HIDE);

            ch.SendText("You make yourself visible.\r\n");
            SocketConnection.Act("$n&n slowly fades into existence.\r\n", ch, null, null, SocketConnection.MessageTarget.room );

            return;
        }
Esempio n. 3
0
        /// <summary>
        /// Move silently.
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="str"></param>
        public static void Sneak(CharData ch, string[] str)
        {
            if( ch == null ) return;
            /* Don't allow charmed mobs to do this, check player's skill */
            if ((!ch.HasSkill("sneak")))
            {
                ch.SendText("You're about as sneaky as a buffalo in tap shoes.\r\n");
                return;
            }

            if (ch.Riding)
            {
                ch.SendText("You can't do that while mounted.\r\n");
                return;
            }

            if (str.Length != 0 && !MUDString.StringsNotEqual(str[0], "off"))
            {
                if (!ch.IsAffected(Affect.AFFECT_SNEAK))
                {
                    ch.SendText("You're not sneaking.\r\n");
                }
                else
                {
                    ch.SendText("You stop sneaking around.\r\n");
                    ch.RemoveAffect(Affect.AFFECT_SNEAK);
                }
                return;
            }

            ch.SendText("You attempt to move silently.\r\n");
            ch.RemoveAffect( Affect.AFFECT_SNEAK );

            /* Check skill knowledge when moving only. */
            Affect af = new Affect(Affect.AffectType.skill, "sneak", -1, Affect.Apply.none, 0, Affect.AFFECT_SNEAK);
            ch.AddAffect(af);

            ch.PracticeSkill("sneak");
            ch.WaitState(10);
            return;
        }
Esempio n. 4
0
        /// <summary>
        /// Steal an object or some coins from a victim.
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="str"></param>
        public static void Steal(CharData ch, string[] str)
        {
            if( ch == null ) return;

            Object obj = null;
            CharData victim;
            bool sleeping = false;
            string arg1 = String.Empty;
            string arg2 = String.Empty;
            string arg = String.Empty;
            int percent;

            if (!ch.HasSkill("steal") && !ch.IsAffected(Affect.AFFECT_CHARM))
            {
                ch.SendText("Who are you trying to kid?  You couldn't steal shoes from a &n&+mbl&+Mo&n&+ma&+Mte&n&+md&n corpse.\r\n");
                return;
            }

            if (ch.Riding != null)
            {
                ch.SendText("You can't do that while mounted.\r\n");
                return;
            }

            if (String.IsNullOrEmpty(arg1) || String.IsNullOrEmpty(arg2))
            {
                ch.SendText("Steal what from whom?\r\n");
                return;
            }

            if ((victim = ch.GetCharRoom(arg2)) == null)
            {
                ch.SendText("They aren't here.\r\n");
                return;
            }

            if (victim == ch)
            {
                ch.SendText("That's pointless.\r\n");
                return;
            }

            if (Combat.IsSafe(ch, victim))
                return;

            if (!ch.IsImmortal())
            {
                ch.WaitState(Skill.SkillList["steal"].Delay);
            }

            // Justice stuff
            Crime.CheckThief(ch, victim);

            if (ch.IsNPC())
            {
                percent = ch.Level * 2;
            }
            else
            {
                percent = ((PC)ch).SkillAptitude["steal"];
            }

            percent += ch.GetCurrLuck() / 20; /* Luck */

            percent -= victim.Level; /* Character level vs victim's */

            if (ch.GetRace() == Race.RACE_HALFLING)
            {
                // Halflings get a racial bonus
                percent += 10;
            }

            if (victim.IsAffected(Affect.AFFECT_CURSE))
                percent += 15;

            if (ch.IsAffected(Affect.AFFECT_CURSE))
                percent -= 15;

            if (!victim.IsAwake())
                percent += 25; /* Sleeping characters are easier */

            if (ch.CheckSneak())
                percent += 10; /* Quiet characters steal better */

            if (!CharData.CanSee(ch, victim))
                percent += 10; /* Unseen characters steal better */

            if (!MUDString.IsPrefixOf(arg1, "coins"))
            {
                percent = (int)(percent * 1.2); /* Cash is fairly easy to steal */
            }
            else
            {
                int number = MUDString.NumberArgument(arg1, ref arg);
                int count = 0;
                foreach (Object iobj in victim.Carrying)
                {
                    if (CharData.CanSeeObj(ch, iobj) && MUDString.NameContainedIn(arg, iobj.Name))
                    {
                        if (++count == number)
                        {
                            obj = iobj;
                            break;
                        }
                    }
                }

                if (!obj)
                {
                    ch.SendText("You can't find it.\r\n");
                    return;
                }

                if (ch.Level < victim.Level)
                {
                    // stealing from higher level is possible, but harder
                    percent -= 5 * (victim.Level - ch.Level);
                }
                else
                {
                    // slight bonus for mobs lower level
                    percent += (ch.Level - victim.Level);
                }
                if (obj.WearLocation == ObjTemplate.WearLocation.none)
                    /* Items worn are harder */
                    percent = (int)(percent * .8);
                else
                    percent = (int)(percent * .4);
            }

            ch.PracticeSkill("steal");

            if (percent > 85)
                percent = 85;

            if (percent < 2)
                percent = 2;
            if (percent < MUDMath.NumberPercent())
            {
                /*
                * Failure.
                */
                //strip sneak
                ch.RemoveAffect(Affect.AFFECT_SNEAK);
                // chance of removing invis
                if (ch.IsAffected(Affect.AFFECT_INVISIBLE) && MUDMath.NumberPercent() > percent)
                {
                    ch.SendText("You really bungled that attempt.\r\n");
                    ch.RemoveAffect(Affect.AFFECT_INVISIBLE);
                }
                else
                {
                    ch.SendText("Oops.\r\n");
                }
                SocketConnection.Act("$n&n tried to steal from $N&n.", ch, null, victim, SocketConnection.MessageTarget.everyone_but_victim);
                if (victim.IsAwake())
                {
                    SocketConnection.Act("$n&n tried to steal from you!", ch, null, victim, SocketConnection.MessageTarget.victim);
                }
                else
                {
                    sleeping = true;
                }
                // Thief flag for justice.
                // Added so blind mobs dont hit who ever failed steal from em.
                if (victim.IsNPC())
                {
                    if (!sleeping && !victim.IsBlind())
                    {
                        CommandType.Interpret(victim, "kill " + ch.Name);
                    }
                }
                else
                {
                    if (!victim.IsBlind() && !sleeping && victim.IsAffected(Affect.AFFECT_BERZERK))
                    {
                        victim.SendText("In your &+Rblood rage&n, you lash out in anger!\r\n");
                        CommandType.Interpret(victim, "kill " + ch.Name);
                    }
                }
                /*
                if ( !Macros.IS_SET( ch.actflags, PC.PLAYER_THIEF ) )
                {
                Macros.SET_BIT( ref ch.actflags, PC.PLAYER_THIEF );
                buf = String.Format(  "{0} became a THIEF by stealing from {1}",
                ch._name, victim._name );
                Immtalk.Immtalk( ch, Immtalk.IMMTALK_CRIME, ch.GetTrust(), buf );
                CharData.SavePlayer( ch );
                }
                */
                //    }
                if (sleeping)
                {
                    if (MUDMath.NumberPercent() < victim.GetCurrLuck())
                    {
                        CommandType.Interpret(victim, "wake");
                    }
                }
                return;
            } //end failure

            if (!MUDString.IsPrefixOf(arg1, "coins"))
            {
                int amount = victim.GetGold() * MUDMath.NumberRange(1, 20) / 100;
                int amount2 = victim.GetSilver() * MUDMath.NumberRange(1, 20) / 100;
                int amount3 = victim.GetCopper() * MUDMath.NumberRange(1, 20) / 100;
                int amount4 = victim.GetPlatinum() * MUDMath.NumberRange(1, 20) / 100;

                if ((amount + amount2 + amount3 + amount4) <= 0)
                {
                    ch.SendText("You couldn't get any &n&+wcoins&n.\r\n");
                    return;
                }

                ch.ReceiveGold(amount);
                ch.ReceiveSilver(amount2);
                ch.ReceiveCopper(amount3);
                ch.ReceivePlatinum(amount4);

                victim.SpendGold(amount);
                victim.SpendSilver(amount2);
                victim.SpendCopper(amount3);
                victim.SpendPlatinum(amount4);

                string text = String.Format("Success!  You got {0} &+Wplatinum&n, {1} &+Ygold&n, {2} silver, and {3} &+ycopper&n.\r\n",
                                            amount2, amount3, amount, amount4);
                ch.SendText(text);
                return;
            }

            if (!ch.CanDropObject(obj) || obj.HasFlag(ObjTemplate.ITEM_INVENTORY))
            {
                ch.SendText("You can't pry it away.\r\n");
                return;
            }

            if (ch.CarryNumber + 1 > Limits.MAX_CARRY)
            {
                ch.SendText("You have your hands full.\r\n");
                return;
            }

            if (ch.CarryWeight + obj.GetWeight() > ch.MaxCarryWeight())
            {
                ch.SendText("You cannot carry that much weight.\r\n");
                return;
            }

            if (obj.WearLocation != ObjTemplate.WearLocation.none)
            {
                ch.SendText("Very daring, and you got it!\r\n");
                victim.UnequipObject(obj);
            }

            obj.RemoveFromChar();
            obj.ObjToChar(ch);
            ch.SendText("Nice work.\r\n");
            if (obj.Trap != null && obj.Trap.CheckTrigger( Trap.TriggerType.steal))
            {
                ch.SetOffTrap(obj);
                if (ch.CurrentPosition == Position.dead)
                {
                    return;
                }
            }
            return;
        }
Esempio n. 5
0
        /// <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;
        }
Esempio n. 6
0
        /// <summary>
        /// The main entry point for executing commands.
        /// Can be recursively called from 'at', 'order', 'force'.
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="argument"></param>
        public static void Interpret(CharData ch, string argument)
        {
            // Get rid of leading and trailing spaces.
            argument = argument.Trim();

            // Strip leading spaces.
            argument.Trim();
            if (argument.Length == 0)
            {
                return;
            }

            // Remove AFK
            if (!ch.IsNPC())
            {
                ch.RemoveActionBit(PC.PLAYER_AFK);
            }

            // Implement freeze command.
            if (!ch.IsNPC() && ch.HasActionBit(PC.PLAYER_FREEZE))
            {
                ch.SendText("You're totally frozen!\r\n");
                return;
            }

            // Grab the command word.  Special parsing so ' can be a command,
            // also no spaces needed after punctuation.
            string command;
            Object obj;
            Room room;
            int cmd;
            string logline = argument;
            int argptr = 0;
            if (!Char.IsLetter(argument[0]) && !Char.IsDigit(argument[0]))
            {
                command = argument.Substring(0, 1);
                argptr++;
                while (argument.Length > argptr && Char.IsWhiteSpace(argument[argptr]))
                {
                    argument = argument.Remove(0, 1);
                }
            }
            else
            {
                command = MUDString.OneArgument(argument, ref argument);
                argument.Trim(); // Clean up the remainder of the command.
            }

            // Nothing to do if command is empty.  Just send them a newline and bail.
            if (string.IsNullOrEmpty(command) && string.IsNullOrEmpty(argument))
            {
                ch.SendText("\r\n");
                return;
            }

            // Look for an item with a teleport trigger in the room.
            // and check to see if the command is a teleport trigger
            if (ch.InRoom && (obj = ch.GetObjHere(argument)))
            {
                if (obj.ItemType == ObjTemplate.ObjectType.teleport)
                {
                    if (CheckCommandTrigger(command, obj.Values[1]) && obj.Values[2] != 0)
                    {
                        if (obj.Values[2] != -1)
                        {
                            obj.Values[2]--;
                        }
                        room = Room.GetRoom(obj.Values[0]);
                        if (room)
                        {
                            SocketConnection.Act("$n&n vanishes suddenly.", ch, null, null, SocketConnection.MessageTarget.room);
                            string text = String.Format("You {0} $p&n.\r\n", command);
                            SocketConnection.Act(text, ch, obj, null, SocketConnection.MessageTarget.character);
                            Log.Trace(String.Format("{0} activated keyword and was teleported by object.", ch.Name));
                            ch.RemoveFromRoom();
                            ch.AddToRoom(room);
                            Interpret(ch, "look auto");
                            SocketConnection.Act("$n&n arrives suddenly.", ch, null, null, SocketConnection.MessageTarget.room);
                        }
                        else
                        {
                            ch.SendText("BUG: The target room for this teleporter does not exist.\r\n");
                            Log.Error("Target room for object {0} does not exist.", obj.ObjIndexData.IndexNumber);
                        }
                        return;
                    }
                }
                else if (obj.ItemType == ObjTemplate.ObjectType.switch_trigger)
                {
                    Exit exit;
                    string cbuf = String.Format("Checking {0} against command no. {1} for {2}.", command, obj.Values[0], obj.Name);
                    ImmortalChat.SendImmortalChat(null, ImmortalChat.IMMTALK_SPAM, 0, cbuf);
                    if (CheckCommandTrigger(command, obj.Values[0]))
                    {
                        ch.SendText("Click.\r\n");
                        room = Room.GetRoom(obj.Values[1]);
                        if (!room)
                        {
                            Log.Error("Target room for switch object {0} does not exist.", obj.ObjIndexData.IndexNumber);
                            return;
                        }
                        exit = room.ExitData[obj.Values[2]];
                        if (exit == null)
                        {
                            Log.Error("Target exit for switch object {0} does not exist.", obj.ObjIndexData.IndexNumber);
                            return;
                        }
                        if (exit.HasFlag(Exit.ExitFlag.blocked))
                        {
                            exit.RemoveFlag(Exit.ExitFlag.blocked);
                        }
                        return;
                    }
                }
            }

            // Look for command in command table.
            bool found = false;
            int trust = ch.GetTrust();
            for (cmd = 0; cmd < CommandTable.Length; cmd++)
            {
                if (CommandTable[cmd].Name.StartsWith(command, StringComparison.CurrentCultureIgnoreCase)
                        && (CommandTable[cmd].MinLevel <= trust))
                {
                    found = true;
                    break;
                }
            }

            // Command was found, respond accordingly.
            if (found)
            {
                // Logging and snooping.
                if (CommandTable[cmd].LoggingType == LogType.never)
                {
                    logline = "---- Nothing to see here ----";
                }

                if ((!ch.IsNPC() && ch.HasActionBit(PC.PLAYER_LOG)) || fLogAll
                        || CommandTable[cmd].LoggingType == LogType.always)
                {
                    string logBuf = String.Format("Log {0}: {1}", ch.Name, logline);
                    Log.Trace(logBuf);
                    ImmortalChat.SendImmortalChat(ch, ImmortalChat.IMMTALK_SECURE, ch.GetTrust(), logBuf);
                }

                if (ch.Socket && ch.Socket.SnoopBy)
                {
                    ch.Socket.SnoopBy.WriteToBuffer("% ");
                    ch.Socket.SnoopBy.WriteToBuffer(logline);
                    ch.Socket.SnoopBy.WriteToBuffer("\r\n");
                }

                // Break meditate
                if (CommandTable[cmd].BreakMeditate)
                {
                    if (!ch.IsNPC() && ch.HasActionBit(PC.PLAYER_MEDITATING))
                    {
                        ch.RemoveActionBit(PC.PLAYER_MEDITATING);
                        ch.SendText("You stop meditating.\r\n");
                    }
                }

                // Break sneak, hide, and invis
                // Anything that will break hide OR invis will break concealment
                // This is DUMB!  Breaks invis w/backstab on a target that's not
                //   there: i.e. "backstab trolll"/"backstab humann" . vis and no
                //   attack! - (Should be handled with make_vis function).
                if (CommandTable[cmd].BreakInvisibility)
                {
                    if (ch.IsAffected(Affect.AFFECT_INVISIBLE))
                    {
                        ch.RemoveAffect(Affect.AFFECT_INVISIBLE);
                        ch.RemoveAffect(Affect.AFFECT_HIDE);
                        ch.RemoveAffect(Affect.AFFECT_MINOR_INVIS);

                        SocketConnection.Act("$n&n snaps into visibility.", ch, null, null, SocketConnection.MessageTarget.room);
                        ch.SendText("You snap into visibility.\r\n");
                    }
                    else if (ch.IsAffected(Affect.AFFECT_MINOR_INVIS))
                    {
                        ch.RemoveAffect(Affect.AFFECT_INVISIBLE);
                        ch.RemoveAffect(Affect.AFFECT_HIDE);
                        ch.RemoveAffect(Affect.AFFECT_MINOR_INVIS);

                        ch.SendText("You appear.\r\n");
                    }
                }

                if (CommandTable[cmd].BreakHide)
                {
                    if (ch.IsAffected(Affect.AFFECT_MINOR_INVIS))
                    {
                        ch.SendText("You appear.\r\n");
                    }
                    ch.AffectStrip( Affect.AffectType.skill, "shadow form");
                    ch.RemoveAffect( Affect.AFFECT_HIDE );
                    ch.RemoveAffect(Affect.AFFECT_MINOR_INVIS);
                }
            }
            // Command was not found, respond accordingly.
            else
            {
                // Look for command in socials table.
                if (!Database.SocialList.CheckSocial(ch, command, argument))
                {
                    if (!ch.IsNPC() && !MUDString.IsPrefixOf(command, "petition"))
                    {
                        string logBuf = String.Format("Log {0}: {1}", ch.Name, logline);
                        Log.Trace(logBuf);
                        ImmortalChat.SendImmortalChat(ch, ImmortalChat.IMMTALK_SECURE, ch.GetTrust(), logBuf);
                        Command.Petition(ch, argument.Split(' '));
                        return;
                    }
                    Log.Trace("Failed to match command.");
                    ch.SendText("Huh?\r\n");
                }
                return;
            }

            // Character not in position for command?
            if (ch.CurrentPosition < CommandTable[cmd].MinPosition)
            {
                switch (ch.CurrentPosition)
                {
                    case Position.dead:
                        ch.SendText("Lie still; you are &+rDEAD&n!\r\n");
                        break;

                    case Position.mortally_wounded:
                    case Position.incapacitated:
                        ch.SendText("You are hurt far too bad for that.\r\n");
                        break;

                    case Position.stunned:
                        ch.SendText("You are too stunned to do that.\r\n");
                        break;

                    case Position.sleeping:
                        ch.SendText("In your dreams, or what?\r\n");
                        break;

                    case Position.reclining:
                        ch.SendText("You can't do that while lying around.\r\n");
                        break;

                    case Position.sitting:
                        ch.SendText("You can't do this sitting!\r\n");
                        break;

                    case Position.kneeling:
                        ch.SendText("Get off your knees!\r\n");
                        break;

                    case Position.resting:
                        ch.SendText("Nah... You feel too relaxed...\r\n");
                        break;

                    case Position.fighting:
                        ch.SendText("No way! You are still fighting!\r\n");
                        break;

                }
                if (!ch.IsImmortal())
                {
                    return;
                }
                if (ch.CurrentPosition == Position.dead)
                    ch.CurrentPosition = Position.sleeping;
                ch.SendText("You're not in the right position, but..\r\n");
            }
            if (ch.IsAffected(Affect.AFFECT_MINOR_PARA) &&
                CommandTable[cmd].Function != Command.LookCommand &&
                CommandTable[cmd].Function != Command.Score &&
                CommandTable[cmd].Function != Command.Attributes)
            {
                if (!ch.IsImmortal())
                {
                    ch.SendText("&+YYour mind moves, but your body doesn't.&n\r\n");
                    return;
                }
                ch.SendText("&+YYour immortality allows you to move!&n\r\n");
            }

            string[] str = argument.Split(new[] {' '}, StringSplitOptions.RemoveEmptyEntries);

            // Dispatch the command.  Catch any exceptions, since most exceptions will probably happen
            // based on user commands.
            try
            {
                (CommandTable[cmd].Function)(ch, str);
            }
            catch (Exception ex)
            {
                Log.Error("Exception in CommandType.Interpret: " + ex);
            }
            return;
        }
Esempio n. 7
0
        /// <summary>
        /// Deliver a killing blow to the victim.
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="victim"></param>
        public static void KillingBlow( CharData ch, CharData victim )
        {
            Event eventdata;
            Room room;
            bool noCorpse = false;

            StopFighting( victim, true );

            if( victim.GroupLeader || victim.NextInGroup )
            {
                victim.RemoveFromGroup( victim );
            }
            if( ch != victim )
            {
                if( victim.IsNPC() && victim.MobileTemplate.DeathFun.Count > 0 )
                {
                    victim.MobileTemplate.DeathFun[0].SpecFunction( victim, MobFun.PROC_NORMAL );
                }
                //        prog_death_trigger( victim );
            }
            if( victim.IsNPC() && victim.DeathFunction != null )
            {
                noCorpse = victim.DeathFunction.SpecFunction( victim, MobFun.PROC_DEATH );
            }
            if( !noCorpse )
            {
                MakeCorpse( victim );
            }

            /* Strip all event-spells from victim! */
            for( int i = (Database.EventList.Count - 1); i >= 0; i-- )
            {
                eventdata = Database.EventList[i];

                if( eventdata.Type == Event.EventType.immolate || eventdata.Type == Event.EventType.acid_arrow )
                {
                    if( (CharData)eventdata.Target2 == victim )
                    {
                        Database.EventList.Remove( eventdata );
                    }
                }
            }

            if( victim.Rider )
            {
                SocketConnection.Act( "$n&n dies suddenly, and you topple to the &n&+yground&n.", victim, null, victim.Rider, SocketConnection.MessageTarget.victim );
                victim.Rider.Riding = null;
                victim.Rider.CurrentPosition = Position.resting;
                victim.Rider = null;
            }

            if( victim.Riding )
            {
                SocketConnection.Act( "$n&n topples from you, &+Ldead&n.", victim, null, victim.Riding, SocketConnection.MessageTarget.victim );
                victim.Riding.Rider = null;
                victim.Riding = null;
            }

            if (!victim.IsNPC() && victim.IsAffected(Affect.AFFECT_VAMP_BITE))
            {
                victim.SetPermRace( Race.RACE_VAMPIRE );
            }

            for (int i = (victim.Affected.Count - 1); i >= 0; i--)
            {
                /* Keep the ghoul affect */
                if (!victim.IsNPC() && victim.IsAffected(Affect.AFFECT_WRAITHFORM))
                {
                    continue;
                }

                victim.RemoveAffect(victim.Affected[i]);
            }

            if( victim.IsNPC() )
            {
                victim.MobileTemplate.NumberKilled++;
                // This may invalidate the char list.
                CharData.ExtractChar( victim, true );
                return;
            }
            CharData.ExtractChar( victim, false );
            //save corpses, don't wait til next save_corpse event
            Database.CorpseList.Save();
            // Character has died in combat, extract them to repop point and put
            // them at the menu.
            /*
                 * Pardon crimes once justice system is complete
                 */
            // This is where we send them to the menu.
            victim.DieFollower( victim.Name );

            if( victim.InRoom )
            {
                room = victim.InRoom;
            }
            else
            {
                List<RepopulationPoint> repoplist = victim.GetAvailableRepops();
                if( repoplist.Count < 1 )
                {
                    victim.SendText( "There is no RepopPoint entry for your race and class.  Sending you to limbo.\r\n" );
                    room = Room.GetRoom( StaticRooms.GetRoomNumber("ROOM_NUMBER_START") );
                }
                else
                {
                    // Drop them at the first repop point in the list.  We may want to be fancier about this later, such as dropping them
                    // at the repop for class none if their particular class isn't found.
                    room = Room.GetRoom(repoplist[0].Room);
                    if( !room )
                    {
                        victim.SendText( "The repop point for your race/class does not exist.  Please bug this.  Sending you to limbo.\r\n" );
                        room = Room.GetRoom( StaticRooms.GetRoomNumber("ROOM_NUMBER_START") );
                    }
                    if( !victim.IsNPC() && Room.GetRoom( ( (PC)victim ).CurrentHome ) )
                    {
                        room = Room.GetRoom( ( (PC)victim ).CurrentHome );
                    }
                }
            }
            victim.RemoveFromRoom();
            if( room )
            {
                victim.InRoom = room;
            }

            // Put them in the correct body
            if( victim.Socket && victim.Socket.Original )
            {
                CommandType.Interpret(victim, "return");
            }

            // Reset reply pointers - handled by CharData.ExtractChar.

            CharData.SavePlayer( victim );

            // Remove from char list: handled by CharData.ExtractChar.

            victim.Socket.ShowScreen(ModernMUD.Screen.MainMenuScreen);

            if( victim.Socket != null )
            {
                victim.Socket.ConnectionStatus = SocketConnection.ConnectionState.menu;
            }

            // Just died flag used for safe time after re-login.
            victim.SetActionBit( PC.PLAYER_JUST_DIED );

            return;
        }
Esempio n. 8
0
        /// <summary>
        /// Flee: Attempt to run away from combat.
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="str"></param>
        public static void Flee(CharData ch, string[] str)
        {
            if( ch == null ) return;

            int attempt;
            int chances;

            if (ch.CurrentPosition < Position.reclining || ch.Wait > 0)
            {
                return;
            }

            // Remove memorization and meditation bits - Xangis
            if (!ch.IsNPC() && ch.HasActionBit(PC.PLAYER_MEDITATING))
            {
                SocketConnection.Act("$N&n is disrupted from meditation.", ch, null, null, SocketConnection.MessageTarget.room);
                SocketConnection.Act("Your meditation is disrupted.", ch, null, null, SocketConnection.MessageTarget.character);
                ch.RemoveActionBit(PC.PLAYER_MEDITATING);
            }
            if (!ch.IsNPC() && ch.HasActionBit(PC.PLAYER_MEMORIZING))
            {
                SocketConnection.Act("$N&n abandons $S studies.", ch, null, null, SocketConnection.MessageTarget.room);
                SocketConnection.Act("You abandon your studies.", ch, null, null, SocketConnection.MessageTarget.character);
                ch.RemoveActionBit(PC.PLAYER_MEMORIZING);
            }

            if (ch.CurrentPosition < Position.fighting)
            {
                ch.SendText("You scramble madly to your feet!\r\n");
                SocketConnection.Act("$n&n scrambles madly to $s feet!",
                     ch, null, null, SocketConnection.MessageTarget.room);
                ch.CurrentPosition = Position.standing;
                return;
            }

            if (!ch.InRoom)
            {
                ch.SendText("You give up when you realize there's nowhere to flee to.\r\n");
            }

            // Panicked people can flee when not fighting.
            CharData victim = ch.Fighting;
            if (!victim)
            {
                if (ch.CurrentPosition == Position.fighting)
                {
                    ch.CurrentPosition = Position.standing;
                }
            }

            if (ch.IsAffected(Affect.AFFECT_BERZERK))
            {
                ch.SendText("You can't flee, you're in a &+RBl&n&+ro&+Ro&n&+rd&+L Rage&n!!\r\n");
                return;
            }

            if (ch.IsAffected( Affect.AFFECT_BOUND))
            {
                ch.SendText("You are bound!  You can't move!\r\n");
                SocketConnection.Act("$n&n tries to flee, but is tied up!",
                     ch, null, null, SocketConnection.MessageTarget.room);
                return;
            }

            if (ch.IsAffected( Affect.AFFECT_HOLD) ||
                    ch.IsAffected( Affect.AFFECT_MINOR_PARA))
            {
                ch.SendText("You can't move!\r\n");
                SocketConnection.Act("$n&n tries to flee, but $e can't move!",
                     ch, null, null, SocketConnection.MessageTarget.room);
                return;
            }

            // You should almost always be able to flee when not fighting.
            if (ch.CurrentPosition == Position.standing)
            {
                chances = 30;
            }
            else
            {
                chances = 6;
            }

            Room wasIn = ch.InRoom;
            for (attempt = 0; attempt < chances; attempt++)
            {
                Exit exit;

                Exit.Direction door = Database.RandomDoor();
                if ((exit = wasIn.GetExit(door)) == null || !exit.TargetRoom
                        || exit.TargetRoom == wasIn || exit.HasFlag(Exit.ExitFlag.closed)
                        || (ch.IsNPC() && (Room.GetRoom(exit.IndexNumber).HasFlag(RoomTemplate.ROOM_NO_MOB)
                        || (ch.HasActionBit(MobTemplate.ACT_STAY_AREA) && exit.TargetRoom.Area != ch.InRoom.Area))))
                {
                    continue;
                }

                if (ch.Riding && ch.Riding.Fighting)
                {
                    Combat.StopFighting(ch.Riding, true);
                }

                // Just to keep the damned messages from being wacky...
                ch.SetAffectBit(Affect.AFFECT_IS_FLEEING);
                ch.Move(door);
                ch.RemoveAffect(Affect.AFFECT_IS_FLEEING);
                if (ch.InRoom == wasIn)
                {
                    break;
                }
                Room nowIn = ch.InRoom;
                ch.InRoom = wasIn;

                SocketConnection.Act("$n&n panics and attempts to flee...", ch, null, null, SocketConnection.MessageTarget.room, true);
                string text;
                if (ch.CheckSneak())
                {
                    SocketConnection.Act("$n&n has fled!", ch, null, null, SocketConnection.MessageTarget.room);
                }
                else
                {
                    text = String.Format("$n&n flees {0}ward.", door.ToString());
                    SocketConnection.Act(text, ch, null, null, SocketConnection.MessageTarget.room, true);
                }
                ch.InRoom = nowIn;

                text = String.Format("You flee {0}ward!\r\n", door.ToString());
                ch.SendText(text);

                Combat.StopFighting(ch, true);
                return;
            }

            SocketConnection.Act("$n&n tries to flee but can't make it out of here!", ch, null, null, SocketConnection.MessageTarget.room, true);
            ch.SendText("&+WYour escape is blocked!\r\n");
            return;
        }
Esempio n. 9
0
        /// <summary>
        /// Inflict damage from a single hit.  This could use some cleanup since it's way too unwieldy at more than 600 lines.
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="victim"></param>
        /// <param name="dam"></param>
        /// <param name="skill"></param>
        /// <param name="weapon"></param>
        /// <param name="damType"></param>
        /// <returns></returns>
        public static bool InflictDamage(CharData ch, CharData victim, int dam, string skill, ObjTemplate.WearLocation weapon, AttackType.DamageType damType)
        {
            if (ch == null || victim == null)
            {
                return false;
            }

            Object obj;
            bool critical = false;

            if( victim.CurrentPosition == Position.dead || victim.Hitpoints < -10 )
            {
                return true;
            }

            /*
            * Stop up any residual loopholes.
            */
            if( ( dam > 1276 ) && ch.Level < Limits.LEVEL_AVATAR )
            {
                string text;

                if (ch.IsNPC() && ch.Socket)
                {
                    text = String.Format("Damage: {0} from {1} by {2}: > 1276 points with {3} damage type!",
                              dam, ch.Name, ch.Socket.Original.Name, skill);
                }
                else
                {
                    text = String.Format("Damage: {0} from {1}: > 1276 points with {2} damage type!",
                              dam, ch.IsNPC() ? ch.ShortDescription : ch.Name, skill);
                }
                Log.Error( text, 0 );
                dam = 1276;
            }

            // Remove memorization and meditation bits - Xangis
            victim.BreakMeditate();
            victim.BreakMemorization();
            if (victim.IsAffected( Affect.AFFECT_MINOR_PARA))
            {
                SocketConnection.Act( "$n&n disrupts the magic preventing $N&n from moving.", ch, null, victim, SocketConnection.MessageTarget.room_vict );
                SocketConnection.Act( "You disrupt the magic preventing $N&n from moving.", ch, null, victim, SocketConnection.MessageTarget.character );
                SocketConnection.Act( "&+YYou can move again.&n", ch, null, victim, SocketConnection.MessageTarget.victim );
                victim.RemoveAffect( Affect.AFFECT_MINOR_PARA );
            }

            bool immune = false;
            if( victim != ch )
            {
                /*
                * Certain attacks are forbidden.
                * Most other attacks are returned.
                */
                victim = CheckGuarding( ch, victim );
                if( IsSafe( ch, victim ) )
                    return false;
                // is_safe could wipe out victim, as it calls procs if a boss
                // check and see that victim is still valid
                if( victim == null )
                    return true;
                Crime.CheckAttemptedMurder( ch, victim );
                if( victim.CurrentPosition > Position.stunned )
                {
                    if( !victim.Fighting )
                        SetFighting( victim, ch );
                    // Can't have prone people automatically stand
                    if( victim.CurrentPosition == Position.standing )
                        victim.CurrentPosition = Position.fighting;

                    if( !ch.Fighting )
                        SetFighting( ch, victim );

                    /*
                    * If NPC victim is following, ch might attack victim's master.
                    * No charm check here because charm would be dispelled from
                    * tanking mobile when combat ensues thus ensuring PC charmer is
                    * not harmed.
                    * Check for IsSameGroup wont work as following mobile is not
                    * always grouped with PC charmer
                    *
                    * Added a check for whether ch has switch skill.  If not,
                    * much lower chancing of retargetting
                    */
                    if( ch.IsNPC()
                            && victim.IsNPC()
                            && victim.Master
                            && victim.Master.InRoom == ch.InRoom
                            && MUDMath.NumberBits( 2 ) == 0 )
                    {
                        StartGrudge( ch, victim.Master, false );
                    }
                }

                /*
                * More charm stuff.
                */
                if( victim.Master == ch )
                {
                    StopFighting( victim, true );
                }

                ch.BreakInvisibility();

                /*
                * Hunting stuff...
                */
                if( dam != 0 && victim.IsNPC() )
                {
                    /* StartGrudge is combined StartHating and StartHunting */
                    StartGrudge( victim, ch, false );
                }

                /*
                * Damage modifiers.
                */

                // Critical hits for double damage
                // Average of 5% for those that have average luck
                // Gnomes could concievably have 10%
                if( MUDMath.NumberPercent() < ( 2 + ( ch.GetCurrLuck() / 18 ) ) && dam > 0 )
                {
                    ch.SendText( "&+WYou score a CRITICAL HIT!&n\r\n" );
                    dam *= 2;
                    critical = true;
                }

                if( victim.IsAffected( Affect.AFFECT_SANCTUARY ) )
                    dam /= 2;

                if( victim.IsAffected( Affect.AFFECT_PROTECT_EVIL ) && ch.IsEvil() )
                    dam -= dam / 8;
                else if( victim.IsAffected( Affect.AFFECT_PROTECT_GOOD ) && ch.IsGood() )
                    dam -= dam / 8;

                // Check stoneskin.  People not affected by a stoneskin affect
                // cannot lose their stoneskin for any reason.  This should mean
                // that mobs will keep their stoneskin and players should always
                // have a chance to lose it, since no player should ever be
                // setbit stoneskin.
                //
                // The bool value of found is used so that we can have them
                // take full damage when their stoneskin shatters, but get the
                // damage reduction if they are either a mob or their stoneskin
                // wears off that round.
                //
                /* Yeah, yeah.. so maybe backstabs shouldn't be aff'd. */
                // Actually they should be affected, but they should have a much
                // higher chance of getting through (say 30-70%).
                //
                // Critical hits will now go through stoneskin
                // automatically
                if (!critical && victim.IsAffected( Affect.AFFECT_STONESKIN) &&
                        ( skill != "backstab" || MUDMath.NumberPercent() < ( 25 + ch.Level ) ) )
                {
                    bool found = false;
                    for (int i = (victim.Affected.Count - 1); i >= 0; i--)
                    {
                        if( victim.Affected[i].HasBitvector( Affect.AFFECT_STONESKIN ) )
                        {
                            // Small chance of shattering the stoneskin on a good hit.
                            // Reduced chance by about 20%
                            if( dam >= 25 && MUDMath.NumberPercent() <= ( dam / 12 ) )
                            {
                                victim.SendText( "&+LYour stoneskin is shattered by the massive blow!&n\r\n" );
                                SocketConnection.Act( "$n&n's massive blow shatters $N&n's stoneskin!", ch, null, victim, SocketConnection.MessageTarget.everyone_but_victim );
                                SocketConnection.Act( "Your massive blow shatters $N&n's stoneskin!", ch, null, victim, SocketConnection.MessageTarget.character );
                                victim.RemoveAffect(victim.Affected[i]);
                                found = true;
                            }
                            else if( dam > 0 ) // Added check for actual damage
                            {
                                for( int j = 0; j < victim.Affected[i].Modifiers.Count; j++ )
                                {
                                    victim.Affected[i].Modifiers[j].Amount--;
                                    if (victim.Affected[i].Modifiers[j].Amount < 1)
                                    {
                                        victim.RemoveAffect(victim.Affected[i]);
                                        victim.SendText("&+LYou feel your skin soften and return to normal.&n\r\n");
                                    }
                                    dam /= 15;
                                    found = true;
                                }
                            }
                        }
                    }
                    // This means they're Affect.AFFECT_STONESKIN as an innate/permenant.
                    // We will still allow it to shatter, but it will refresh itself
                    // upon a mob update.  Because of this, we make it easier to shatter.
                    // No damage reduction when it shatters.
                    if( !found )
                    {
                        if( dam >= 8 && MUDMath.NumberPercent() <= ( dam / 8 ) )
                        {
                            victim.SendText( "&+LYour stoneskin is shattered by the massive blow!&n\r\n" );
                            SocketConnection.Act( "$n&n's massive blow shatters $N&n's stoneskin!", ch, null, victim, SocketConnection.MessageTarget.everyone_but_victim );
                            SocketConnection.Act( "Your massive blow shatters $N&n's stoneskin!", ch, null, victim, SocketConnection.MessageTarget.character );
                            victim.RemoveAffect( Affect.AFFECT_STONESKIN );
                        }
                        else
                        {
                            dam = dam / 15 != 0 ? dam / 15 : 1;
                        }
                    }

                }

                if( dam < 0 )
                    dam = 0;

                /*
                * Check for disarm, trip, parry, dodge and shield block.
                */
                if (skill != "barehanded fighting" || skill == "kick")
                {
                    // Trip and disarm removed because those should be handled
                    // by each individual mob's special function.
                    if( ch.IsNPC()
                            && ch.HasInnate( Race.RACE_WEAPON_WIELD )
                            && MUDMath.NumberPercent() < Math.Min( 25, Math.Max( 10, ch.Level ) )
                            && !victim.IsNPC() )
                        UseMagicalItem( ch );
                }
            }

            switch( victim.CheckRIS( damType ) )
            {
                case Race.ResistanceType.resistant:
                    dam -= dam / 3;
                    break;
                case Race.ResistanceType.immune:
                    immune = true;
                    dam = 0;
                    break;
                case Race.ResistanceType.susceptible:
                    dam += dam / 2;
                    break;
                case Race.ResistanceType.vulnerable:
                    dam *= 2;
                    break;
                default:
                    break;
            }

            if( ( damType == AttackType.DamageType.wind || damType == AttackType.DamageType.gas || damType == AttackType.DamageType.asphyxiation )
                    && victim.IsAffected(Affect.AFFECT_DENY_AIR))
            {
                if( MUDMath.NumberPercent() < 50 )
                {
                    ch.SendText( "&+CYou deny the damage.&n\r\n" );
                    immune = true;
                    dam = 0;
                }
                else
                    dam -= dam / 5;
            }
            if (damType == AttackType.DamageType.fire && victim.IsAffected( Affect.AFFECT_DENY_FIRE))
            {
                if( MUDMath.NumberPercent() < 50 )
                {
                    ch.SendText( "&+rYou deny the damage.&n\r\n" );
                    immune = true;
                    dam = 0;
                }
                else
                    dam -= dam / 5;
            }
            if( ( damType == AttackType.DamageType.earth || damType == AttackType.DamageType.crushing )
                    && victim.IsAffected( Affect.AFFECT_DENY_EARTH))
            {
                if( MUDMath.NumberPercent() < 50 )
                {
                    ch.SendText( "&+yYou deny the damage.&n\r\n" );
                    immune = true;
                    dam = 0;
                }
                else
                    dam -= dam / 5;
            }
            if( ( damType == AttackType.DamageType.water || damType == AttackType.DamageType.acid || damType == AttackType.DamageType.drowning )
                    && victim.IsAffected( Affect.AFFECT_DENY_WATER))
            {
                if( MUDMath.NumberPercent() < 50 )
                {
                    ch.SendText( "&+bYou deny the damage.&n\r\n" );
                    immune = true;
                    dam = 0;
                }
                else
                    dam -= dam / 5;
            }

            // Check for protection spells that give 25% damage reduction - Xangis
            if (damType == AttackType.DamageType.fire && victim.IsAffected( Affect.AFFECT_PROTECT_FIRE))
                dam = ( dam * 3 ) / 4;
            else if (damType == AttackType.DamageType.cold && victim.IsAffected( Affect.AFFECT_PROTECT_COLD))
                dam = ( dam * 3 ) / 4;
            else if (damType == AttackType.DamageType.acid && victim.IsAffected( Affect.AFFECT_PROTECT_ACID))
                dam = ( dam * 3 ) / 4;
            else if (damType == AttackType.DamageType.gas && victim.IsAffected( Affect.AFFECT_PROTECT_GAS))
                dam = ( dam * 3 ) / 4;
            else if (damType == AttackType.DamageType.electricity && victim.IsAffected( Affect.AFFECT_PROTECT_LIGHTNING))
                dam = ( dam * 3 ) / 4;

            // Barkskin protects from 8% of slash and 12% of pierce damage.
            if (victim.IsAffected( Affect.AFFECT_BARKSKIN))
            {
                if (skill == "1h slashing" || skill == "2h slashing")
                    dam = dam * 11 / 12;
                else if (skill == "1h piercing" || skill == "2h piercing")
                    dam = dam * 7 / 8;
            }

            // Check for vampiric touch for anti-paladins and vampires
            if( weapon == ObjTemplate.WearLocation.hand_one || weapon == ObjTemplate.WearLocation.hand_two || weapon == ObjTemplate.WearLocation.hand_three || weapon == ObjTemplate.WearLocation.hand_four )
            {
                if( ( ( ch.IsClass(CharClass.Names.antipaladin) || ch.GetRace() == Race.RACE_VAMPIRE )
                        && skill == "barehanded fighting" && !Object.GetEquipmentOnCharacter(ch, weapon)) || (ch.IsAffected( Affect.AFFECT_VAMP_TOUCH)
                             && ( !( obj = Object.GetEquipmentOnCharacter( ch, weapon ) ) || obj.HasAffect( Affect.AFFECT_VAMP_TOUCH ) ) ) )
                {
                    ch.Hitpoints += dam / 3;
                    if( ch.Hitpoints > ( ch.GetMaxHit() + 50 + ch.Level * 5 ) )
                    {
                        ch.Hitpoints = ch.GetMaxHit() + 50 + ch.Level * 5;
                    }
                }
            }

            /* PC to PC damage quartered.
            *  NPC to PC damage divided by 3.
            */
            if( dam > 0 && !victim.IsNPC() && victim != ch )
            {
                if( !ch.IsNPC() )
                    dam /= 4;
                else
                    dam /= 3;
            }

            /*
            * Just a check for anything that is excessive damage
            * Send a log message, keeping the imms on their toes
            * Changed this from 300 to 250 'cause hitters get more than one
            *  attack/round and w/haste that's 1000 possible in the time one fist
            *  goes off.  That's more than the fist might do and it has to be
            *  memmed.
            */
            if (dam > 250 && skill != "backstab" )
            {
                string buf4;
                if (!string.IsNullOrEmpty(skill))
                {
                    buf4 = String.Format("Excessive damage: {0} attacking {1} for {2}, skill = {3}({4}).",
                              ch.Name, victim.Name, dam, Skill.SkillList[skill].DamageText, skill);
                }
                else
                {
                    buf4 = String.Format("Excessive damage: {0} attacking {1} for {2}, unknown damage type.",
                              ch.Name, victim.Name, dam);
                }
                Log.Trace( buf4 );
            }

            /*
            * We moved DamageMessage out of the victim != ch if above
            * so self damage would show.  Other valid type_undefined
            * damage is ok to avoid like mortally wounded damage
            */
            if (!String.IsNullOrEmpty(skill))
            {
                SendDamageMessage(ch, victim, dam, skill, weapon, immune);
            }

            victim.Hitpoints -= dam;

            /* Check for HOLY_SACRFICE and BATTLE_ECSTASY */
            if( dam > 0 && victim != ch )
            {
                CharData groupChar;
                if (victim.IsAffected( Affect.AFFECT_HOLY_SACRIFICE) && victim.GroupLeader)
                {
                    for( groupChar = victim.GroupLeader; groupChar; groupChar = groupChar.NextInGroup )
                    {
                        if( groupChar == victim || groupChar.InRoom != ch.InRoom )
                            continue;
                        groupChar.Hitpoints += dam / 5;
                        if (groupChar.Hitpoints > groupChar.GetMaxHit() + 50 + groupChar.Level * 5)
                        {
                            groupChar.Hitpoints = groupChar.GetMaxHit() + 50 + groupChar.Level * 5;
                        }
                    } //end for loop
                } //end if holy sac
                if( ch.GroupLeader != null )
                {
                    for( groupChar = ch.GroupLeader; groupChar != null; groupChar = groupChar.NextInGroup )
                    {
                        if( groupChar == victim || groupChar.InRoom != ch.InRoom )
                            continue;
                        if( groupChar.IsAffected( Affect.AFFECT_BATTLE_ECSTASY ) )
                        {
                            groupChar.Hitpoints += dam / 20;
                            if( groupChar.Hitpoints > groupChar.GetMaxHit() + 50 + groupChar.Level * 5 )
                                groupChar.Hitpoints = groupChar.GetMaxHit() + 50 + groupChar.Level * 5;
                        } // end if battle ecstasy
                    } //end for loop
                } //end if grouped
            } //end if

            // Make sure if they got an instant kill roll that the victim dies.
            if (skill == "instant kill")
            {
                if( victim.GetRace() != Race.RACE_DEVIL
                        && victim.GetRace() != Race.RACE_DEMON
                        && victim.GetRace() != Race.RACE_GOD )
                    victim.Hitpoints = -20;
            }

            /* Added damage exp! */
            // chance added because people level faster and faster as they get higher level...
            // to be worked out when exp is redone.
            // you can now only get damage exp on mobs that con easy or better
            // and there's only a 25% chance per hit of you evern being eligible for damage exp.
            if( MUDMath.NumberPercent() < 25 && victim.Level >= ( ch.Level - 3 ) )
                ch.GainExperience( Math.Max( 1, dam / 20 ) );

            if( !victim.IsNPC()
                    && victim.Level >= Limits.LEVEL_AVATAR
                    && victim.Hitpoints < 1 )
                victim.Hitpoints = 1;

            /*
            * Magic shields that retaliate
            *
            * Apparently two people with the same sort of shield do not
            * take damage from each other
            */
            if( ( dam > 1 ) && victim != ch )
            {
                if( victim.IsAffected( Affect.AFFECT_FIRESHIELD )
                        && !ch.IsAffected( Affect.AFFECT_FIRESHIELD ) )
                    InflictSpellDamage( victim, ch, dam / 2, "fireshield", AttackType.DamageType.fire );

                if (victim.IsAffected( Affect.AFFECT_COLDSHIELD)
                        && !ch.IsAffected(Affect.AFFECT_COLDSHIELD))
                    InflictSpellDamage( victim, ch, dam / 2, "coldshield", AttackType.DamageType.cold );

                if (victim.IsAffected(Affect.AFFECT_SHOCK_SHIELD)
                        && !ch.IsAffected(Affect.AFFECT_SHOCK_SHIELD))
                    InflictSpellDamage( victim, ch, dam / 2, "shockshield", AttackType.DamageType.electricity );

                /* Soulshield is a complex one.  If the attacker and victim are of
                * opposite alignment, the shield retaliates with 1/2 damage just like
                * any other shield.  If the victim is neutral and the attacker is
                * not, the shield retaliates with 1/4 damage.  If the victim is good
                * or evil and the attacker is neutral, the shield retaliates with
                * 1/8 damage.  If the attacker and victim are of same alignment,
                * the shield does nothing.
                */
                if (victim.IsAffected(Affect.AFFECT_SOULSHIELD)
                        && !ch.IsAffected(Affect.AFFECT_SOULSHIELD))
                {
                    if( victim.IsEvil() && ch.IsGood() )
                        InflictSpellDamage(victim, ch, dam / 2, "soulshield", AttackType.DamageType.harm);
                    else if( victim.IsGood() && ch.IsEvil() )
                        InflictSpellDamage(victim, ch, dam / 2, "soulshield", AttackType.DamageType.harm);
                    else if( victim.IsNeutral() && ( ch.IsEvil() || ch.IsGood() ) )
                        InflictSpellDamage(victim, ch, dam / 4, "soulshield", AttackType.DamageType.harm);
                    else if( victim.IsGood() && ch.IsNeutral() )
                        InflictSpellDamage(victim, ch, dam / 8, "soulshield", AttackType.DamageType.harm);
                    else if( victim.IsEvil() && ch.IsNeutral() )
                        InflictSpellDamage(victim, ch, dam / 8, "soulshield", AttackType.DamageType.harm);
                }
            }

            if (victim.IsAffected( Affect.AFFECT_BERZERK ) && victim.CurrentPosition <= Position.stunned )
                victim.RemoveAffect(Affect.AFFECT_BERZERK);

            if (dam > 0 && skill != "barehanded fighting"
                    && IsWieldingPoisoned( ch, weapon )
                    && !Magic.SpellSavingThrow( ch.Level, victim, AttackType.DamageType.poison ) )
            {
                InflictPoison( "poison_weapon", ch.Level, IsWieldingPoisoned( ch, weapon ), ch, victim );
                SocketConnection.Act( "$n&n suffers from the &+Gpoison&n inflicted upon $m.", victim, null, null, SocketConnection.MessageTarget.room, true );
                Object.StripAffect( Object.GetEquipmentOnCharacter( ch, weapon ), Affect.AffectType.skill, "poison weapon" );
            }

            victim.UpdatePosition();

            switch( victim.CurrentPosition )
            {
                case Position.mortally_wounded:
                    victim.SendText(
                        "&+LYou are &+Rmo&n&+rr&+Rt&n&+ral&+Rl&n&+ry&+L wounded, and will die soon, if not aided.&n\r\n" );
                    SocketConnection.Act( "$n&+L is &+Rmo&n&+rr&+Rt&n&+ral&+Rl&n&+ry&+L wounded, and will die soon, if not aided.&n",
                         victim, null, null, SocketConnection.MessageTarget.room, true );
                    StopNotVicious( victim );
                    break;

                case Position.incapacitated:
                    victim.SendText(
                        "&+LYou are incapacitated and will &n&+rbl&+Re&n&+re&+Rd&+L to death, if not aided.&n\r\n" );
                    SocketConnection.Act( "$n&+L is incapacitated and will slowly &n&+rbl&+Re&n&+re&+Rd&+L to death, if not aided.&n",
                         victim, null, null, SocketConnection.MessageTarget.room, true );
                    StopNotVicious( victim );
                    break;

                case Position.stunned:
                    victim.SendText( "&+LYou are stunned, but will probably recover.&n\r\n" );
                    SocketConnection.Act( "$n&+L is stunned, but will probably recover.&n",
                         victim, null, null, SocketConnection.MessageTarget.room, true );
                    break;

                case Position.dead:
                    if( victim == ch )
                    {
                        victim.SendText( "&+LYou have been &+Rsl&n&+ra&+Ri&n&+rn&+L!&n\r\n\r\n" );
                    }
                    else
                    {
                        string buf = String.Format( "&+LYou have been &+Rsl&n&+ra&+Ri&n&+rn&+L by&n {0}&+L!&n\r\n\r\n",
                                                    ch.ShowNameTo( victim, false ) );
                        victim.SendText( buf );
                    }
                    /* Added this to stop a bug. */
                    Combat.StopFighting( victim, true );
                    SocketConnection.Act( "$n&+L is &n&+rdead&+L!&n", victim, null, null, SocketConnection.MessageTarget.room, true );
                    break;

                default:
                    if( dam > victim.GetMaxHit() / 5 )
                        victim.SendText( "That really did &+RHURT&n!\r\n" );
                    if( victim.Hitpoints < victim.GetMaxHit() / 10 )
                        victim.SendText( "You sure are &n&+rBL&+RE&n&+rE&+RDI&n&+rN&+RG&n!\r\n" );
                    break;
            }

            // Check for weapon procs
            if( ( obj = Object.GetEquipmentOnCharacter( ch, weapon ) ) && Position.dead != victim.CurrentPosition )
            {
                if( obj.SpecFun.Count > 0 )
                    obj.CheckSpecialFunction(true);
            }

            /*
            * Sleep spells and extremely wounded folks.
            */
            if( !victim.IsAwake() )      /* lets make NPC's not slaughter PC's */
            {
                if( victim.Fighting
                        && victim.Fighting.Hunting
                        && victim.Fighting.Hunting.Who == victim )
                    StopHunting( victim.Fighting );
                if( victim.Fighting
                        && !victim.IsNPC()
                        && ch.IsNPC() )
                    StopFighting( victim, true );
                else
                    StopFighting( victim, false );
            }

            /*
            * Payoff for killing things.
            */
            if( victim.CurrentPosition == Position.dead )
            {
                // Done in attempt to squelch the combat continuation bug
                StopFighting( victim, true );

                if( !victim.HasActionBit(MobTemplate.ACT_NOEXP ) || !victim.IsNPC() )
                    GroupExperienceGain( ch, victim );

                if( ch.IsNPC() )
                {
                    if( ch.Hunting )
                    {
                        if( ch.Hunting.Who == victim )
                            StopHunting( ch );
                    }
                    if( ch.IsHating(victim) )
                    {
                        ch.StopHating( victim );
                    }
                }

                if( !victim.IsNPC() )
                {
                    if( ch.IsNPC() )
                    {
                        ( (PC)victim ).MobDeaths++;
                        if( victim.IsGuild() )
                        {
                            ( (PC)victim ).GuildMembership.MonsterDeaths++;
                            ( (PC)victim ).GuildMembership.Score += CalculateDeathScore( ch, victim );
                        }
                        ( (PC)victim ).Score += CalculateDeathScore( ch, victim );

                    }
                    else
                    {
                        ( (PC)ch ).PlayerKills++;
                        ( (PC)victim ).PlayerDeaths++;

                        ( (PC)victim ).Score += CalculateDeathScore( ch, victim );
                        ( (PC)ch ).Score += CalculateKillScore( ch, victim );

                        if( ch.IsGuild()
                                && victim.IsGuild()
                                && ( (PC)ch ).GuildMembership != ( (PC)victim ).GuildMembership )
                        {
                            ( (PC)ch ).GuildMembership.PlayerKills++;
                            ( (PC)victim ).GuildMembership.PlayerDeaths++;
                            ( (PC)ch ).GuildMembership.Score += CalculateKillScore( ch, victim );
                            ( (PC)victim ).GuildMembership.Score += CalculateDeathScore( ch, victim );
                        }
                    }

                    string logBuf = String.Format( "{0}&n killed by {1}&n at {2}",
                              victim.Name, ( ch.IsNPC() ? ch.ShortDescription : ch.Name ),
                              victim.InRoom.IndexNumber );
                    Log.Trace( logBuf );
                    ImmortalChat.SendImmortalChat( ch, ImmortalChat.IMMTALK_DEATHS, Limits.LEVEL_AVATAR, logBuf );

                    /*
                    * Dying penalty:
                    *
                    * At level 1 you lose 12.5% of a level.
                    * At level 50 you lose 25% of a level.
                    */
                    // Made it so people level 5 and under lose no exp from death.
                    if( ch.Level > 5 )
                        victim.GainExperience( ( 0 - ( ( ( 50 + victim.Level ) * ExperienceTable.Table[ victim.Level ].LevelExperience ) / 400 ) ) );
                    if( victim.Level < 2 && victim.ExperiencePoints < 1 )
                        victim.ExperiencePoints = 1;

                }
                else
                {
                    if( !ch.IsNPC() )
                    {
                        ( (PC)ch ).MobKills++;
                        if( ch.IsGuild() )
                        {
                            ( (PC)ch ).GuildMembership.MonsterKills++;
                            ( (PC)ch ).GuildMembership.Score += CalculateKillScore( ch, victim );
                        }
                        ( (PC)ch ).Score += CalculateKillScore( ch, victim );
                    }
                }
                KillingBlow( ch, victim );

                return true;
            }

            if( victim == ch )
            {
                return false;
            }

            /*
            * Wimp out?
            */
            if( victim.IsNPC() && dam > 0 )
            {
                if( ( victim.HasActionBit(MobTemplate.ACT_WIMPY ) && MUDMath.NumberBits( 1 ) == 0
                        && victim.Hitpoints < victim.GetMaxHit() / 5 )
                        || (victim.IsAffected( Affect.AFFECT_CHARM) && victim.Master
                             && victim.Master.InRoom != victim.InRoom ) )
                {
                    StartFearing( victim, ch );
                    StopHunting( victim );
                    CommandType.Interpret(victim, "flee");
                }
            }

            if( !victim.IsNPC() && victim.Hitpoints > 0 && victim.Hitpoints <= victim.Wimpy )
            {
                CommandType.Interpret(victim, "flee");
            }

            return false;
        }
Esempio n. 10
0
        /// <summary>
        /// Inflicts damage from a spell, based on the weapon damage() function, but customized for spells.
        /// 
        /// Needs to be cleaned up because it's just too big (600+ lines).
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="victim"></param>
        /// <param name="dam"></param>
        /// <param name="spell"></param>
        /// <param name="damType"></param>
        /// <returns></returns>
        public static bool InflictSpellDamage( CharData ch, CharData victim, int dam, Spell spell, AttackType.DamageType damType )
        {
            if( ch == null || victim == null || victim.CurrentPosition == Position.dead )
                return true;

            // Remove memorization and meditation bits.
            // And invis.
            ch.BreakInvisibility();
            victim.BreakMeditate();
            victim.BreakMemorization();

            if( CheckShrug( ch, victim ) )
                return false;

            if( victim.CurrentPosition == Position.sleeping
                    && !( victim.GetRace() == Race.RACE_FIRE_ELE && damType == AttackType.DamageType.fire )
                    && !( victim.GetRace() == Race.RACE_WATER_ELE && damType == AttackType.DamageType.water )
                    && !( victim.GetRace() == Race.RACE_EARTH_ELE && damType == AttackType.DamageType.earth )
                    && !( victim.GetRace() == Race.RACE_AIR_ELE && damType == AttackType.DamageType.wind ) )
            {
                SocketConnection.Act( "$n&n has a rude awakening!", victim, null, null, SocketConnection.MessageTarget.room );
                victim.CurrentPosition = Position.resting;
                if( ch.InRoom == victim.InRoom && ch.FlightLevel == victim.FlightLevel )
                    SetFighting( victim, ch );
            }

            // Check for globe spells.  See also FinishSpell under TargetType.singleCharacterOffensive
            // This check here is just to prevent area effect spells from
            // doing damage if too low level.  The check for direct spells is in
            // Magic.cs
            if (victim.IsAffected( Affect.AFFECT_MAJOR_GLOBE)
                    && (spell.SpellCircle[(int)ch.CharacterClass.ClassNumber] <= 6
                         || spell.Name == "fireshield"
                         || spell.Name == "shockshield"
                         || spell.Name == "soulshield"
                         || spell.Name == "coldshield" ) )
            {
                SocketConnection.Act( "&+RThe globe around $N&+R's body bears the brunt of your assault!&n", ch, null, victim, SocketConnection.MessageTarget.character );
                SocketConnection.Act( "&+RYour globe deflects $n&+R's attack!&n", ch, null, victim, SocketConnection.MessageTarget.victim );
                SocketConnection.Act( "&+R$N&+R's globe deflects $n&+R's attack!&n", ch, null, victim, SocketConnection.MessageTarget.room_vict );
                return false;
            }
            if (victim.IsAffected( Affect.AFFECT_GREATER_SPIRIT_WARD) && spell.SpellCircle[(int)ch.CharacterClass.ClassNumber] <= 5)
            {
                SocketConnection.Act( "&+WThe aura around $N&+W's body bears the brunt of your assault!&n", ch, null, victim, SocketConnection.MessageTarget.character );
                SocketConnection.Act( "&+WYour globe absorbs $n&+W's attack!&n", ch, null, victim, SocketConnection.MessageTarget.victim );
                SocketConnection.Act( "&+W$N&+W's aura absorbs $n&+W's attack!&n", ch, null, victim, SocketConnection.MessageTarget.room_vict );
                return false;
            }
            if (victim.IsAffected( Affect.AFFECT_MINOR_GLOBE) && spell.SpellCircle[(int)ch.CharacterClass.ClassNumber] <= 4)
            {
                SocketConnection.Act( "&+RThe globe around $N&+R's body bears the brunt of your assault!&n", ch, null, victim, SocketConnection.MessageTarget.character );
                SocketConnection.Act( "&+RYour globe deflects $n&+R's attack!&n", ch, null, victim, SocketConnection.MessageTarget.victim );
                SocketConnection.Act( "&+R$N&+R's globe deflects $n&+R's attack!&n", ch, null, victim, SocketConnection.MessageTarget.room_vict );
                return false;
            }
            if (victim.IsAffected( Affect.AFFECT_SPIRIT_WARD) && spell.SpellCircle[(int)ch.CharacterClass.ClassNumber] <= 3)
            {
                SocketConnection.Act( "&+WThe aura around $N&+W's body bears the brunt of your assault!&n", ch, null, victim, SocketConnection.MessageTarget.character );
                SocketConnection.Act( "&+WYour globe absorbs $n&+W's attack!&n", ch, null, victim, SocketConnection.MessageTarget.victim );
                SocketConnection.Act( "&+W$N&+W's aura absorbs $n&+W's attack!&n", ch, null, victim, SocketConnection.MessageTarget.victim );
                return false;
            }

            /*
            * Stop up any residual loopholes.
            */
            // 1275 is average damage from Akiaurn's Power Word
            // I changed this to reflect that.
            if( ( dam > 1275 ) && ch.Level < Limits.LEVEL_AVATAR && ch.GetRace() != Race.RACE_DRAGON )
            {
                string buf3;

                if( ch.IsNPC() && ch.Socket )
                    buf3 = String.Format(
                              "Spell_Damage: {0} from {1} by {2}: > 1275 points with {3} spell!",
                              dam, ch.Name, ch.Socket.Original.Name, spell.Name );
                else
                    buf3 = String.Format(
                              "Spell_Damage: {0} from {1}: > 1275 points with {2} spell!",
                              dam, ch.IsNPC() ? ch.ShortDescription : ch.Name, spell.Name );

                Log.Error( buf3, 0 );
                dam = 1275;
            }

            if (victim.IsAffected( Affect.AFFECT_MINOR_PARA)
                    && !( victim.GetRace() == Race.RACE_FIRE_ELE && damType == AttackType.DamageType.fire )
                    && !( victim.GetRace() == Race.RACE_WATER_ELE && damType == AttackType.DamageType.water )
                    && !( victim.GetRace() == Race.RACE_EARTH_ELE && damType == AttackType.DamageType.earth )
                    && !( victim.GetRace() == Race.RACE_AIR_ELE && damType == AttackType.DamageType.wind ) )
            {
                SocketConnection.Act( "$n&n disrupts the magic preventing $N&n from moving.", ch, null, victim, SocketConnection.MessageTarget.room_vict );
                SocketConnection.Act( "You disrupt the magic preventing $N&n from moving.", ch, null, victim, SocketConnection.MessageTarget.character );
                SocketConnection.Act( "&+YYou can move again.&n", ch, null, victim, SocketConnection.MessageTarget.victim );
                victim.RemoveAffect( Affect.AFFECT_MINOR_PARA );
                victim.AffectStrip( Affect.AffectType.spell, "earthen grasp" );
                victim.AffectStrip( Affect.AffectType.spell, "greater earthen grasp");
            }

            bool immune = false;
            if( victim != ch )
            {
                /*
                * Certain attacks are forbidden.
                * Most other attacks are returned.
                */
                if( IsSafe( ch, victim ) )
                    return false;
                // is_safe could wipe out victim, as it calls procs if a boss
                // check and see that victim is still valid
                if( !victim )
                    return true;
                Crime.CheckAttemptedMurder( ch, victim );

                if( victim.CurrentPosition > Position.stunned
                        && !( victim.GetRace() == Race.RACE_FIRE_ELE && damType == AttackType.DamageType.fire )
                        && !( victim.GetRace() == Race.RACE_WATER_ELE && damType == AttackType.DamageType.water )
                        && !( victim.GetRace() == Race.RACE_EARTH_ELE && damType == AttackType.DamageType.earth )
                        && !( victim.GetRace() == Race.RACE_AIR_ELE && damType == AttackType.DamageType.wind ) )
                {
                    // Offensive spells engage victim if not fighting, and
                    //   caster only if neither are fighting.
                    if( !victim.Fighting && victim.InRoom == ch.InRoom
                            && victim.FlightLevel == ch.FlightLevel )
                    {
                        SetFighting( victim, ch );
                        if( !ch.Fighting )
                            SetFighting( ch, victim );
                        // Can't have prone people automaticaly stand.
                        if( victim.CurrentPosition == Position.standing )
                            victim.CurrentPosition = Position.fighting;
                    }
                    /*
                    * If NPC victim is following, ch might attack victim's master.
                    * No charm check here because charm would be dispelled from
                    * tanking mobile when combat ensues thus ensuring PC charmer is
                    * not harmed.
                    * Check for is_same_group wont work as following mobile is not
                    * always grouped with PC charmer
                    */
                    if( ch.IsNPC()
                            && victim.IsNPC()
                            && victim.Master
                            && victim.Master.InRoom == ch.InRoom
                            && MUDMath.NumberBits( 2 ) == 0 )
                    {
                        StopFighting( ch, false );
                        SetFighting( ch, victim.Master );
                        return false;
                    }
                }

                /*
                * More charm stuff.
                */
                if( victim.Master == ch
                        && !( victim.GetRace() == Race.RACE_FIRE_ELE && damType == AttackType.DamageType.fire )
                        && !( victim.GetRace() == Race.RACE_WATER_ELE && damType == AttackType.DamageType.water )
                        && !( victim.GetRace() == Race.RACE_EARTH_ELE && damType == AttackType.DamageType.earth )
                        && !( victim.GetRace() == Race.RACE_AIR_ELE && damType == AttackType.DamageType.wind ) )
                    StopFighting( victim, true );

                /*
                * Hunting stuff...
                */
                if( dam != 0 && victim.IsNPC()
                        && !( victim.GetRace() == Race.RACE_FIRE_ELE && damType == AttackType.DamageType.fire )
                        && !( victim.GetRace() == Race.RACE_WATER_ELE && damType == AttackType.DamageType.water )
                        && !( victim.GetRace() == Race.RACE_EARTH_ELE && damType == AttackType.DamageType.earth )
                        && !( victim.GetRace() == Race.RACE_AIR_ELE && damType == AttackType.DamageType.wind ) )
                {
                    StartGrudge( victim, ch, false );
                }

                /*
                * Damage modifiers.
                */
                if (victim.IsAffected( Affect.AFFECT_SANCTUARY))
                    dam /= 2;

                if ((victim.IsAffected( Affect.AFFECT_PROTECT_EVIL)) && ch.IsEvil())
                    dam -= dam / 8;
                else if ((victim.IsAffected( Affect.AFFECT_PROTECT_GOOD)) && ch.IsGood())
                    dam -= dam / 8;

                if( dam < 0 )
                    dam = 0;
            }

            switch( victim.CheckRIS( damType ) )
            {
                case Race.ResistanceType.resistant:
                    dam -= dam / 3;
                    break;
                case Race.ResistanceType.immune:
                    immune = true;
                    dam = 0;
                    break;
                case Race.ResistanceType.susceptible:
                    dam += dam / 2;
                    break;
                case Race.ResistanceType.vulnerable:
                    dam *= 2;
                    break;
            }

            if( ( damType == AttackType.DamageType.wind || damType == AttackType.DamageType.gas || damType == AttackType.DamageType.asphyxiation )
                    && victim.IsAffected( Affect.AFFECT_DENY_AIR))
            {
                if( MUDMath.NumberPercent() < 50 )
                {
                    victim.SendText( "&+CYou deny the damage.&n\r\n" );
                    immune = true;
                    dam = 0;
                }
                else
                    dam -= dam / 5;
            }
            if (damType == AttackType.DamageType.fire && victim.IsAffected( Affect.AFFECT_DENY_FIRE))
            {
                if( MUDMath.NumberPercent() < 50 )
                {
                    victim.SendText( "&+rYou deny the damage.&n\r\n" );
                    immune = true;
                    dam = 0;
                }
                else
                    dam -= dam / 5;
            }
            if( ( damType == AttackType.DamageType.earth || damType == AttackType.DamageType.crushing )
                    && victim.IsAffected(Affect.AFFECT_DENY_EARTH))
            {
                if( MUDMath.NumberPercent() < 50 )
                {
                    victim.SendText( "&+yYou deny the damage.&n\r\n" );
                    immune = true;
                    dam = 0;
                }
                else
                    dam -= dam / 5;
            }
            if( ( damType == AttackType.DamageType.water || damType == AttackType.DamageType.acid || damType == AttackType.DamageType.drowning )
                    && victim.IsAffected(Affect.AFFECT_DENY_WATER))
            {
                if( MUDMath.NumberPercent() < 50 )
                {
                    victim.SendText( "&+bYou deny the damage.&n\r\n" );
                    immune = true;
                    dam = 0;
                }
                else
                    dam -= dam / 5;
            }

            // Check for protection spells that give 25% damage reduction - Xangis
            if (damType == AttackType.DamageType.fire && victim.IsAffected( Affect.AFFECT_PROTECT_FIRE))
                dam = ( dam * 3 ) / 4;
            else if (damType == AttackType.DamageType.cold && victim.IsAffected( Affect.AFFECT_PROTECT_COLD))
                dam = ( dam * 3 ) / 4;
            else if (damType == AttackType.DamageType.acid && victim.IsAffected( Affect.AFFECT_PROTECT_ACID))
                dam = ( dam * 3 ) / 4;
            else if (damType == AttackType.DamageType.gas && victim.IsAffected( Affect.AFFECT_PROTECT_GAS))
                dam = ( dam * 3 ) / 4;
            else if (damType == AttackType.DamageType.electricity && victim.IsAffected( Affect.AFFECT_PROTECT_LIGHTNING))
                dam = ( dam * 3 ) / 4;

            /*
            * We moved DamageMessage out of the victim != ch if above
            * so self damage would show.  Other valid type_undefined
            * damage is ok to avoid like mortally wounded damage
            */
            if( spell != Spell.SpellList["reserved"]
                    && !( victim.GetRace() == Race.RACE_FIRE_ELE && damType == AttackType.DamageType.fire )
                    && !( victim.GetRace() == Race.RACE_WATER_ELE && damType == AttackType.DamageType.water )
                    && !( victim.GetRace() == Race.RACE_EARTH_ELE && damType == AttackType.DamageType.earth )
                    && !( victim.GetRace() == Race.RACE_AIR_ELE && damType == AttackType.DamageType.wind ) )
                SendSpellDamageMessage( ch, victim, dam, spell, immune );

            /*  PC to PC damage quartered.
            *  NPC to PC damage divided by 3.
            */
            if( dam > 0 && !victim.IsNPC() && victim != ch )
            {
                if( !ch.IsNPC() )
                    dam /= 4;
                else
                    dam /= 3;
            }

            /*
            * Hurt the victim.
            * Inform the victim of his new state.
            */
            if( !( victim.GetRace() == Race.RACE_FIRE_ELE && damType == AttackType.DamageType.fire )
                    && !( victim.GetRace() == Race.RACE_WATER_ELE && damType == AttackType.DamageType.water )
                    && !( victim.GetRace() == Race.RACE_EARTH_ELE && damType == AttackType.DamageType.earth )
                    && !( victim.GetRace() == Race.RACE_AIR_ELE && damType == AttackType.DamageType.wind ) )
            {
                /* Added damage exp! */
                // chance added because people level faster and faster as they get higher level...
                // you can now only get damage exp on mobs that con easy or better
                // and there's only a 25% chance per hit of you evern being eligible for damage exp.
                if( MUDMath.NumberPercent() < 25 && victim.Level >= ( ch.Level - 3 ) )
                    ch.GainExperience( Math.Max( 1, dam / 20 ) );
                victim.Hitpoints -= dam;
            }
            else
            {
                string attack;

                if( spell != null && spell != Spell.SpellList["none"] )
                    attack = spell.Name;
                else
                    attack = "it";

                SocketConnection.Act( "$N&n absorbs your $t!", ch, attack, victim, SocketConnection.MessageTarget.character );
                SocketConnection.Act( "You absorb $n&n's $t!", ch, attack, victim, SocketConnection.MessageTarget.victim );
                SocketConnection.Act( "$N&n absorbs $n&n's $t", ch, attack, victim, SocketConnection.MessageTarget.room_vict );
                if( ch.IsImmortal() )
                {
                    string buf4 = String.Format( "You healed {0} damage.",
                                                 victim.GetMaxHit() >= dam + victim.Hitpoints ? dam : victim.GetMaxHit() - victim.Hitpoints );
                    ch.SendText( buf4 );
                }

                victim.Hitpoints = Math.Min( victim.GetMaxHit(), victim.Hitpoints + dam );

                return false;
            }

            if( !victim.IsNPC()
                    && victim.Level >= Limits.LEVEL_AVATAR
                    && victim.Hitpoints < 1 )
                victim.Hitpoints = 1;

            if (victim.IsAffected(Affect.AFFECT_BERZERK)
                    && victim.CurrentPosition <= Position.stunned )
                victim.RemoveAffect(Affect.AFFECT_BERZERK);

            victim.UpdatePosition();

            switch( victim.CurrentPosition )
            {
                case Position.mortally_wounded:
                    victim.SendText(
                        "&+LYou are &+Rmo&n&+rr&+Rt&n&+ral&+Rl&n&+ry&+L wounded, and will die soon, if not aided.&n\r\n" );
                    SocketConnection.Act( "$n&+L is &+Rmo&n&+rr&+Rt&n&+ral&+Rl&n&+ry&+L wounded, and will die soon, if not aided.&n",
                         victim, null, null, SocketConnection.MessageTarget.room, true );
                    StopNotVicious( victim );
                    break;

                case Position.incapacitated:
                    victim.SendText(
                        "&+LYou are incapacitated and will slowly &n&+rbl&+Re&n&+re&+Rd&+L to death, if not aided.\r\n" );
                    SocketConnection.Act( "$n&+L is incapacitated and will slowly &n&+rbl&+Re&n&+re&+Rd&+L to death, if not aided.&n",
                         victim, null, null, SocketConnection.MessageTarget.room, true );
                    StopNotVicious( victim );
                    break;

                case Position.stunned:
                    victim.SendText( "&+LYou are stunned, but will probably recover.&n\r\n" );
                    SocketConnection.Act( "$n&+L is stunned, but will probably recover.&n",
                         victim, null, null, SocketConnection.MessageTarget.room, true );
                    break;

                case Position.dead:
                    SocketConnection.Act( spell.MessageKill, ch, null, victim, SocketConnection.MessageTarget.room_vict );
                    SocketConnection.Act( spell.MessageKill, ch, null, victim, SocketConnection.MessageTarget.character );
                    if( victim == ch )
                    {
                        victim.SendText( "&+LYou have been &+Rsl&n&+ra&+Ri&n&+rn&+L!&n\r\n\r\n" );
                    }
                    else
                    {
                        string buf = String.Format( "&+LYou have been &+Rsl&n&+ra&+Ri&n&+rn&+L by&n {0}&+L!&n\r\n\r\n",
                                                    ch.ShowNameTo( victim, false ) );
                        victim.SendText( buf );
                    }
                    StopFighting( victim, true );
                    SocketConnection.Act( "$n&+L is &n&+rdead&+L!&n", victim, null, null, SocketConnection.MessageTarget.room, true );
                    break;

                default:
                    if( dam > victim.GetMaxHit() / 5 )
                        victim.SendText( "That really did &+RHURT&n!\r\n" );
                    if( victim.Hitpoints < victim.GetMaxHit() / 10 )
                        victim.SendText( "You sure are &n&+rBL&+RE&n&+rE&+RDI&n&+rN&+RG&n!\r\n" );
                    break;
            }

            /*
            * Sleep spells and extremely wounded folks.
            */
            if( !victim.IsAwake() )      /* lets make NPC's not slaughter PC's */
            {
                if( victim.Fighting
                        && victim.Fighting.Hunting
                        && victim.Fighting.Hunting.Who == victim )
                    StopHunting( victim.Fighting );
                if( victim.Fighting
                        && !victim.IsNPC()
                        && ch.IsNPC() )
                    StopFighting( victim, true );
                else
                    StopFighting( victim, false );
            }

            /*
            * Payoff for killing things.
            */
            if( victim.CurrentPosition == Position.dead )
            {
                StopFighting( ch, false );

                if( !victim.HasActionBit(MobTemplate.ACT_NOEXP ) || !victim.IsNPC() )
                    GroupExperienceGain( ch, victim );

                if( !victim.IsNPC() )
                {
                    if( ch.IsNPC() )
                    {
                        ( (PC)victim ).MobDeaths++;
                        if( victim.IsGuild() )
                        {
                            ( (PC)victim ).GuildMembership.MonsterDeaths++;
                            ( (PC)victim ).GuildMembership.Score += CalculateDeathScore( ch, victim );
                        }
                        ( (PC)victim ).Score += CalculateDeathScore( ch, victim );
                    }
                    else
                    {
                        ( (PC)ch ).PlayerKills++;
                        ( (PC)victim ).PlayerDeaths++;

                        ( (PC)victim ).Score += CalculateDeathScore( ch, victim );
                        ( (PC)ch ).Score += CalculateKillScore( ch, victim );

                        if( ch.IsGuild()
                                && victim.IsGuild()
                                && ( (PC)ch ).GuildMembership != ( (PC)victim ).GuildMembership )
                        {
                            ( (PC)ch ).GuildMembership.PlayerKills++;
                            ( (PC)victim ).GuildMembership.PlayerDeaths++;
                            ( (PC)ch ).GuildMembership.Score += CalculateKillScore( ch, victim );
                            ( (PC)victim ).GuildMembership.Score += CalculateDeathScore( ch, victim );
                        }
                    }

                    string logBuf = String.Format( "{0}&n killed by {1}&n at {2}",
                              victim.Name,
                              ( ch.IsNPC() ? ch.ShortDescription : ch.Name ),
                              victim.InRoom.IndexNumber );
                    Log.Trace( logBuf );
                    ImmortalChat.SendImmortalChat( ch, ImmortalChat.IMMTALK_DEATHS, Limits.LEVEL_AVATAR, logBuf );

                    /*
                    * Dying penalty:
                    * 1/2 way back to previous 2 levels.
                    */
                    // Newbies do not lose exp from death.
                    if( ch.Level > 5 )
                        victim.GainExperience( ( 0 - ( ( ( 50 + victim.Level ) * ExperienceTable.Table[ victim.Level ].LevelExperience ) / 400 ) ) );
                    if( victim.Level < 2 && victim.ExperiencePoints < 1 )
                        victim.ExperiencePoints = 1;
                }
                else
                {
                    if( !ch.IsNPC() )
                    {
                        ( (PC)ch ).MobKills++;
                        if( ch.IsGuild() )
                        {
                            ( (PC)ch ).GuildMembership.MonsterKills++;
                            ( (PC)ch ).GuildMembership.Score += CalculateKillScore( ch, victim );
                        }
                        ( (PC)ch ).Score += CalculateKillScore( ch, victim );
                    }
                }

                KillingBlow( ch, victim );

                // Keep in mind after this point the character is not in the
                // CharList, not in any room, and is at the menu.  Don't do
                // anything that would cause a segmentation fault.

                if( ch.IsGuild()
                        && victim.IsGuild()
                        && ( (PC)ch ).GuildMembership != ( (PC)victim ).GuildMembership )
                {
                    ( (PC)ch ).GuildMembership.Score += 20;
                }

                return true;
            }

            if( victim == ch )
            {
                return false;
            }

            /*
            * Wimp out?
            */
            if( victim.IsNPC() && dam > 0 )
            {
                if( ( victim.HasActionBit(MobTemplate.ACT_WIMPY ) && MUDMath.NumberBits( 1 ) == 0
                        && victim.Hitpoints < victim.GetMaxHit() / 5 )
                        || (victim.IsAffected(Affect.AFFECT_CHARM) && victim.Master
                             && victim.Master.InRoom != victim.InRoom ) )
                {
                    StartFearing( victim, ch );
                    StopHunting( victim );
                    CommandType.Interpret(victim, "flee");
                }
            }

            if( !victim.IsNPC() && victim.Hitpoints > 0 && victim.Hitpoints <= victim.Wimpy )
            {
                CommandType.Interpret(victim, "flee");
            }

            return false;
        }
Esempio n. 11
0
        public static void StopFollower( CharData ch )
        {
            if( !ch )
            {
                Log.Error("StopFollower called with no CH argument.\r\n", 0);
                return;
            }

            if( !ch.Master )
            {
                Log.Error("StopFollower: null master.", 0);
                return;
            }

            if( ch.IsAffected( Affect.AFFECT_CHARM ) )
            {
                ch.RemoveAffect(Affect.AFFECT_CHARM);
                ch.AffectStrip( Affect.AffectType.spell, "domination");
            }

            if( ch.Master != ch && CanSee( ch.Master, ch ) && ch.Master.InRoom )
                SocketConnection.Act( "$n&n stops following you.", ch, null, ch.Master, SocketConnection.MessageTarget.victim );
            if( ch.InRoom )
                SocketConnection.Act( "You stop following $N&n.", ch, null, ch.Master, SocketConnection.MessageTarget.character );

            // Remove the follower from the list of followers
            foreach( CharData follower in ch.Master.Followers )
            {
                if( follower == ch )
                {
                    ch.Master.Followers.Remove( follower );
                }
            }

            ch.Master = null;

            return;
        }
Esempio n. 12
0
        /// <summary>
        /// Extracts a character from the world.  If delete is true, it then deletes that character.
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="delete"></param>
        public static void ExtractChar( CharData ch, bool delete )
        {
            if( ch == null )
            {
                Log.Error( "ExtractChar: null ch.", 0 );
                return;
            }

            try
            {
                if (ch.Fighting)
                {
                    Combat.StopFighting(ch, true);
                }

                Magic.ForgetAllSpells(ch);

                Event.DeleteAttachedEvents(ch);

                // Remove any affects we want to be gone next time they log in.
                ch.RemoveAffect(Affect.AFFECT_CASTING);
                ch.RemoveAffect(Affect.AFFECT_SINGING);

                // Meaning they're dead for good or have left the game.
                if (delete)
                {
                    string name;

                    if (ch.IsNPC())
                    {
                        name = ch.ShortDescription;
                    }
                    else
                    {
                        name = ch.Name;
                    }

                    ch.DieFollower(name);
                    if (ch.GroupLeader || ch.NextInGroup)
                    {
                        ch.RemoveFromGroup(ch);
                    }

                    /* Get rid of weapons _first_ */

                    {
                        Object obj3 = Object.GetEquipmentOnCharacter(ch, ObjTemplate.WearLocation.hand_one);
                        Object obj2 = Object.GetEquipmentOnCharacter(ch, ObjTemplate.WearLocation.hand_two);

                        if (obj3 != null)
                        {
                            obj3.RemoveFromWorld();
                        }

                        /* Now kill obj2 if it exists no matter if on body or floor */
                        if (obj2)
                        {
                            obj2.RemoveFromWorld();
                        }
                    }

                    for (int i = ch.Carrying.Count - 1; i >= 0; --i)
                    {
                        ch.Carrying[i].RemoveFromWorld();
                    }
                }

                CharData worldChar;
                for (int xx = Database.CharList.Count - 1; xx >= 0; xx--)
                {
                    worldChar = Database.CharList[xx];
                    if (worldChar.ReplyTo == ch)
                    {
                        worldChar.ReplyTo = null;
                    }
                    if (worldChar.IsConsenting(ch))
                    {
                        worldChar.StopConsenting(ch);
                        SocketConnection.Act("You stop consenting $N&n.", worldChar, null, ch, SocketConnection.MessageTarget.character);
                    }
                    if (worldChar.IsIgnoring(ch))
                    {
                        worldChar.StopIgnoring(ch);
                        SocketConnection.Act("You stop ignoring $N&n.", worldChar, null, ch, SocketConnection.MessageTarget.character);
                    }
                    if (!worldChar.IsNPC() && ((PC)worldChar).Guarding == ch)
                    {
                        ((PC)worldChar).Guarding = null;
                        SocketConnection.Act("You stop guarding $N&n.", worldChar, null, ch, SocketConnection.MessageTarget.character);
                    }
                    if (worldChar.IsHating(ch))
                        worldChar.StopHating(ch);
                    if (worldChar.Hunting && worldChar.Hunting.Who == ch)
                        Combat.StopHunting(worldChar);
                    if (worldChar.Fearing && worldChar.Fearing.Who == ch)
                        Combat.StopFearing(worldChar);
                    // Remove from the active character list.
                    // BUG: TODO: FIXME: This invalidates the list for anyone iterating through
                    // a list that may kill characters, such as violence_update.
                    // it = CharList.erase( it );
                }

                if (ch.InRoom)
                {
                    // This was placed *after* the act strings to be safe.
                    for (int iwch = ch.InRoom.People.Count - 1; iwch >= 0; iwch--)
                    {
                        if (ch.InRoom.People[iwch] == ch)
                        {
                            ch.RemoveFromRoom();
                            break;
                        }
                    }
                }

                // They're not being yanked from game, probably just dead and going to the menu.
                if (!delete)
                {
                    Room location;

                    if (ch.Level < 5 || Macros.IsSet((int)Database.SystemData.ActFlags, (int)Sysdata.MudFlags.alwaysequip))
                        ch.ReceiveNewbieEquipment();

                    if (!ch.IsNPC() && (ch.GetOrigRace() < Limits.MAX_PC_RACE) && ((int)ch.CharacterClass.ClassNumber < CharClass.ClassList.Length))
                    {
                        // Get the default respawn location based on currhome, then race/class default.
                        location = Room.GetRoom(((PC)ch).CurrentHome);
                        if (location == null)
                        {
                            int place;
                            List<RepopulationPoint> repoplist = ch.GetAvailableRepops();
                            if (repoplist.Count < 1)
                            {
                                place = StaticRooms.GetRoomNumber("ROOM_NUMBER_START");
                            }
                            else
                            {
                                place = repoplist[0].RoomIndexNumber;
                            }
                            location = Room.GetRoom(place);
                            if (location == null)
                            {
                                Log.Error("Starting room does not exist for class {0} of player's race!  Calling ch.AddToRoom() for altar.", (int)ch.CharacterClass.ClassNumber);
                                ch.AddToRoom(Room.GetRoom(StaticRooms.GetRoomNumber("ROOM_NUMBER_ALTAR")));
                            }
                        }
                        else
                        {
                            ch.AddToRoom(location);
                        }
                    }
                    else
                    {
                        location = Room.GetRoom(StaticRooms.GetRoomNumber("ROOM_NUMBER_START"));
                        if (location == null)
                        {
                            Log.Error("Starting room {0} does not exist!  Calling char_to_room for altar.", StaticRooms.GetRoomNumber("ROOM_NUMBER_START"));
                            ch.AddToRoom(Room.GetRoom(StaticRooms.GetRoomNumber("ROOM_NUMBER_ALTAR")));
                        }
                        else
                        {
                            ch.AddToRoom(Room.GetRoom(StaticRooms.GetRoomNumber("ROOM_NUMBER_START")));
                        }
                    }
                    return;
                }

                // Clear modifiers.
                if (ch.IsNPC())
                {
                    --ch.MobileTemplate.NumActive;
                }
                else
                {
                    ((PC)ch).Hunger = 48;
                    ((PC)ch).Thirst = 48;
                    ((PC)ch).Drunk = 0;
                    ((PC)ch).LastRentLocation = 0;
                    ch.ArmorPoints = 100;
                    ch.CurrentPosition = Position.standing;
                    ch.Hitpoints = Math.Max(1, ch.Hitpoints);
                    ch.CurrentMana = Math.Max(1, ch.CurrentMana);
                    ch.CurrentMoves = Math.Max(1, ch.CurrentMoves);
                    ((PC)ch).HitpointModifier = 0;
                    ch.Hitroll = 0;
                    ch.Damroll = 0;
                    ch.SavingThrows[0] = 0;
                    ch.SavingThrows[1] = 0;
                    ch.SavingThrows[2] = 0;
                    ch.SavingThrows[3] = 0;
                    ch.SavingThrows[4] = 0;
                    ch.ModifiedStrength = 0;
                    ch.ModifiedIntelligence = 0;
                    ch.ModifiedWisdom = 0;
                    ch.ModifiedDexterity = 0;
                    ch.ModifiedConstitution = 0;
                    ch.ModifiedAgility = 0;
                    ch.ModifiedCharisma = 0;
                    ch.ModifiedPower = 0;
                    ch.ModifiedLuck = 0;
                    ((PC)ch).MaxStrMod = 0;
                    ((PC)ch).MaxIntMod = 0;
                    ((PC)ch).MaxWisMod = 0;
                    ((PC)ch).MaxDexMod = 0;
                    ((PC)ch).MaxConMod = 0;
                    ((PC)ch).MaxAgiMod = 0;
                    ((PC)ch).MaxChaMod = 0;
                    ((PC)ch).MaxPowMod = 0;
                    ((PC)ch).MaxLukMod = 0;
                }

                if (ch.Socket && ch.Socket.Original)
                {
                    CommandType.Interpret(ch, "return");
                }

                ch.DeleteMe = true;
            }
            catch (Exception ex)
            {
                Log.Error("Exception in ExtractChar: " + ex.ToString());
            }
            return;
        }
Esempio n. 13
0
        /// <summary>
        /// When a spell event terminates, we need something to happen.
        /// 
        /// By this point we should have terminated the spell/song event data
        /// and should only need the info about the character and the spell
        /// and the argument(s).
        /// 
        /// Passing of the correct function parameters should be handled by the
        /// event system.
        /// </summary>
        /// <param name="ch">The caster</param>
        /// <param name="spell">The spell number</param>
        /// <param name="target">The _targetType</param>
        public static void FinishSpell( CharData ch, Spell spell, Target target )
        {
            Object obj;
            int chance = 0;
            bool found = false;

            string lbuf = String.Format("Magic.FinishSpell: {0} by {1}", spell.Name, ch.Name);
            Log.Trace( lbuf );

            for( int i = Database.CastList.Count - 1; i >= 0; i--)
            {
                if (Database.CastList[i].Who && Database.CastList[i].Who == ch)
                {
                    Database.CastList.RemoveAt( i );
                }
            }

            // If they're not casting at the end of the song or spell
            // they certainly can't finish it.
            if( ch.IsAffected( Affect.AFFECT_CASTING ) )
                ch.RemoveAffect( Affect.AFFECT_CASTING );
            else
            {
                return;
            }

            if( !ch.CheckConcentration(spell) )
                return;

            if( ( ch.IsAffected( Affect.AFFECT_MUTE ) || ch.HasInnate( Race.RACE_MUTE ) )
                    && !ch.IsClass( CharClass.Names.psionicist ) )
            {
                ch.SendText( "Your lips move but no sound comes out.\r\n" );
                return;
            }

            // Make sure the room is still castable.
            if( !ch.InRoom.CheckCastable( ch, false, false ) )
                return;

            if( ch.InRoom.CheckStarshell( ch ) )
                return;

            MemorizeData memorized = null;
            if (!ch.IsNPC() && !ch.IsImmortal() && !ch.IsClass(CharClass.Names.psionicist))
            {
                foreach( MemorizeData mem in ((PC)ch).Memorized )
                {
                    if( !mem.Memmed )
                        continue;
                    if( mem.Name == spell.Name )
                    {
                        found = true;
                        memorized = mem;
                        break;
                    }
                }

                if (!found && !ch.IsNPC() && !ch.IsClass(CharClass.Names.psionicist))
                {
                    ch.SendText( "You do not have that spell memorized!\r\n" );
                    if( spell.ValidTargets == TargetType.objectOrCharacter )
                        target = null;
                    else if( spell.ValidTargets == TargetType.none )
                        target = null;
                    return;
                }
            }

            if( ch.IsAffected( Affect.AFFECT_FEEBLEMIND ) )
            {
                ch.SendText( "You are just too stupid to cast that spell!\r\n" );
                SocketConnection.Act( "$n&n screws up $s face in concentration.", ch, null, null, SocketConnection.MessageTarget.room );
                SocketConnection.Act( "$n&n tries really, really hard to complete a spell, but fails.", ch, null, null, SocketConnection.MessageTarget.room );
                return;
            }

            // Locate targets.
            CharData victim = null;
            switch( spell.ValidTargets )
            {
                default:
                    Log.Trace( "FinishSpell: bad TargetType for spell {1}.", spell );
                    return;
                case TargetType.objectOrCharacter:
                    if( ch.IsAffected( Affect.AFFECT_BLIND ) )
                    {
                        ch.SendText( "You cannot see to cast that spell.\r\n" );
                        return;
                    }
                    break;
                case TargetType.none:
                    break;
                case TargetType.trap:
                    ch.SendText( "You cannot cast a trap!\r\n" );
                    return;
                case TargetType.singleCharacterOffensive:
                    victim = (CharData)target;

                    if( ch.IsAffected( Affect.AFFECT_BLIND ) )
                    {
                        //allow casting if in combat and no _targetType specified
                        if( !( ch.Fighting && victim == ch.Fighting ) )
                        {
                            ch.SendText( "You cannot see to cast that spell.\r\n" );
                            return;
                        }
                    }
                    if( !victim )
                    {
                        ch.SendText( "They aren't here.\r\n" );
                        return;
                    }
                    if( !victim.InRoom || victim.InRoom != ch.InRoom )
                    {
                        ch.SendText( "They are not here.\r\n" );
                        return;
                    }
                    if( Combat.IsSafe( ch, victim ) )
                        return;
                    // Command.is_safe could wipe out victim, as it calls procs if a boss
                    // check and see that victim is still valid
                    if( !victim )
                        return;

                    Crime.CheckAttemptedMurder( ch, victim );

                    /* Check for globes.  This will stop any spells of type TargetType.singleCharacterOffensive
                    * but area effect spells with type TargetType.none will get through, since we
                    * don't know whether they will be offensive or not.  The only thing we can
                    * really do is add this same thing in the Command.SpellDamage function to prevent
                    * those from getting through.  However, we must treat cases of things like
                    * an area effect sleep spell as a special case within the SpellWhatever
                    * function in Spells.cs.  However, by the nature of the spell, anything
                    * that is not either offensive and not direct damage, it should get through
                    * just so that these spells have some weaknesses for the strategic to get
                    * around.
                    */
                    /*
                    *  TODO: Find out why this globe code was commented out and either uncomment or delete.
                    if( CharData.IsAffected( victim, Affect.AFFECT_MAJOR_GLOBE ) && Spell.Table[spell].spell_circle[ch.cclass] <= 6 )
                    {
                    Descriptor._actFlags( "&+RThe globe around $N&n's body bears the brunt of your assault!&n", ch, null, victim, Descriptor.MessageTarget.character );
                    Descriptor._actFlags( "&+RYour globe deflects $n&+R's attack!&n", ch, null, victim, Descriptor.MessageTarget.victim );
                    Descriptor._actFlags( "&+R$N&+R's globe deflects $n&+R's attack!&n", ch, null, victim, Descriptor.MessageTarget.room );
                    return;
                    }
                    if( CharData.IsAffected( victim, Affect.AFFECT_GREATER_SPIRIT_WARD ) && Spell.Table[spell].spell_circle[ch.cclass] <= 5 )
                    {
                    Descriptor._actFlags( "&+WThe aura around $N&n's body bears the brunt of your assault!&n", ch, null, victim, Descriptor.MessageTarget.character );
                    Descriptor._actFlags( "&+WYour globe absorbs $n&+W's attack!&n", ch, null, victim, Descriptor.MessageTarget.victim );
                    Descriptor._actFlags( "&+W$N&+W's aura absorbs $n&+W's attack!&n", ch, null, victim, Descriptor.MessageTarget.room );
                    return;
                    }
                    if( CharData.IsAffected( victim, Affect.AFFECT_MINOR_GLOBE ) && Spell.Table[spell].spell_circle[ch.cclass] <= 4 )
                    {
                    Descriptor._actFlags( "&+RThe globe around $N&n's body bears the brunt of your assault!&n", ch, null, victim, Descriptor.MessageTarget.character );
                    Descriptor._actFlags( "&+RYour globe deflects $n&+R's attack!&n", ch, null, victim, Descriptor.MessageTarget.victim );
                    Descriptor._actFlags( "&+R$N&+R's globe deflects $n&+R's attack!&n", ch, null, victim, Descriptor.MessageTarget.room );
                    return;
                    }
                    if( CharData.IsAffected( victim, Affect.AFFECT_SPIRIT_WARD ) && Spell.Table[spell].spell_circle[ch.cclass] <= 3 )
                    {
                    Descriptor._actFlags( "&+WThe aura around $N&n's body bears the brunt of your assault!&n", ch, null, victim, Descriptor.MessageTarget.character );
                    Descriptor._actFlags( "&+WYour globe absorbs $n&+W's attack!&n", ch, null, victim, Descriptor.MessageTarget.victim );
                    Descriptor._actFlags( "&+W$N&+W's aura absorbs $n&+W's attack!&n", ch, null, victim, Descriptor.MessageTarget.room );
                    return;
                    }
                    */
                    break;
                case TargetType.singleCharacterWorld:
                    victim = (CharData)target;

                    if( ch.IsAffected( Affect.AFFECT_BLIND ) && victim != ch )
                    {
                        ch.SendText( "You cannot see to cast that spell.\r\n" );
                        return;
                    }
                    break;
                case TargetType.singleCharacterDefensive:
                    victim = (CharData)target;

                    if( ch.IsAffected( Affect.AFFECT_BLIND ) && victim != ch )
                    {
                        ch.SendText( "You cannot see to cast that spell.\r\n" );
                        return;
                    }
                    if( !victim || victim.InRoom != ch.InRoom )
                    {
                        ch.SendText( "They aren't here.\r\n" );
                        return;
                    }
                    break;
                case TargetType.self:
                    break;
                case TargetType.objectInInventory:
                    obj = (Object)target;

                    if( ch.IsAffected( Affect.AFFECT_BLIND ) )
                    {
                        ch.SendText( "You cannot see to cast that spell.\r\n" );
                        return;
                    }
                    if( !obj || obj.CarriedBy != ch )
                    {
                        ch.SendText( "You are not carrying that.\r\n" );
                        return;
                    }
                    break;
                case TargetType.objectInRoom:
                    obj = (Object)target;

                    if( ch.IsAffected( Affect.AFFECT_BLIND ) )
                    {
                        ch.SendText( "You cannot see to cast that spell.\r\n" );
                        return;
                    }
                    if( !obj || ( obj.CarriedBy != ch && obj.InRoom != ch.InRoom ) )
                    {
                        ch.SendText( "You do not see that here.\r\n" );
                        return;
                    }
                    break;
                case TargetType.objectCorpse:
                    break;
                case TargetType.singleCharacterRanged:
                    victim = (CharData)target;
                    if( ch.IsAffected( Affect.AFFECT_BLIND ) )
                    {
                        ch.SendText( "You cannot see to cast that spell.\r\n" );
                        return;
                    }
                    if( !victim
                            || victim.FlightLevel != ch.FlightLevel
                            || !CharData.CanSee( ch, victim ) )
                    {
                        ch.SendText( "Your prey has disappeared.\r\n" );
                        return;
                    }
                    //check that _targetType is still within the spell range
                    if( ch.InRoom == victim.InRoom )
                    {
                        break;
                    }
                    bool targetInRange = false;
                    int dir;
                    for( dir = 0; dir < Limits.MAX_DIRECTION; dir++ )
                    {
                        if( !ch.InRoom.ExitData[ dir ]
                                || ch.InRoom.ExitData[ dir ].HasFlag( Exit.ExitFlag.secret )
                                || ch.InRoom.ExitData[ dir ].HasFlag( Exit.ExitFlag.closed )
                                || ch.InRoom.ExitData[ dir ].HasFlag( Exit.ExitFlag.blocked )
                                || ch.InRoom.ExitData[dir].HasFlag(Exit.ExitFlag.walled))
                            continue;
                        if( ch.InRoom.ExitData[ dir ].TargetRoom == victim.InRoom )
                        {
                            targetInRange = true;
                            break;
                        }
                        // for fireball we check two rooms away
                        if( ch.InRoom.ExitData[ dir ].TargetRoom &&
                                ch.InRoom.ExitData[ dir ].TargetRoom.ExitData[ dir ]
                                && ch.InRoom.ExitData[ dir ].TargetRoom.ExitData[ dir ].TargetRoom == victim.InRoom )
                        {
                            targetInRange = true;
                            break;
                        }
                    }
                    if( !targetInRange )
                    {
                        ch.SendText( "They are no longer in range!\r\n" );
                        return;
                    }
                    break;
                }

            // No wait state - we already made them wait.
            ch.PracticeSpell( spell );

            if (ch.IsNPC())
            {
                chance = 85;
            }
            else if (ch.HasSpell(spell.Name))
            {
                chance = ((PC)ch).SpellAptitude[spell.Name];
            }

            if( !ch.IsImmortal() && ( MUDMath.NumberPercent() > chance ) )
            {
                ch.SendText( "You lost your concentration.\r\n" );
                SocketConnection.Act( "&+r$n&n&+r stops chanting abruptly.&n", ch, null, null, SocketConnection.MessageTarget.room );
            }
            else
            {
                // TODO: Figure out whether this should be re-enabled.
                //if( song )
                //{
                //    ch.SendText( "You complete a verse of the song...\r\n" );
                //    ch.GainExperience( 1 );
                //    SaySong( ch, spell );
                //}
                //else
                {
                    if (!ch.IsClass(CharClass.Names.psionicist))
                    {
                        ch.SendText( "You complete your spell...\r\n" );
                        if( MUDString.StringsNotEqual( spell.Name, "ventriloquate" ) )
                            SaySpell( ch, spell );
                    }
                    ch.GainExperience( 1 );
                }
                if( !ch.IsNPC() )
                {
                    string buf = String.Format( "Spell ({0}) being cast by {1}", spell.Name, ch.Name );
                    Log.Trace( buf );
                }

                int level = Macros.Range(1, ch.Level, Limits.LEVEL_HERO);
                spell.Invoke(ch, level, target);

                if( memorized && !ch.IsNPC() && !ch.IsImmortal() )
                {
                    memorized.Memmed = false;
                    memorized.Memtime = memorized.FullMemtime;
                }
            }

            if( ( spell.ValidTargets == TargetType.singleCharacterOffensive
                    || spell.ValidTargets == TargetType.singleCharacterRanged )
                    && victim && victim.Master != ch && victim != ch && victim.IsAwake() )
            {
                if( ch.InRoom == victim.InRoom )
                {
                    if( !victim.Fighting && CharData.CanSee( victim, ch ) )
                        victim.AttackCharacter( ch );
                }
                else
                {
                    // Range spell presumably, since different rooms
                    Combat.StartGrudge( victim, ch, true );
                    foreach( CharData roomChar in ch.InRoom.People )
                    {
                        if( roomChar == victim )
                            continue;
                        if( roomChar.FlightLevel != ch.FlightLevel )
                            continue;
                        //protectors will be aggro'd
                        if (roomChar.HasActionBit(MobTemplate.ACT_PROTECTOR) && (roomChar.GetRace() == victim.GetRace()))
                        {
                            Combat.StartGrudge( roomChar, ch, true );
                        }
                        // all aggro mobs will hunt down caster
                        if (roomChar.HasActionBit(MobTemplate.ACT_AGGRESSIVE))
                        {
                            Combat.StartGrudge(roomChar, ch, true);
                        }
                    }
                }
            }
            return;
        }
Esempio n. 14
0
        public static void Chameleon(CharData ch, string[] str)
        {
            if( ch == null ) return;
            if (!ch.IsNPC() && !ch.HasSkill("chameleon power"))
            {
                ch.SendText("You don't know how to act like a chameleon.\r\n");
                return;
            }

            ch.SendText("You attempt to blend in with your surroundings.\r\n");

            if (ch.IsAffected(Affect.AFFECT_HIDE))
            {
                ch.RemoveAffect(Affect.AFFECT_HIDE);
            }

            if (ch.CheckSkill("chameleon power"))
            {
                ch.SetAffectBit(Affect.AFFECT_HIDE);
            }

            return;
        }
Esempio n. 15
0
        /// <summary>
        /// Set ch as fighting victim.
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="victim"></param>
        public static void SetFighting( CharData ch, CharData victim )
        {
            if( ch == victim )
                return;

            if( ch.Fighting )
            {
                Log.Error( "Set_fighting: already fighting", 0 );
                string buf = String.Format( "...{0} attacking {1} at {2}",
                                            ( ch.IsNPC() ? ch.ShortDescription : ch.Name ),
                                            ( victim.IsNPC() ? victim.ShortDescription : victim.Name ),
                                            victim.InRoom.IndexNumber );
                Log.Error( buf, 0 );
                return;
            }

            if (ch.IsAffected(Affect.AFFECT_SLEEP))
            {
                ch.RemoveAffect(Affect.AFFECT_SLEEP);
            }

            if( ch.FlightLevel != victim.FlightLevel )
            {
                StartGrudge( ch, victim, false );
                return;
            }

            ch.Fighting = victim;
            if( ch.CurrentPosition == Position.standing )
                ch.CurrentPosition = Position.fighting;

            return;
        }
Esempio n. 16
0
        /// <summary>
        /// Command to climb something.
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="str"></param>
        public static void Climb(CharData ch, string[] str)
        {
            if( ch == null ) return;

            int chance;

            if (!ch.HasSkill("climb"))
            {
                ch.SendText("You lack the skills to climb anything.\r\n");
                return;
            }

            if (str.Length == 0)
            {
                ch.SendText("Climb what?\r\n");
                return;
            }

            Object obj = ch.GetObjHere(str[0]);
            if (!obj)
            {
                ch.SendText("Uhh... what exactly did you want to climb!?\r\n");
                return;
            }

            if (obj.ItemType != ObjTemplate.ObjectType.wall)
            {
                ch.SendText("That wasn't exactly designed for climbing.\r\n");
                return;
            }

            if (ch.IsNPC())
            {
                chance = ch.Level * 3 / 2 + 20;
            }
            else
            {
                chance = ((PC)ch).SkillAptitude["climb"];
            }

            // Agility helps.
            chance += ch.GetCurrAgi() / 10;

            switch (obj.ObjIndexData.IndexNumber)
            {
                case StaticObjects.OBJECT_NUMBER_WALL_STONE:
                    chance += 5;
                    break;
                case StaticObjects.OBJECT_NUMBER_WALL_IRON:
                    chance -= 15;
                    break;
                default:
                    ch.SendText("That wasn't exactly designed for climbing.\r\n");
                    return;
            }

            // Maximum chance of 98%
            if (chance > 98)
            {
                chance = 98;
            }

            if (MUDMath.NumberPercent() >= chance)
            {
                ch.SendText("You try to climb it, but you fall on your ass!\r\n");
                ch.CurrentPosition = Position.sitting;
                ch.WaitState(5);
                return;
            }

            ch.SendText("With great skill, you scale the wall!\r\n");

            // Value 0 of a wall object is the direction that has been walled...
            // This means that they should move in that direction.  We leave it up to
            // move_char to make sure that there is actually an exit in that direction.
            // we use the climbing bit to allow them to pass the walls in move_char.
            ch.SetAffectBit(Affect.AFFECT_CLIMBING);
            ch.Move((Exit.Direction)obj.Values[0]);
            ch.RemoveAffect(Affect.AFFECT_CLIMBING);

            return;
        }
Esempio n. 17
0
        public static void Berzerk(CharData ch, string[] str)
        {
            if( ch == null ) return;

            Affect af = new Affect();

            /* Don't allow charmed mobs to do this, check player's level */
            if ((ch.IsNPC() && ch.IsAffected( Affect.AFFECT_CHARM))
                    || (!ch.IsNPC() && !ch.HasSkill("berzerk")))
            {
                ch.SendText("You're not enough of a warrior to enter a &+RBl&n&+ro&+Ro&n&+rd&+L Rage&n.\r\n");
                return;
            }

            if (ch.IsAffected(Affect.AFFECT_BERZERK))
            {
                if (MUDMath.NumberPercent() + 10 > ((PC)ch).SkillAptitude["berzerk"])
                {
                    ch.SendText("You failed to calm yourself down!\r\n");
                    ch.WaitState(Skill.SkillList["berzerk"].Delay);
                    return;
                }
                ch.SendText("You no longer see targets everywhere.\r\n");
                ch.RemoveAffect(Affect.AFFECT_BERZERK);
                ch.WaitState(Skill.SkillList["berzerk"].Delay);
                return;
            }

            ch.SendText("Your slam your weapon into yourself and &+Rbl&n&+ro&+Ro&n&+rd&n splatters all over!\r\n");
            ch.SendText("The sight of &+Rbl&n&+ro&+Ro&n&+rd&n begins to drive you crazy!\r\n");

            if (ch.CheckSkill("berzerk"))
            {
                af.Value = "berzerk";
                af.Type = Affect.AffectType.skill;
                af.Duration = MUDMath.Dice(1, 2);
                af.AddModifier( Affect.Apply.hitroll, Math.Max(ch.Level / 6, 2));
                af.AddModifier( Affect.Apply.damroll, Math.Max(ch.Level / 6, 2));
                af.AddModifier( Affect.Apply.ac, (ch.Level / 2));
                af.AddModifier( Affect.Apply.max_constitution, MUDMath.Dice(5, 9));
                af.AddModifier( Affect.Apply.agility, 0 - MUDMath.Dice(5, 9));
                af.AddModifier( Affect.Apply.max_strength, MUDMath.Dice(5, 9));
                af.SetBitvector(Affect.AFFECT_BERZERK);
                ch.AddAffect(af);

                ch.SendText("You are overcome by &+RBl&n&+ro&+Ro&n&+rd&+L Rage&n!!\r\n");
                SocketConnection.Act("$n has slipped into a &+RBl&n&+ro&+Ro&n&+rd&+L Rage&n!!", ch, null, null, SocketConnection.MessageTarget.room);

                return;
            }
            ch.SendText("You get a little angry, but fail to call up a &+Rblood rage&n.\r\n");

            return;
        }
Esempio n. 18
0
        /// <summary>
        /// Hide yourself or an object.
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="str"></param>
        public static void Hide(CharData ch, string[] str)
        {
            if( ch == null ) return;
            /* Check player's skill */
            if (!ch.HasSkill("hide"))
            {
                if(str.Length != 0)
                {
                    HideItem(ch, new[] { str[0] });
                    return;
                }
                ch.SendText("You're far too obvious to hide anywhere.\r\n");
                return;
            }

            if (ch.Riding)
            {
                ch.SendText("You can't do that while mounted.\r\n");
                return;
            }

            if (ch.CurrentPosition <= Position.sleeping)
            {
                return;
            }
            ch.SendText("You attempt to hide.\r\n");

            if (ch.IsAffected(Affect.AFFECT_HIDE))
            {
                ch.RemoveAffect(Affect.AFFECT_HIDE);
            }

            if (ch.CheckSkill("hide"))
            {
                ch.SetAffectBit(Affect.AFFECT_HIDE);
            }

            ch.WaitState(12);

            return;
        }
Esempio n. 19
0
        /// <summary>
        /// Sing -- using a bard song without an instrument.
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="str"></param>
        public static void Sing(CharData ch, string[] str)
        {
            if( ch == null ) return;

            if (!ch.IsClass(CharClass.Names.bard) && !ch.IsImmortal())
            {
                ch.SendText("You don't know how to sing.\r\n");
                return;
            }

            if (ch.IsAffected(Affect.AFFECT_MINOR_PARA) ||
                    ch.IsAffected(Affect.AFFECT_HOLD))
            {
                ch.SendText("You can't Sing when you're paralyzed!\r\n");
                return;
            }

            if (ch.HasActionBit(Affect.AFFECT_MUTE))
            {
                ch.SendText("You have no voice!\r\n");
                return;
            }

            if (str.Length == 0)
            {
                if (ch.IsAffected(Affect.AFFECT_SINGING))
                {
                    ch.RemoveAffect(Affect.AFFECT_SINGING);
                    ch.SendText("You stop singing.\r\n");
                }
                else
                {
                    ch.SendText("Sing what?\r\n");
                }
                return;
            }

            Magic.Cast(ch, String.Join(" ", str));
        }
Esempio n. 20
0
        /// <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());
            }
        }
Esempio n. 21
0
        /// <summary>
        /// The main social action processing routine.  Sends the social strings and any associated sounds.
        /// </summary>
        /// <param name="ch">Character acting out the social.</param>
        /// <param name="command">Command entered by the character.</param>
        /// <param name="argument">Additional modifiers to the command entered.</param>
        /// <returns></returns>
        public bool CheckSocial(CharData ch, string command, string argument)
        {
            string arg = String.Empty;

            Social soc = FindSocial(command);
            if (soc == null)
            {
                return false;
            }

            if (!ch.IsNPC() && ch.HasActionBit(PC.PLAYER_NO_EMOTE))
            {
                ch.SendText("You are anti-social!\r\n");
                return true;
            }

            if (!ch.IsNPC() && ch.HasActionBit(PC.PLAYER_MEDITATING))
            {
                ch.RemoveActionBit(PC.PLAYER_MEDITATING);
                ch.SendText("You stop meditating.\r\n");
            }

            // Performing a social action removes hide and conceal.
            if (ch.IsAffected(Affect.AFFECT_MINOR_INVIS))
            {
                ch.SendText("You appear.\r\n");
            }
            ch.AffectStrip(Affect.AffectType.skill, "shadow form");
            ch.AffectStrip(Affect.AffectType.spell, "concealment");
            ch.RemoveAffect(Affect.AFFECT_MINOR_INVIS);
            ch.RemoveAffect(Affect.AFFECT_HIDE);

            switch (ch.CurrentPosition)
            {
                case Position.dead:
                    ch.SendText("Lie still; you are DEAD.\r\n");
                    return true;

                case Position.incapacitated:
                case Position.mortally_wounded:
                    ch.SendText("You are hurt far too badly for that.\r\n");
                    return true;

                case Position.stunned:
                    ch.SendText("You are too stunned to do that.\r\n");
                    return true;

                case Position.sleeping:
                    // Special exception - only social when you're using when asleep is "snore".
                    if (!"snore".StartsWith(soc.Name, StringComparison.CurrentCultureIgnoreCase))
                    {
                        break;
                    }
                    ch.SendText("In your dreams, or what?\r\n");
                    return true;

            }

            MUDString.OneArgument(argument, ref arg);
            CharData victim = null;
            if (arg.Length == 0)
            {
                SocketConnection.Act(soc.CharNoArgument, ch, null, victim, SocketConnection.MessageTarget.character);
                SocketConnection.Act(soc.OthersNoArgument, ch, null, victim, SocketConnection.MessageTarget.room);
                if (!String.IsNullOrEmpty(soc.AudioFile) && ch.InRoom != null)
                {
                    foreach (CharData cd in ch.InRoom.People)
                    {
                        cd.SendSound(soc.AudioFile);
                    }
                }
                return true;
            }
            victim = ch.GetCharWorld(arg);
            if (!victim || (ch.IsRacewar(victim) && ch.InRoom != victim.InRoom))
            {
                ch.SendText("They aren't here.\r\n");
            }
            else if (victim == ch)
            {
                SocketConnection.Act(soc.CharSelf, ch, null, victim, SocketConnection.MessageTarget.character);
                SocketConnection.Act(soc.OthersSelf, ch, null, victim, SocketConnection.MessageTarget.room);
                if (!String.IsNullOrEmpty(soc.AudioFile) && ch.InRoom != null)
                {
                    foreach (CharData cd in ch.InRoom.People)
                    {
                        cd.SendSound(soc.AudioFile);
                    }
                }
            }
            else if (!ch.GetCharRoom(arg) && CharData.CanSee(ch, victim)
                      && soc.CharFound.Length > 0 && soc.VictimFound.Length > 0)
            {
                if (!ch.IsImmortal())
                {
                    ch.SendText("You don't see them here.\r\n");
                    return true;
                }
                if (!victim.IsNPC())
                {
                    const string ldbase = "From far away, ";

                    if (victim.IsIgnoring(ch))
                    {
                        ch.SendText("They are ignoring you.\r\n");
                        return false;
                    }
                    Room original = ch.InRoom;
                    ch.RemoveFromRoom();
                    ch.AddToRoom(victim.InRoom);

                    string ldmsg = ldbase;
                    ldmsg += soc.CharFound;
                    SocketConnection.Act(ldmsg, ch, null, victim, SocketConnection.MessageTarget.character);

                    ldmsg = ldbase;
                    ldmsg += soc.VictimFound;
                    SocketConnection.Act(ldmsg, ch, null, victim, SocketConnection.MessageTarget.victim);

                    if (!String.IsNullOrEmpty(soc.AudioFile) && ch.InRoom != null)
                    {
                        foreach (CharData cd in ch.InRoom.People)
                        {
                            cd.SendSound(soc.AudioFile);
                        }
                    }

                    ch.RemoveFromRoom();
                    ch.AddToRoom(original);

                }
                else
                {
                    ch.SendText("They aren't here.\r\n");
                }
            }
            else
            {
                SocketConnection.Act(soc.CharFound, ch, null, victim, SocketConnection.MessageTarget.character);
                SocketConnection.Act(soc.VictimFound, ch, null, victim, SocketConnection.MessageTarget.victim);
                SocketConnection.Act(soc.OthersFound, ch, null, victim, SocketConnection.MessageTarget.everyone_but_victim);
                if (!String.IsNullOrEmpty(soc.AudioFile) && ch.InRoom != null)
                {
                    foreach (CharData cd in ch.InRoom.People)
                    {
                        cd.SendSound(soc.AudioFile);
                    }
                }

                // If mobs are to respond to socials, it should be inserted here.
                // This might be useful for some quests, mob functions, or other things.
            }

            return true;
        }