Exemple #1
0
        /// <summary>
        /// Recoding of the WearObject function into a table-based system which is fairly
        /// complex, but easy to maintain via the table. Bitshifting is used to check
        /// each wear location for a piece of equipment.
        /// 
        /// (not enabled)
        /// 
        /// TODO: Enable/finish this or remove it. See WearObject for what it is intended
        /// to replace.
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="obj"></param>
        /// <param name="replaceExisting"></param>
        static void NewWearObject(CharData ch, ref Object obj, bool replaceExisting)
        {
            int count;

            for (count = 0; count < WearData.Table.Length; ++count)
            {
                if (obj.HasWearFlag(new Bitvector(0, (1 << count))))
                {
                    if (WearData.Table[count].BodyPartNeeded == 0 ||
                            Macros.IsSet((int)Race.RaceList[ch.GetRace()].BodyParts, WearData.Table[count].BodyPartNeeded))
                    {
                        if (WearData.Table[count].RacesNotAllowed == -1 ||
                                ch.GetRace() != WearData.Table[(1 << count)].RacesNotAllowed)
                        {
                            bool found = false;
                            int wearLoc = 0;
                            foreach (int wear in WearData.Table[count].WearLocations)
                            {
                                if (wear != 0 && !ch.RemoveObject((ObjTemplate.WearLocation)wear, replaceExisting))
                                {
                                    continue;
                                }
                                wearLoc = wear;
                                found = true;
                                break;
                            }
                            if (!found)
                            {
                                return;
                            }
                            SocketConnection.Act(WearData.Table[(1 << count)].WearMessageToWearer, ch, obj, null, SocketConnection.MessageTarget.character);
                            SocketConnection.Act(WearData.Table[(1 << count)].WearMessageToRoom, ch, obj, null, SocketConnection.MessageTarget.room);
                            // Need to allow for multiple wear locations rather than just picking the first one.
                            ch.EquipObject(ref obj, (ObjTemplate.WearLocation)wearLoc);
                            return;

                        }
                        ch.SendText("Your race cannot wear that type of equipment.\r\n");
                        return;
                    }
                    ch.SendText("The design of your body prevents you from using that.\r\n");
                    return;
                }
            }
        }
Exemple #2
0
        /// <summary>
        /// Springleap.  Can be used to initiate combat and can be used during combat.
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="str"></param>
        public static void Springleap(CharData ch, string[] str)
        {
            if( ch == null ) return;

            int chance;

            /* Check player's level and class, mobs can use this skill */
            if ((!ch.HasSkill("springleap")))
            {
                ch.SendText("You'd better leave the martial arts to Bruce Lee.\r\n");
                return;
            }

            if (ch.GetRace() == Race.RACE_CENTAUR)
            {
                ch.SendText("Your anatomy prevents you from springleaping.\r\n");
                return;
            }

            if (ch.IsBlind())
            {
                return;
            }

            CharData victim = ch.Fighting;

            if (str.Length != 0)
            {
                if (!(victim = ch.GetCharRoom(str[0])) || victim.CurrentPosition == Position.dead)
                {
                    ch.SendText("You don't see them here.\r\n");
                    return;
                }
            }
            else
            {
                if (!victim || victim.CurrentPosition == Position.dead)
                {
                    ch.SendText("You aren't fighting anyone.\r\n");
                    return;
                }
            }

            /* springleap self */
            if (ch == victim)
            {
                ch.SendText("You can't quite figure out how to do that.\r\n");
                return;
            }

            /* Check size of ch vs. victim. */
            /* If ch is too small. */
            if (ch.CurrentSize - 2 > victim.CurrentSize)
            {
                SocketConnection.Act("Your acrobatic maneuver cannot accurately leap into such a small being.", ch, null, victim, SocketConnection.MessageTarget.character);
                return;
            }
            /* Ch 2 or more sizes larger than victim => bad! */
            if (ch.CurrentSize + 2 < victim.CurrentSize)
            {
                SocketConnection.Act("Your acrobatic maneuver does not seem to work on someone so large.", ch, null, victim, SocketConnection.MessageTarget.character);
                SocketConnection.Act("$n&n jumps into you, and slides down your leg.", ch, null, victim, SocketConnection.MessageTarget.victim);
                SocketConnection.Act("$n&n jumps into $N&n and slides down $S leg.", ch, null, victim, SocketConnection.MessageTarget.room_vict);

                ch.WaitState(Skill.SkillList["springleap"].Delay);
                ch.CurrentPosition = Position.reclining;
                if (victim.Fighting == null)
                {
                    Combat.SetFighting(victim, ch);
                }
                return;
            }

            ch.WaitState(MUDMath.FuzzyNumber(Skill.SkillList["springleap"].Delay));
            ch.PracticeSkill("springleap");

            if (ch.IsNPC())
            {
                chance = (ch.Level * 3) / 2 + 15;
            }
            else
            {
                chance = ((PC)ch).SkillAptitude["springleap"] - 5;
            }

            if (chance > 95)
            {
                chance = 95;
            }

            if (victim.CurrentPosition < Position.fighting)
            {
                chance /= 4;
            }

            if (MUDMath.NumberPercent() < chance)
            {
                ch.CurrentPosition = Position.fighting;
                SocketConnection.Act("&+WYour springleap knocks $N&n&+W on $S butt.&n", ch, null, victim, SocketConnection.MessageTarget.character);
                SocketConnection.Act("&+W$n&n&+W leaps gracefully at $N&n&+W, sending $M to the ground.&n", ch, null, victim, SocketConnection.MessageTarget.room);
                SocketConnection.Act("&+W$n&n&+W leaps at you, knocking you to the ground!&n", ch, null, victim, SocketConnection.MessageTarget.victim);
                if (victim.IsAffected(Affect.AFFECT_SINGING))
                {
                    victim.RemoveAffect(Affect.AFFECT_SINGING);
                    SocketConnection.Act("$n&n gasps and falls silent as $e falls over backward!", victim, null, null, SocketConnection.MessageTarget.room);
                    victim.SendText("You abort your singing!\r\n");
                }
                if (victim.IsAffected(Affect.AFFECT_CASTING))
                {
                    victim.RemoveAffect(Affect.AFFECT_CASTING);
                    SocketConnection.Act("$n&n no longer has any idea what $e was casting.", victim, null, null, SocketConnection.MessageTarget.room);
                    victim.SendText("Lying on the ground, you realize you have no idea what you were just casting.\r\n");
                }

                if (!ch.Fighting)
                {
                    Combat.SetFighting(ch, victim);
                }
                if (!victim.Fighting)
                {
                    Combat.SetFighting(victim, ch);
                }
                if (!Combat.CheckTumble(victim))
                {
                    victim.WaitState((Skill.SkillList["springleap"].Delay * 5 / 6));
                    if (victim.CurrentPosition > Position.sitting)
                    {
                        victim.CurrentPosition = Position.sitting;
                    }
                    Combat.InflictDamage(ch, victim, MUDMath.NumberRange(1, ch.Level), "springleap", ObjTemplate.WearLocation.none, AttackType.DamageType.bludgeon);
                }
                else
                {
                    Combat.InflictDamage(ch, victim, MUDMath.NumberRange(1, (ch.Level / 3)), "springleap", ObjTemplate.WearLocation.none, AttackType.DamageType.bludgeon);
                    ch.SendText("You roll with the blow, finally landing on your feet.\r\n");
                    SocketConnection.Act("$n&n rolls with the blow, finally landing on $s feet.", victim, null, null, SocketConnection.MessageTarget.room);
                }
            }
            else
            {
                bool pissedOff = false;
                if (ch.Fighting == victim || victim.GetCurrInt() > MUDMath.NumberPercent())
                {
                    pissedOff = true;
                }
                if (pissedOff)
                {
                    SocketConnection.Act("As $N&n avoids your leap you crash to the ground.", ch, null, victim, SocketConnection.MessageTarget.character);
                    SocketConnection.Act("$n&n crashes to the ground as you avoid $s springleap.", ch, null, victim, SocketConnection.MessageTarget.victim);
                    if (!ch.Fighting)
                    {
                        Combat.SetFighting(ch, victim);
                    }
                    if (!victim.Fighting)
                    {
                        Combat.SetFighting(victim, ch);
                    }
                }
                else
                {
                    SocketConnection.Act("You ungracefully leap at $N and miss, landing head first!", ch, null, victim, SocketConnection.MessageTarget.character);
                }
                SocketConnection.Act("$n&n misses a springleap and falls awkwardly to the ground.", ch, null, null, SocketConnection.MessageTarget.room);
                ch.CurrentPosition = Position.reclining;
                Combat.InflictDamage(ch, ch, MUDMath.NumberRange(1, 4), "springleap",
                        ObjTemplate.WearLocation.none, AttackType.DamageType.bludgeon);
            }

            return;
        }
Exemple #3
0
        /// <summary>
        /// Shows a character's attribute screen.
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="str"></param>
        public static void Attributes(CharData ch, string[] str)
        {
            if( ch == null ) return;

            string buf1 = String.Empty;

            if (ch.IsNPC())
            {
                ch.SendText("&nYour attributes are as would be expected for an NPC.\r\n");
                return;
            }

            if (ch.IsImmortal() && str.Length != 0)
            {
                CharData worldChar = ch.GetCharWorld(str[0]);
                if (!worldChar)
                {
                    ch.SendText("No such person.\r\n");
                    return;
                }
                if (worldChar.IsNPC())
                {
                    ch.SendText("NPCs don't have skills!\r\n");
                    return;
                }
            }

            string buf = String.Format(
                "&+WName: &+G{0}&n    &+WLevel: {1}&n\r\n",
                MUDString.PadStr(ch.Name, 17),
                ch.Level);
            buf1 += buf;

            buf = String.Format(
                      "&+WRace:&n {0}          &+WClass:&n {1}     &n&+WSex:&n {2}\r\n",
                      MUDString.PadStr(Race.RaceList[ch.GetRace()].ColorName, 16),
                      MUDString.PadStr(ch.CharacterClass.WholistName, 16),
                      System.Threading.Thread.CurrentThread.CurrentCulture.TextInfo.ToTitleCase(ch.GetSexString()));
            buf1 += buf;

            // Break a player's size into strings when we get around to it
            // -- Xangis
            if (!ch.IsNPC())
            {
                buf = String.Format(
                          "&+WHeight:&n {0} inches         &+WWeight:&n {1} pounds    &+WSize:&n {2}\r\n",
                          MUDString.PadInt(((PC)ch).Height, 3),
                          MUDString.PadInt(((PC)ch).Weight, 5),
                          Race.SizeString(ch.CurrentSize));
            }
            else
            {
                buf = String.Format("&+WSize:&n  {0}\r\n", ch.CurrentSize);
            }
            buf1 += buf;

            TimeSpan time = TimeSpan.FromTicks(ch.TimePlayed.Ticks) + (DateTime.Now - ch.LogonTime);
            int days = (int)time.TotalHours / 24;
            time = (time - TimeSpan.FromDays(days));
            int hours = (int)time.TotalHours;
            time = (time - TimeSpan.FromHours(hours));
            int minutes = (int)time.TotalMinutes;

            // Age is a hack until we get it coded - Xangis
            buf = String.Format(
                      "\r\n&+BAge:&n {0} years.             &+BPlaying Time:&n {1} days {2} hours {3} minutes.\r\n",
                      MUDString.PadInt(ch.GetAge(), 3), days, hours, minutes);
            buf1 += buf;

            // Need to create a function to display character status strings
            buf = String.Format("&+BStatus:&n  {0}", System.Threading.Thread.CurrentThread.CurrentCulture.TextInfo.ToTitleCase(Position.PositionString(ch.CurrentPosition)));
            if (!ch.IsNPC() && ch.IsAffected(Affect.AFFECT_BERZERK))
            {
                buf += ", &+Rberzerk&n";
            }
            if (!ch.IsNPC() && ch.HasActionBit(PC.PLAYER_MEMORIZING))
            {
                buf += ", Memorizing";
            }
            if (ch.IsAffected(Affect.AFFECT_CASTING))
            {
                buf += ", Casting";
            }
            if (ch.IsAffected(Affect.AFFECT_SINGING))
            {
                buf += ", Singing";
            }
            if (!ch.IsNPC() && ch.HasActionBit(PC.PLAYER_MEDITATING))
            {
                buf += ", Meditating";
            }
            if (!ch.IsNPC() && ch.HasActionBit(PC.PLAYER_CAMPING))
            { /* This is ugly and should be moved to its own function */
                buf += ", Camping";
            }
            buf += ".\r\n\r\n";
            buf1 += buf;

            // We want players to see the same stats for levels 1-50.

            // Should create string converters so that we have no decimals displayed
            // below this point.
            buf = String.Format("     &+cSTR:&n  {0}      &+cArmor Class:&n {1}.\r\n",
                      MUDString.PadStr(StringConversion.AbilityScoreString(ch.GetCurrStr()), 15), ch.GetAC());
            buf1 += buf;
            buf = String.Format("     &+cAGI:&n  {0}      &+cHitroll:&n     {1}\r\n",
                      MUDString.PadStr(StringConversion.AbilityScoreString(ch.GetCurrAgi()), 15), StringConversion.BonusString(ch.GetHitroll(ObjTemplate.WearLocation.hand_one)));
            buf1 += buf;
            buf = String.Format("     &+cDEX:&n  {0}      &+cDamroll:&n     {1}\r\n",
                      MUDString.PadStr(StringConversion.AbilityScoreString(ch.GetCurrDex()), 15), StringConversion.BonusString(ch.GetDamroll(ObjTemplate.WearLocation.hand_one)));
            buf1 += buf;
            buf = String.Format("     &+cCON:&n  {0}      &+cAlignment:&n   {1}\r\n",
                      MUDString.PadStr(StringConversion.AbilityScoreString(ch.GetCurrCon()), 15), StringConversion.AlignmentString(ch));
            buf1 += buf;
            buf = String.Format("     &n&+cINT:&n  {0}\r\n", MUDString.PadStr(StringConversion.AbilityScoreString(ch.GetCurrInt()), 15));
            buf1 += buf;
            buf = String.Format("     &+cWIS:&n  {0}      &+BSaving Throws&n\r\n",
                      MUDString.PadStr(StringConversion.AbilityScoreString(ch.GetCurrWis()), 15));
            buf1 += buf;
            buf = String.Format("     &+cPOW:&n  {0}      &+cParalysis:&n {1}\r\n",
                      MUDString.PadStr(StringConversion.AbilityScoreString(ch.GetCurrPow()), 15), StringConversion.BonusString(-ch.SavingThrows[0]));
            buf1 += buf;
            buf = String.Format("     &+cCHA:&n  {0}      &+cRod:&n       {1}\r\n",
                      MUDString.PadStr(StringConversion.AbilityScoreString(ch.GetCurrCha()), 15), StringConversion.BonusString(-ch.SavingThrows[1]));
            buf1 += buf;
            buf = String.Format("     &+cLUK:&n  {0}      &+cPetrify:&n   {1}\r\n",
                      MUDString.PadStr(StringConversion.AbilityScoreString(ch.GetCurrLuck()), 15), StringConversion.BonusString(-ch.SavingThrows[2]));
            buf1 += buf;

            buf = String.Format("                                &+cBreath:&n    {0}\r\n",
                      StringConversion.BonusString(-ch.SavingThrows[3]));
            buf1 += buf;

            buf = String.Format("&+BWimpy:        &n{0}               &+cSpell:&n     {1}\r\n",
                      MUDString.PadInt(ch.Wimpy, 4), StringConversion.BonusString(-ch.SavingThrows[4]));
            buf1 += buf;

            buf = String.Format("&+BLoad Carried: &n{0} pounds ({1})\r\n",
                      MUDString.PadInt(ch.CarryWeight, 3), StringConversion.WeightString(ch));
            buf1 += buf;

            ch.SendText(buf1);
            return;
        }
Exemple #4
0
        /// <summary>
        /// Shows a character's score screen.
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="str"></param>
        public static void Score(CharData ch, string[] str)
        {
            if( ch == null ) return;

            string text = String.Empty;

            if (ch == null)
            {
                Log.Error("Command.Score(): null ch.", 0);
                return;
            }

            Affect prev;

            text += "&+WName: &+G" + ch.Name + "&n" + (ch.IsNPC() ? String.Empty : ((PC)ch).Title) + "\r\n";
            text += "&+WRace:&n " + MUDString.PadStr(Race.RaceList[ch.GetRace()].ColorName, 16);
            text += "&+WClass:&n " + MUDString.PadStr(ch.CharacterClass.WholistName, 32) + "&n\r\n";
            text += "&+WLevel: " + MUDString.PadInt(ch.Level, 5) + "     Played: " + (ch.TimePlayed.Hours) + " hours       &+WSex: ";
            text += System.Threading.Thread.CurrentThread.CurrentCulture.TextInfo.ToTitleCase(ch.GetSexString()) + "\r\n";
            if (ch.Fighting == null)
            {
                text += "&+WExperience: &+B" + StringConversion.ExperienceString(ch) + "&n\r\n\r\n";
            }
            text += "&+WCurrent/Max Health: [&n&+g" + MUDString.PadInt(ch.Hitpoints, 5) + "&+W / &n&+g" + MUDString.PadInt(ch.GetMaxHit(), 5);
            text += "&+W]     Coins:     Carried     In Bank\r\n";
            text += "&+WCurrent/Max Moves:  [&n&+g" + MUDString.PadInt(ch.CurrentMoves, 5) + "&+W / &n&+g" + MUDString.PadInt(ch.MaxMoves, 5);
            text += "&+W]     &+WPlatinum      " + MUDString.PadInt(ch.GetPlatinum(), 5) + "        ";
            text += (ch.IsNPC() ? 0 : ((PC)ch).Bank.Platinum) + "\r\n";
            text += "Current/Max Mana:   [&n&+g" + MUDString.PadInt(ch.CurrentMana, 5) + "&+W / &n&+g" + MUDString.PadInt(ch.MaxMana, 5);
            text += "&+W]     &+YGold          " + MUDString.PadInt(ch.GetGold(), 5) + "        " + (ch.IsNPC() ? 0 : ((PC)ch).Bank.Gold) + "\r\n";
            text += "                                        &n&+wSilver        " + MUDString.PadInt(ch.GetSilver(), 5) + "        ";
            text += (ch.IsNPC() ? 0 : ((PC)ch).Bank.Silver) + "\r\n";
            text += "&+WFrags: &+W" + MUDString.PadInt((ch.IsNPC() ? 0 : ((PC)ch).Frags), 3) + "&n                               &n&+yCopper        ";
            text += MUDString.PadInt(ch.GetCopper(), 5) + "        " + (ch.IsNPC() ? 0 : ((PC)ch).Bank.Copper) + "\r\n";
            if (!ch.IsNPC())
            {
                text += "&+WTotal Deaths: &+W" + MUDString.PadInt(((PC)ch).MobDeaths + ((PC)ch).PlayerDeaths, 5) + "&n     &+WMobs Killed: &+W";
                text += MUDString.PadInt(((PC)ch).MobKills, 5) + "&n\r\n&+WPlayers Killed: &+W" + MUDString.PadInt(((PC)ch).PlayerKills, 5);
                text += "&n   &+WPlayer Deaths: &+W" + MUDString.PadInt(((PC)ch).PlayerDeaths, 5) + "&n\r\n";
            }

            if (!ch.IsNPC())
            {
                int divisor = ((PC)ch).Created.Quantity;
                if (divisor == 0)
                    divisor = 1;
                text += String.Format("&+WItems Created: &n{0}    &+WTotal Value: &n{1}  &+WBest: &n{2}  &+WAvg: &n{3}\r\n",
                    MUDString.PadInt(((PC)ch).Created.Quantity, 5),
                    MUDString.PadInt(((PC)ch).Created.TotalCost, 5),
                    MUDString.PadInt(((PC)ch).Created.MaxCost, 5),
                    MUDString.PadInt((((PC)ch).Created.TotalCost / divisor), 5));
                divisor = ((PC)ch).Destroyed.Quantity;
                if (divisor == 0)
                    divisor = 1;
                text += String.Format("&+WItems Destroyed: &n{0}  &+WTotal Value: &n{1}  &+WBest: &n{2}  &+WAvg: &n{3}\r\n",
                    MUDString.PadInt(((PC)ch).Destroyed.Quantity, 5),
                    MUDString.PadInt(((PC)ch).Destroyed.TotalCost, 5),
                    MUDString.PadInt(((PC)ch).Destroyed.MaxCost, 5),
                    MUDString.PadInt((((PC)ch).Destroyed.TotalCost / divisor), 5));
            }

            if (!ch.IsNPC())
            {
                text += "&+WTotal Score: &+W" + ((PC)ch).Score + "&n\r\n";
            }

            if (ch.IsClass(CharClass.Names.monk) || ch.IsClass(CharClass.Names.mystic))
            {
                text += "&+WTradition: &+B" + TraditionData.Names[((PC)ch).Tradition] + "&n\r\n";
                text += "&+WTraining Points: &+B" + (ch.IsNPC() ? 0 : ((PC)ch).SkillPoints) + "&n\r\n";
            }

            if (ch.Followers != null && ch.Followers.Count > 0)
            {
                text += "&+BFollowers:&n\r\n";
                foreach (CharData follower in ch.Followers)
                {
                    if (follower == null)
                    {
                        continue;
                    }
                    text += follower.ShowNameTo(ch, true) + " &n\r\n";
                }
                text += "\r\n";
            }
            if (ch.IsAffected( Affect.AFFECT_POISON))
            {
                text += "&+GYou are poisoned.&n\r\n";
            }

            if ((ch.IsAffected( Affect.AFFECT_DETECT_MAGIC) || ch.IsImmortal())
                    && MUDString.StringsNotEqual(BitvectorFlagType.AffectString(ch.AffectedBy, true), "none"))
            {
                text += "&+BEnchantments: &+W" + BitvectorFlagType.AffectString(ch.AffectedBy, true) + "&n\r\n\r\n";
            }

            if (ch.Affected != null)
            {
                bool printed = false;
                prev = null;
                foreach (Affect affect in ch.Affected)
                {
                    if (!printed)
                    {
                        text += "&+BActive Spells:&+W\r\n";
                        printed = true;
                    }

                    /* Show only new affects to mortals. */
                    if (prev != null && prev.Value == affect.Value
                            && prev.Type == affect.Type && !ch.IsImmortal())
                    {
                        prev = affect;
                        continue;
                    }
                    prev = affect;

                    if (affect.Type == Affect.AffectType.skill && !String.IsNullOrEmpty(affect.Value) && ch.IsImmortal())
                    {
                        text += MUDString.CapitalizeANSIString( Skill.SkillList[affect.Value].Name );
                    }
                    else if (affect.Type == Affect.AffectType.skill && !String.IsNullOrEmpty(affect.Value))
                    {
                        continue;
                    }
                    else if (affect.Type == Affect.AffectType.spell && !String.IsNullOrEmpty(affect.Value))
                    {
                        text += MUDString.CapitalizeANSIString(Spell.SpellList[affect.Value].Name);
                    }
                    else if (affect.Type == Affect.AffectType.song && !String.IsNullOrEmpty(affect.Value))
                    {
                        text += MUDString.CapitalizeANSIString(affect.Value);
                    }
                    else
                    {
                        text += "Something";
                    }

                    if (ch.IsImmortal())
                    {
                        foreach (AffectApplyType apply in affect.Modifiers)
                        {
                            text += " modifies " + StringConversion.AffectApplyString(apply.Location) + " by " + apply.Amount;
                        }
                        text += " for " + affect.Duration + " hours with bits " + affect.AffectString(false) + ".\r\n";
                    }
                    else
                    {
                        if (affect.Duration == 0 && ch.IsAffected( Affect.AFFECT_DETECT_MAGIC))
                        {
                            text += " (fading rapidly)\r\n";
                        }
                        else if (affect.Duration == 1 && ch.IsAffected( Affect.AFFECT_DETECT_MAGIC))
                        {
                            text += " (fading)\r\n";
                        }
                        else
                        {
                            text += "\r\n";
                        }
                    }
                }
            }
            text += "&n";
            ch.SendText(text);
            return;
        }
Exemple #5
0
        public static void Shift(CharData ch, string[] str)
        {
            if( ch == null ) return;
            if (ch.GetRace() != Race.RACE_GITHYANKI && !ch.IsImmortal())
            {
                ch.SendText("You lack that abillity!\r\n");
                return;
            }

            if (str.Length < 1 || String.IsNullOrEmpty(str[0]))
            {
                ch.SendText("Shift to where?\r\n");
                return;
            }

            if (ch.Fighting)
            {
                ch.SendText("You can't break off your fight.\r\n");
                return;
            }
            if ((ch.HasInnateTimer(InnateTimerData.Type.shift_astral) && !MUDString.IsPrefixOf(str[0], "astral"))
                || (ch.HasInnateTimer(InnateTimerData.Type.shift_prime) && !MUDString.IsPrefixOf(str[0], "prime")))
            {
                ch.SendText("You need to rest a _bitvector first.\r\n");
                return;
            }

            Area area = ch.InRoom.Area;
            Spell spell = StringLookup.SpellLookup("plane shift");
            if (!spell)
            {
                ch.SendText("Something seems to be blocking your ability to shift.");
                Log.Error("Shift: 'plane shift' spell not found. Check the spells file.");
                return;
            }
            spell.Invoke(ch, ch.Level, new Target(str[0]));
            // if it failed, don't lag or add a timer
            if (area == ch.InRoom.Area)
                return;
            if (!ch.IsImmortal())
            {
                if (!MUDString.IsPrefixOf(str[0], "astral"))
                    ch.AddInnateTimer(InnateTimerData.Type.shift_astral, 8);
                else if (!MUDString.IsPrefixOf(str[0], "prime"))
                    ch.AddInnateTimer(InnateTimerData.Type.shift_prime, 8);
            }
            ch.WaitState(14);
        }
Exemple #6
0
        /// <summary>
        /// Checks for magic resistance, also known as "shrug" -- as in "shrugging off the effects".
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="victim"></param>
        /// <returns></returns>
        public static bool CheckShrug( CharData ch, CharData victim )
        {
            int chance;

            if( !victim.HasInnate( Race.RACE_SHRUG ) )
            {
                return false;
            }

            switch( victim.GetRace() )
            {   // Default at 99 to show races not listed here.
                case Race.RACE_GREYELF:
                    chance = 25;
                    break;
                case Race.RACE_GITHZERAI:
                    chance = 10;
                    break;
                case Race.RACE_DROW:
                    chance = 40;
                    break;
                case Race.RACE_RAKSHASA:
                    chance = 15;
                    break;
                case Race.RACE_GITHYANKI:
                    chance = 20;
                    break;
                // Demons, devils, etc.
                default:
                    chance = 25 + ( victim.Level ) / 2;
                    break;
            }

            if( MUDMath.NumberPercent() < chance )
            {
                SocketConnection.Act( "&+MYour spell flows around &n$N&+M, leaving $M unharmed!&n", ch, null, victim, SocketConnection.MessageTarget.character );
                SocketConnection.Act( "&+M$N&+M's spell flows around you, leaving you unharmed!&n", victim, null, ch, SocketConnection.MessageTarget.character );
                SocketConnection.Act( "&+M$N&+M's spell flows around $n&+M, leaving $m unharmed!&n", victim, null, ch, SocketConnection.MessageTarget.room_vict );
                return true;
            }
            return false;
        }
Exemple #7
0
        /// <summary>
        /// Creates a duplicate of a mobile minus its inventory.
        /// </summary>
        /// <param name="parent"></param>
        /// <param name="clone"></param>
        public static void CloneMobile( CharData parent, CharData clone )
        {
            int i;

            if( parent == null || clone == null || !parent.IsNPC() )
                return;

            // Fix values.
            clone.Name = parent.Name;
            clone.ShortDescription = parent.ShortDescription;
            clone.FullDescription = parent.FullDescription;
            clone.Description = parent.Description;
            clone.Gender = parent.Gender;
            clone.CharacterClass = parent.CharacterClass;
            clone.SetPermRace( parent.GetRace() );
            clone.Level = parent.Level;
            clone.TrustLevel = 0;
            clone.SpecialFunction = parent.SpecialFunction;
            clone.SpecialFunctionNames = parent.SpecialFunctionNames;
            clone.Timer = parent.Timer;
            clone.Wait = parent.Wait;
            clone.Hitpoints = parent.Hitpoints;
            clone.MaxHitpoints = parent.MaxHitpoints;
            clone.CurrentMana = parent.CurrentMana;
            clone.MaxMana = parent.MaxMana;
            clone.CurrentMoves = parent.CurrentMoves;
            clone.MaxMoves = parent.MaxMoves;
            clone.SetCoins( parent.GetCopper(), parent.GetSilver(), parent.GetGold(), parent.GetPlatinum() );
            clone.ExperiencePoints = parent.ExperiencePoints;
            clone.ActionFlags = parent.ActionFlags;
            clone.Affected = parent.Affected;
            clone.CurrentPosition = parent.CurrentPosition;
            clone.Alignment = parent.Alignment;
            clone.Hitroll = parent.Hitroll;
            clone.Damroll = parent.Damroll;
            clone.Wimpy = parent.Wimpy;
            clone.Deaf = parent.Deaf;
            clone.Hunting = parent.Hunting;
            clone.Hating = parent.Hating;
            clone.Fearing = parent.Fearing;
            clone.Resistant = parent.Resistant;
            clone.Immune = parent.Immune;
            clone.Susceptible = parent.Susceptible;
            clone.CurrentSize = parent.CurrentSize;
            clone.PermStrength = parent.PermStrength;
            clone.PermIntelligence = parent.PermIntelligence;
            clone.PermWisdom = parent.PermWisdom;
            clone.PermDexterity = parent.PermDexterity;
            clone.PermConstitution = parent.PermConstitution;
            clone.PermAgility = parent.PermAgility;
            clone.PermCharisma = parent.PermCharisma;
            clone.PermPower = parent.PermPower;
            clone.PermLuck = parent.PermLuck;
            clone.ModifiedStrength = parent.ModifiedStrength;
            clone.ModifiedIntelligence = parent.ModifiedIntelligence;
            clone.ModifiedWisdom = parent.ModifiedWisdom;
            clone.ModifiedDexterity = parent.ModifiedDexterity;
            clone.ModifiedConstitution = parent.ModifiedConstitution;
            clone.ModifiedAgility = parent.ModifiedAgility;
            clone.ModifiedCharisma = parent.ModifiedCharisma;
            clone.ModifiedPower = parent.ModifiedPower;
            clone.ModifiedLuck = parent.ModifiedLuck;
            clone.ArmorPoints = parent.ArmorPoints;
            //clone._mpactnum = parent._mpactnum;

            for (i = 0; i < 6; i++)
            {
                clone.SavingThrows[i] = parent.SavingThrows[i];
            }

            // Now add the affects.
            foreach (Affect affect in parent.Affected)
            {
                clone.AddAffect(affect);
            }
        }
Exemple #8
0
 /// <summary>
 /// Checks whether char is resistant to the supplied damage type.
 /// </summary>
 /// <param name="ch"></param>
 /// <param name="bit"></param>
 /// <returns></returns>
 public static bool CheckResistant( CharData ch, Race.DamageType bit )
 {
     return ( Macros.IsSet( (int)ch.Resistant | (int)Race.RaceList[ ch.GetRace() ].Resistant, (int)bit ) );
 }
Exemple #9
0
 /// <summary>
 /// Checks whether char is vulnerable to the supplied damage type.
 /// </summary>
 /// <param name="ch"></param>
 /// <param name="bit"></param>
 /// <returns></returns>
 public static bool CheckVulnerable(CharData ch, Race.DamageType bit)
 {
     return (Macros.IsSet((int)ch.Vulnerable | (int)Race.RaceList[ch.GetRace()].Vulnerable, (int)bit));
 }
Exemple #10
0
        /// <summary>
        /// True if char can see victim.
        ///
        /// This is only a straightford all-or-none vision checker.
        ///
        /// If you need more granularity, use Command.HowSee which returns an enum
        /// based on the level of visibility but otherwise functions similarly.
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="victim"></param>
        /// <returns></returns>
        public static bool CanSee( CharData ch, CharData victim )
        {
            if( ch == null )
            {
                Log.Error( "CharData.CanSee: called with null ch.", 0 );
                return false;
            }

            if( victim == null )
            {
                Log.Error( "CharData.CanSee: called with null victim.", 0 );
                return false;
            }

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

            /* All mobiles cannot see wizinvised immorts */
            if (ch.IsNPC() && !ch.IsNPC() && ch.HasActionBit(PC.PLAYER_WIZINVIS))
            {
                return false;
            }

            if (!ch.IsNPC() && ch.HasActionBit(PC.PLAYER_WIZINVIS) && ch.GetTrust() < ch.Level)
            {
                return false;
            }

            if (!ch.IsNPC() && ch.HasActionBit(PC.PLAYER_GODMODE))
            {
                return true;
            }

            if( ch.IsAffected( Affect.AFFECT_BLIND ) )
            {
                return false;
            }

            if (ch.InRoom == null)
            {
                Log.Error("CanSee called by player " + ch.Name + " with null room.");
                return false;
            }

            if( ch.InRoom.IsDark() && !ch.HasInnate( Race.RACE_ULTRAVISION )
                    && !ch.IsAffected( Affect.AFFECT_ULTRAVISION ) && !ch.HasInnate( Race.RACE_INFRAVISION )
                    && !ch.IsAffected(Affect.AFFECT_INFRAVISION ) )
            {
                return false;
            }

            if (ch.CurrentPosition == Position.dead)
            {
                return true;
            }

            if ((victim.IsAffected(Affect.AFFECT_INVISIBLE) || victim.IsAffected(Affect.AFFECT_MINOR_INVIS))
                    && !ch.HasInnate( Race.RACE_DETECT_INVIS ) && !ch.IsAffected(Affect.AFFECT_DETECT_INVIS )
                    && !(ch.IsAffected(Affect.AFFECT_ELEM_SIGHT) &&
                          ( ch.GetRace() == Race.RACE_AIR_ELE || ch.GetRace() == Race.RACE_WATER_ELE
                            || ch.GetRace() == Race.RACE_FIRE_ELE || ch.GetRace() == Race.RACE_EARTH_ELE ) ) )
            {
                return false;
            }

            if( victim.IsAffected( Affect.AFFECT_HIDE ) && !ch.HasInnate( Race.RACE_DETECT_HIDDEN )
                    && !ch.IsAffected( Affect.AFFECT_DETECT_HIDDEN ) && !ch.Fighting )
            {
                return false;
            }

            return true;
        }
Exemple #11
0
 /// <summary>
 /// Checks whether char is immune to the supplied damage type.
 /// </summary>
 /// <param name="ch"></param>
 /// <param name="bit"></param>
 /// <returns></returns>
 public static bool CheckImmune( CharData ch, Race.DamageType bit )
 {
     return ( Macros.IsSet( (int)ch.Immune | (int)Race.RaceList[ ch.GetRace() ].Immune, (int)bit ) );
 }
Exemple #12
0
        /// <summary>
        /// Checks whether the caller is aggressive toward the victim.
        /// </summary>
        /// <param name="victim"></param>
        /// <returns></returns>
        public bool IsAggressive(CharData victim)
        {
            CharData ch = this;
            Guild guild = null;

            if (victim == null)
            {
                Log.Error("IsAggressive: called with null ch or victim.", 0);
                return false;
            }

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

            if (MUDString.NameContainedIn("_guildgolem_", ch.Name))
            {
                foreach (Guild it in Database.GuildList)
                {
                    guild = it;
                    if (guild.ID == Guild.GolemGuildID(ch))
                        break;
                }
                if (guild != null && guild.Ostracized.Length != 0)
                {
                    if (MUDString.NameContainedIn(victim.Name, guild.Ostracized))
                        return true;
                }
            }
            if (MUDString.NameContainedIn(Race.RaceList[victim.GetRace()].Name, Race.RaceList[ch.GetOrigRace()].Hate))
            {
                Log.Trace("Returning true for IsAggressive due to race hatred.");
                return true;
            }
            if (ch.HasActionBit(MobTemplate.ACT_AGGROGOOD) && victim.IsGood())
            {
                Log.Trace("Returning true for IsAggressive due to aggro good and good victim.");
                return true;
            }
            if (ch.HasActionBit(MobTemplate.ACT_AGGROEVIL) && victim.IsEvil())
            {
                Log.Trace("Returning true for IsAggressive due to aggro evil and evil victim.");
                return true;
            }
            if (ch.HasActionBit(MobTemplate.ACT_AGGRONEUT) && victim.IsNeutral())
            {
                Log.Trace("Returning true for IsAggressive due to aggro neutral and neutral victim.");
                return true;
            }
            if (ch.HasActionBit(MobTemplate.ACT_AGGROEVILRACE) && victim.GetRacewarSide() == Race.RacewarSide.evil)
            {
                Log.Trace("Returning true for IsAggressive due to aggro evil race and victim evil racewar.");
                return true;
            }
            if (ch.HasActionBit(MobTemplate.ACT_AGGROGOODRACE) && victim.GetRacewarSide() == Race.RacewarSide.good)
            {
                Log.Trace("Returning true for IsAggressive due to aggro good race and victim good racewar.");
                return true;
            }
            if (ch.HasActionBit(MobTemplate.ACT_AGGRESSIVE))
            {
                Log.Trace("Returning true for IsAggressive due to aggressive flag on ch.");
                return true;
            }

            return ch.IsHating(victim);
        }
Exemple #13
0
        /// <summary>
        /// Regeneration and natural healing.
        /// </summary>
        /// <param name="ch"></param>
        /// <returns></returns>
        public static int HitGain( CharData ch )
        {
            int gain;
            int percent = 0;

            if( ch == null )
            {
                Log.Error( "HitGain(): null ch", 0 );
                return 0;
            }

            // They aren't going to gain hits in a no heal room...
            if (ch.InRoom.HasFlag(RoomTemplate.ROOM_NO_HEAL))
            {
                return 0;
            }

            gain = 1;
            percent = 100;

            if (ch.CheckSkill("fast healing", PracticeType.none))
            {
                gain += 1;
            }
            if (MUDMath.NumberPercent() < 3)
            {
                ch.PracticeSkill("fast healing");
            }

            switch( ch.CurrentPosition )
            {
                case Position.sleeping:
                    gain += 3;
                    break;
                case Position.reclining:
                    gain += 2;
                    break;
                case Position.resting:
                    gain += 1;
                    break;
                case Position.fighting:
                    gain = 0;
                    break;
            }

            if( ch.HasInnate( Race.RACE_REGENERATE ) )
            {
                // Automatically one extra hp, two at level 30.
                gain += 1 + (ch.Level / 30);
                // One percent chance of gaining another per level.
                percent += (ch.Level);
            }

            // Hunger and thirst for PCs.
            if (!ch.IsNPC())
            {
                if (((PC)ch).Hunger == 0)
                {
                    gain /= 2;
                    gain -= 1;
                    percent -= 25;
                    ch.SendText("&nYou double over from &+Rhunger pains&n!\r\n");
                }

                if (((PC)ch).Thirst == 0)
                {
                    gain /= 2;
                    gain -= 1;
                    percent -= 25;
                    ch.SendText("&nYou suffer from severe &+cth&+Ci&n&+cr&+Cst&n!\r\n");
                }
            }

            if( ch.IsAffected( Affect.AFFECT_POISON ) )
            {
                gain /= 4;
                percent /= 2;
            }

            if( gain == 0 )
                if( MUDMath.NumberPercent() < percent )
                    gain = 1;

            // Heal rooms heal you a little quicker
            if (ch.InRoom.HasFlag(RoomTemplate.ROOM_HEAL))
            {
                gain += Math.Max(1, gain / 2);
            }

            if( ( ch.InRoom.TerrainType != TerrainType.underwater_has_ground
                    && ch.InRoom.TerrainType != TerrainType.unswimmable_water
                    && ch.InRoom.TerrainType != TerrainType.swimmable_water
                    && ch.HasInnate( Race.RACE_WATERBREATH )
                    && MUDString.StringsNotEqual( Race.RaceList[ ch.GetRace() ].Name, "Object" )
                    && ch.GetRace() != Race.RACE_GOD )
                    || ( ch.InRoom.TerrainType == TerrainType.underwater_has_ground
                         && ( !ch.IsImmortal() && !ch.IsAffected( Affect.AFFECT_BREATHE_UNDERWATER )
                              && !ch.HasInnate( Race.RACE_WATERBREATH ) ) ) )
                gain = 0;

            return Math.Min( gain, ch.GetMaxHit() - ch.Hitpoints );
        }
Exemple #14
0
        /// <summary>
        /// This function's main access commands are wear, wield, and hold, which have the
        /// following flow:
        /// wear:  Command.Wear, wear_obj, equip_hand
        /// wield: Command.Wield, equip_hand
        /// hold:  Command.Hold, equip_hand 
        /// 
        /// We assume by this point that the character is physically able to use the item and will be able
        /// to equip it however specified.  Those checks are performed by WearObject(), Equip(), and Hold().
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="obj"></param>
        /// <param name="type"></param>
        /// <returns></returns>
        public static bool EquipInHand(CharData ch, Object obj, int type)
        {
            int weight = 0;
            ObjTemplate.WearLocation firstAvail = ObjTemplate.WearLocation.none;
            ObjTemplate.WearLocation secondAvail = ObjTemplate.WearLocation.none;
            ObjTemplate.WearLocation lastAvail = ObjTemplate.WearLocation.none;

            Object hand1 = GetEquipmentOnCharacter(ch, ObjTemplate.WearLocation.hand_one);
            Object hand2 = GetEquipmentOnCharacter(ch, ObjTemplate.WearLocation.hand_two);
            Object hand3 = GetEquipmentOnCharacter(ch, ObjTemplate.WearLocation.hand_three);
            Object hand4 = GetEquipmentOnCharacter(ch, ObjTemplate.WearLocation.hand_four);
            if (hand1 && (hand1._itemType == ObjTemplate.ObjectType.weapon || hand1._itemType == ObjTemplate.ObjectType.ranged_weapon))
                weight += hand1.GetWeight();
            if (hand2 && (hand2._itemType == ObjTemplate.ObjectType.weapon || hand2._itemType == ObjTemplate.ObjectType.ranged_weapon))
                weight += hand2.GetWeight();
            if (hand3 && (hand3._itemType == ObjTemplate.ObjectType.weapon || hand3._itemType == ObjTemplate.ObjectType.ranged_weapon))
                weight += hand3.GetWeight();
            if (hand4 && (hand4._itemType == ObjTemplate.ObjectType.weapon || hand4._itemType == ObjTemplate.ObjectType.ranged_weapon))
                weight += hand4.GetWeight();

            if (ch.GetRace() != Race.RACE_THRIKREEN)
            {
                if (hand3)
                    Log.Error("non-thrikreen wielding item in hand3", 0);
                if (hand4)
                    Log.Error("non-thrikreen wielding item in hand4", 0);
            }

            // Find number of hand slots used and first available hand.
            // Be sure to handle twohanded stuff.
            if (hand4 && hand4.HasFlag(ObjTemplate.ITEM_TWOHANDED))
            {
                Log.Error("Twohanded weapon in fourth hand -- this is not possible.", 0);
            }
            if (hand3 && hand3.HasFlag(ObjTemplate.ITEM_TWOHANDED))
            {
                if (hand4)
                {
                    Log.Error("Twohanded weapon in third hand with fourth hand holding twohanded weapon -- this is not possible, all twohanded must have a blank hand after it.", 0);
                }
                hand4 = hand3;
            }
            if (hand2 && hand2.HasFlag(ObjTemplate.ITEM_TWOHANDED))
            {
                if (hand3)
                {
                    Log.Error("Twohanded weapon in second hand with third hand holding twohanded weapon -- this is not possible, all twohanded must have a blank hand after it.", 0);
                }
                hand2 = hand3;
            }
            if (!ch.HasInnate(Race.RACE_EXTRA_STRONG_WIELD))
            {
                if (hand1 && hand1.HasFlag(ObjTemplate.ITEM_TWOHANDED))
                {
                    if (hand2)
                    {
                        Log.Error("Twohanded weapon in second hand with first hand holding twohanded weapon -- this is not possible, all twohanded must have a blank hand after it.", 0);
                    }
                    hand2 = hand1;
                }
            }

            if (obj.HasFlag(ObjTemplate.ITEM_TWOHANDED)
                    && !ch.HasInnate(Race.RACE_EXTRA_STRONG_WIELD))
            {
                if (ch.GetRace() == Race.RACE_THRIKREEN && !hand4)
                {
                    firstAvail = ObjTemplate.WearLocation.hand_four;
                    lastAvail = ObjTemplate.WearLocation.hand_four;
                }
                if (ch.GetRace() == Race.RACE_THRIKREEN && !hand3)
                {
                    if (lastAvail == 0)
                        lastAvail = ObjTemplate.WearLocation.hand_three;
                    secondAvail = firstAvail;
                    firstAvail = ObjTemplate.WearLocation.hand_three;
                }
                if (!hand2)
                {
                    if (lastAvail == 0)
                        lastAvail = ObjTemplate.WearLocation.hand_two;
                    secondAvail = firstAvail;
                    firstAvail = ObjTemplate.WearLocation.hand_two;
                }
                if (!hand1)
                {
                    if (lastAvail == 0)
                        lastAvail = ObjTemplate.WearLocation.hand_one;
                    secondAvail = firstAvail;
                    firstAvail = ObjTemplate.WearLocation.hand_one;
                }

                if (firstAvail == 0)
                {
                    ch.SendText("Your hands are full!\r\n");
                    return false;
                }
                if (secondAvail == 0)
                {
                    ch.SendText("You need two hands free to wield that!\r\n");
                    return false;
                }
            }
            else if (obj.HasFlag(ObjTemplate.ITEM_TWOHANDED))
            {
                if (ch.GetRace() == Race.RACE_THRIKREEN && !hand4)
                {
                    firstAvail = ObjTemplate.WearLocation.hand_four;
                }
                if (ch.GetRace() == Race.RACE_THRIKREEN && !hand3)
                {
                    if (lastAvail == 0)
                        lastAvail = ObjTemplate.WearLocation.hand_three;
                    secondAvail = firstAvail;
                    firstAvail = ObjTemplate.WearLocation.hand_three;
                }
                if (!hand2)
                {
                    if (lastAvail == 0)
                        lastAvail = ObjTemplate.WearLocation.hand_two;
                    secondAvail = firstAvail;
                    firstAvail = ObjTemplate.WearLocation.hand_two;
                }
                if (!hand1)
                {
                    if (lastAvail == 0)
                        lastAvail = ObjTemplate.WearLocation.hand_one;
                    secondAvail = ObjTemplate.WearLocation.hand_one;
                    firstAvail = ObjTemplate.WearLocation.hand_one;
                }

                if (firstAvail == 0)
                {
                    ch.SendText("Your hands are full!\r\n");
                    return false;
                }
                if (secondAvail == 0)
                {
                    ch.SendText("You need two hands free to wield that!\r\n");
                    return false;
                }
            }
            else
            {
                if (ch.GetRace() == Race.RACE_THRIKREEN && !hand4)
                {
                    if (lastAvail == 0)
                        lastAvail = ObjTemplate.WearLocation.hand_four;
                    firstAvail = ObjTemplate.WearLocation.hand_four;
                }
                if (ch.GetRace() == Race.RACE_THRIKREEN && !hand3)
                {
                    if (lastAvail == 0)
                        lastAvail = ObjTemplate.WearLocation.hand_three;
                    firstAvail = ObjTemplate.WearLocation.hand_three;
                }
                if (!hand2)
                {
                    if (lastAvail == 0)
                        lastAvail = ObjTemplate.WearLocation.hand_two;
                    firstAvail = ObjTemplate.WearLocation.hand_two;
                }
                if (hand1 == null)
                {
                    if (lastAvail == 0)
                        lastAvail = ObjTemplate.WearLocation.hand_one;
                    firstAvail = ObjTemplate.WearLocation.hand_one;
                }

                if (firstAvail == 0)
                {
                    ch.SendText("Your hands are full!\r\n");
                    return false;
                }
            }

            // Successful hand availability, send message and ready the item.
            // Twohanded shields, held items, and lights are equipped primary.
            // This could annoy ogres/thris but twohanded versions of these items
            // are so rare it's not likely to be an issue.
            switch (type)
            {
                case EQUIP_HOLD:
                    if (!obj.HasFlag(ObjTemplate.ITEM_TWOHANDED))
                        ch.EquipObject(ref obj, lastAvail);
                    else
                        ch.EquipObject(ref obj, firstAvail);
                    break;
                case EQUIP_SHIELD:
                    SocketConnection.Act("You strap $p&n to your arm.", ch, obj, null, SocketConnection.MessageTarget.character);
                    SocketConnection.Act("$n&n straps $p&n to $s arm.", ch, obj, null, SocketConnection.MessageTarget.room);
                    if (!obj.HasFlag(ObjTemplate.ITEM_TWOHANDED))
                        ch.EquipObject(ref obj, lastAvail);
                    else
                        ch.EquipObject(ref obj, firstAvail);
                    break;
                case EQUIP_LIGHT:
                    if (obj._itemType == ObjTemplate.ObjectType.light && obj._values[2] != 0)
                    {
                        SocketConnection.Act("You &n&+rli&+Rght&n $p&n and hold it before you.", ch, obj, null, SocketConnection.MessageTarget.character);
                        SocketConnection.Act("$n&n &+Rlig&n&+rhts&n $p&n and holds it before $m.", ch, obj, null, SocketConnection.MessageTarget.room);
                    }
                    else
                    {
                        SocketConnection.Act("You hold the &+Lspent&n remains of $p&n.", ch, obj, null, SocketConnection.MessageTarget.character);
                        SocketConnection.Act("$n&n holds the spent husk of $p&n.", ch, obj, null, SocketConnection.MessageTarget.room);
                    }
                    if (!obj.HasFlag(ObjTemplate.ITEM_TWOHANDED))
                        ch.EquipObject(ref obj, lastAvail);
                    else
                        ch.EquipObject(ref obj, firstAvail);
                    break;
                case EQUIP_WIELD:
                    // Have to check for dual wield skill, and for total weight of weapons.
                    if (firstAvail != ObjTemplate.WearLocation.hand_one)
                    {
                        // Those without dual wield cannot wield anything in their second hand.  Include thrikreen
                        if (!ch.IsNPC() && !ch.HasSkill("dual wield"))
                        {
                            ch.SendText("You lack the skills to wield a weapon in anything but your primary hand.\r\n");
                            return false;
                        }
                    }
                    if ((weight + obj.GetWeight()) > StrengthModifier.Table[ch.GetCurrStr()].WieldWeight)
                    {
                        SocketConnection.Act("Your meager strength is overwhelmed by $p&n.", ch, obj, null, SocketConnection.MessageTarget.character);
                        return false;
                    }
                    SocketConnection.Act("You wield $p&n.", ch, obj, null, SocketConnection.MessageTarget.character);
                    SocketConnection.Act("$n&n brandishes $p&n.", ch, obj, null, SocketConnection.MessageTarget.room);
                    ch.EquipObject(ref obj, firstAvail);
                    break;
            }

            // Objects with a trap activated on wear.
            if (obj._trap != null && obj._trap.CheckTrigger( Trap.TriggerType.wear))
            {
                ch.SetOffTrap(obj);
                if (ch.CurrentPosition == Position.dead)
                    return false;
            }

            return true;
        }
Exemple #15
0
        /// <summary>
        /// Processes a blur-type attack.  Returns true if the victim died.
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="victim"></param>
        /// <returns></returns>
        public static bool BlurAttack( CharData ch, CharData victim )
        {
            if (ch == null) return false;

            int numAttacks;
            int count;

            if( ch.IsAffected( Affect.AFFECT_CASTING ) )
            {
                return false;
            }

            if( ch.IsAffected( Affect.AFFECT_BLUR ) && MUDMath.NumberPercent() < 25 )
            {
                SocketConnection.Act( "$n&n moves with a BLUR of speed!", ch, null, null, SocketConnection.MessageTarget.room );
                SocketConnection.Act( "You move with a BLUR of speed!", ch, null, null, SocketConnection.MessageTarget.character );
                for( count = 0, numAttacks = 4; count < numAttacks && victim.CurrentPosition > Position.dead; ++count )
                {
                    SingleAttack( ch, victim, String.Empty, ObjTemplate.WearLocation.hand_one );
                }
            }
            else
            {
                Object wield;

                if( MUDMath.NumberPercent() > 10 )
                    return false;
                if( ch.IsClass(CharClass.Names.hunter) || ch.IsClass(CharClass.Names.ranger ))
                    numAttacks = 2;
                else if( ch.GetRace() == Race.RACE_OGRE || ch.GetRace() == Race.RACE_CENTAUR )
                    numAttacks = 4;
                else
                    numAttacks = 9;
                if( MUDMath.NumberPercent() < ch.GetCurrLuck() )
                    numAttacks++;
                if( MUDMath.NumberPercent() < victim.GetCurrLuck() )
                    numAttacks--;

                /* 9716 is the index number for the dagger of the wind. */
                // HORRIBLE HORRIBLE TODO: FIXME: BUG: Never hard-code item index numbers.
                if( ( wield = Object.GetEquipmentOnCharacter( ch, ObjTemplate.WearLocation.hand_one ) ) && wield.ObjIndexData.IndexNumber == 9716 )
                {
                    SocketConnection.Act( "&+c$n&+c's $p&n &+cbegins to move with the &+Wspeed&+c of a &+lstorm&+c!&n", ch, wield, null, SocketConnection.MessageTarget.room );
                    SocketConnection.Act( "Your $p&n &+cbegins to move with the &+Wspeed&+c of a &+lstorm&+c!&n", ch, wield, null, SocketConnection.MessageTarget.character );
                    for( count = 0; count < numAttacks && victim.CurrentPosition > Position.dead; ++count )
                    {
                        SingleAttack(ch, victim, String.Empty, ObjTemplate.WearLocation.hand_one);
                    }
                    return ( victim.CurrentPosition > Position.dead );
                }
                if( ( wield = Object.GetEquipmentOnCharacter( ch, ObjTemplate.WearLocation.hand_two ) ) && wield.ObjIndexData.IndexNumber == 9716 )
                {
                    SocketConnection.Act( "&+c$n&+c's $p&n &+cbegins to move with the &+Wspeed&+c of a &+lstorm&+c!&n", ch, wield, null, SocketConnection.MessageTarget.room );
                    SocketConnection.Act( "Your $p&n &+cbegins to move with the &+Wspeed&+c of a &+lstorm&+c!&n", ch, wield, null, SocketConnection.MessageTarget.character );
                    for( count = 0; count < numAttacks && victim.CurrentPosition > Position.dead; ++count )
                    {
                        SingleAttack(ch, victim, String.Empty, ObjTemplate.WearLocation.hand_two);
                    }
                    return ( victim.CurrentPosition > Position.dead );
                }
                if( ( wield = Object.GetEquipmentOnCharacter( ch, ObjTemplate.WearLocation.hand_three ) ) && wield.ObjIndexData.IndexNumber == 9716 )
                {
                    SocketConnection.Act( "&+c$n&+c's $p&n &+cbegins to move with the &+Wspeed&+c of a &+lstorm&+c!&n", ch, wield, null, SocketConnection.MessageTarget.room );
                    SocketConnection.Act( "Your $p&n &+cbegins to move with the &+Wspeed&+c of a &+lstorm&+c!&n", ch, wield, null, SocketConnection.MessageTarget.character );
                    for( count = 0; count < numAttacks && victim.CurrentPosition > Position.dead; ++count )
                    {
                        SingleAttack(ch, victim, String.Empty, ObjTemplate.WearLocation.hand_three);
                    }
                    return ( victim.CurrentPosition > Position.dead );
                }
                if( ( wield = Object.GetEquipmentOnCharacter( ch, ObjTemplate.WearLocation.hand_four ) ) && wield.ObjIndexData.IndexNumber == 9716 )
                {
                    SocketConnection.Act( "&+c$n&+c's $p&n &+cbegins to move with the &+Wspeed&+c of a &+lstorm&+c!&n", ch, wield, null, SocketConnection.MessageTarget.room );
                    SocketConnection.Act( "Your $p&n &+cbegins to move with the &+Wspeed&+c of a &+lstorm&+c!&n", ch, wield, null, SocketConnection.MessageTarget.character );
                    for( count = 0; count < numAttacks && victim.CurrentPosition > Position.dead; ++count )
                    {
                        SingleAttack(ch, victim, String.Empty, ObjTemplate.WearLocation.hand_four);
                    }
                    return ( victim.CurrentPosition > Position.dead );
                }
            }
            return false;
        }
Exemple #16
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;
        }
Exemple #17
0
        /// <summary>
        /// Checks whether the victim is able to dodge the attacker's swing.
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="victim"></param>
        /// <returns></returns>
        public static bool CheckDodge( CharData ch, CharData victim )
        {
            if( !victim.IsAwake() || victim.CurrentPosition < Position.reclining )
                return false;

            if (ch.IsAffected(Affect.AFFECT_DAZZLE))
                return false;

            if( !victim.HasSkill( "dodge" ) )
                return false;

            int chance = victim.GetSkillChance("dodge");

            // Size difference bonus for dodge for halflings - they get 2% dodge
            // bonus per size difference between them and the attacker. -- Xangis
            // Drow get a flat 15% bonus.
            if( victim.GetRace() == Race.RACE_HALFLING )
            {
                if( ch.CurrentSize > victim.CurrentSize )
                {
                    chance += 3 * ( ch.CurrentSize - victim.CurrentSize );
                }
            }
            else if( victim.HasInnate( Race.RACE_GOOD_DODGE ) )
            {
                chance += 8;
            }
            else if( victim.HasInnate( Race.RACE_BAD_DODGE ) )
            {
                chance -= 3;
            }

            // Bashed mobs/creatures have a hard time dodging
            if( victim.CurrentPosition < Position.fighting )
            {
                chance -= 25;
            }

            // Leap is 16% max at level 50.  Considering crappy thri hitpoints it's necessary.
            if( victim.GetRace() == Race.RACE_THRIKREEN && MUDMath.NumberPercent() <= ( victim.Level / 3 ) )
            {
                SocketConnection.Act( "$N&n leaps over your attack.", ch, null, victim, SocketConnection.MessageTarget.character );
                SocketConnection.Act( "You leap over $n&n's attack.", ch, null, victim, SocketConnection.MessageTarget.victim );
                SocketConnection.Act( "$N&n leaps over $n&n's attack.", ch, null, victim, SocketConnection.MessageTarget.room_vict );
                return true;
            }

            victim.PracticeSkill( "dodge" );

            if( MUDMath.NumberPercent() >= chance - ch.Level )
                return false;

            switch( MUDMath.NumberRange( 1, 2 ) )
            {
                case 1:
                    SocketConnection.Act( "$N&n dodges your attack.", ch, null, victim, SocketConnection.MessageTarget.character );
                    SocketConnection.Act( "You dodge $n&n's attack.", ch, null, victim, SocketConnection.MessageTarget.victim );
                    SocketConnection.Act( "$N&n dodges $n&n's attack.", ch, null, victim, SocketConnection.MessageTarget.room_vict );
                    break;
                case 2:
                    SocketConnection.Act( "$N&n sidesteps your attack.", ch, null, victim, SocketConnection.MessageTarget.character );
                    SocketConnection.Act( "You narrowly dodge $n&n's attack.", ch, null, victim, SocketConnection.MessageTarget.victim );
                    SocketConnection.Act( "$N&n avoids $n&n's attack.", ch, null, victim, SocketConnection.MessageTarget.room_vict );
                    break;
                default:
                    break;
            }

            if( ch.Fighting == null )
                SetFighting( ch, victim );
            if( victim.Fighting == null )
                SetFighting( victim, ch );

            return true;
        }
Exemple #18
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;
        }
Exemple #19
0
        /// <summary>
        /// Do one round of attacks for one character.
        /// Note: This is a round, not a single attack!
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="victim"></param>
        /// <param name="skill"></param>
        /// <returns></returns>
        public static bool CombatRound(CharData ch, CharData victim, string skill)
        {
            Object wield;
            int chance = 0;

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

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

            /* No casting/being para'd and hitting at the same time. */
            if( ( ch.IsAffected( Affect.AFFECT_CASTING ) ) || ch.IsAffected( Affect.AFFECT_MINOR_PARA )
                    || ch.IsAffected(Affect.AFFECT_HOLD))
            {
                return false;
            }

            /* I don't know how a dead person can hit someone/be hit. */
            if( victim.CurrentPosition == Position.dead || victim.Hitpoints < -10 )
            {
                StopFighting( victim, true );
                return true;
            }

            /*
            * Set the fighting fields now.
            */
            if( victim.CurrentPosition > Position.stunned )
            {
                if( !victim.Fighting )
                    SetFighting( victim, ch );
                // Can't have bashed/prone people just automatically be standing.
                if( victim.CurrentPosition == Position.standing )
                    victim.CurrentPosition = Position.fighting;
            }

            // HORRIBLE HORRIBLE! We've got index numbers hard-coded.  TODO: FIXME: BUG: Get rid of this!
            if( ch.IsNPC() && ch.MobileTemplate != null && ( ch.MobileTemplate.IndexNumber == 9316 ||
                   ch.MobileTemplate.IndexNumber == 9748 ) && MUDMath.NumberPercent() < 20 )
            {
                CheckShout( ch, victim );
            }
            ch.BreakInvisibility();

            // Everyone gets at least one swing/breath in battle.
            // This handles breathing, roaring, etc.
            if (!CheckRaceSpecial(ch, victim, skill))
                SingleAttack(ch, victim, skill, ObjTemplate.WearLocation.hand_one);

            // Thrikreen primary hand extra attack, only thri extra attack that is
            // given to non-warriors in addition to warriors
            if( ch.GetRace() == Race.RACE_THRIKREEN && MUDMath.NumberPercent() < ch.Level )
            {
                if( ch.IsClass(CharClass.Names.warrior) )
                {
                    switch( MUDMath.NumberRange( 1, 4 ) )
                    {
                        case 1:
                            if( Object.GetEquipmentOnCharacter( ch, ObjTemplate.WearLocation.hand_one ) )
                                SingleAttack(ch, victim, skill, ObjTemplate.WearLocation.hand_one);
                            break;
                        case 2:
                            if( Object.GetEquipmentOnCharacter( ch, ObjTemplate.WearLocation.hand_two ) )
                                SingleAttack(ch, victim, skill, ObjTemplate.WearLocation.hand_two);
                            break;
                        case 3:
                            if( Object.GetEquipmentOnCharacter( ch, ObjTemplate.WearLocation.hand_three ) )
                                SingleAttack(ch, victim, skill, ObjTemplate.WearLocation.hand_three);
                            break;
                        case 4:
                            if( Object.GetEquipmentOnCharacter( ch, ObjTemplate.WearLocation.hand_four ) )
                                SingleAttack(ch, victim, skill, ObjTemplate.WearLocation.hand_four);
                            break;
                    }
                }
                else
                {
                    SingleAttack(ch, victim, skill, ObjTemplate.WearLocation.hand_one);
                    if( MUDMath.NumberPercent() < ch.Level / 2 )
                    {
                        SingleAttack(ch, victim, skill, ObjTemplate.WearLocation.hand_one);
                    }
                }
            }

            // Don't hurt a corpse.
            if( victim.CurrentPosition == Position.dead || victim.Hitpoints < -10 )
            {
                StopFighting( ch, false );
                {
                    return true;
                }
            }

            // For NPCs we assume they have max skill value for their level.
            // When checking combat skills we only prDescriptor.actice them on a successful
            // check in order to make them go up slower.  If they go up too slow
            // we can always practice them before they check.

            chance = ch.GetAttackChance(2);
            if( MUDMath.NumberPercent() < chance )
            {
                ch.PracticeSkill( "second attack" );
                SingleAttack(ch, victim, skill, ObjTemplate.WearLocation.hand_one);
                if( ch.Fighting != victim )
                {
                    return false;
                }
            }

            // Check for Thri-Kreen arm #3
            if( ch.GetRace() == Race.RACE_THRIKREEN && ( wield = Object.GetEquipmentOnCharacter( ch, ObjTemplate.WearLocation.hand_three ) ) )
            {
                if( wield.HasWearFlag( ObjTemplate.WEARABLE_WIELD ) )
                {
                    if( ch.IsNPC() )
                    {
                        if( !ch.HasSkill( "second attack" ))
                        {
                            chance = ch.Level / 5;  // Up to 10% chance of third arm for psis and
                        }
                        // other miscellaneous thris
                        else
                        {
                            chance = ((ch.Level - Skill.SkillList["second attack"].ClassAvailability[(int)ch.CharacterClass.ClassNumber]) * 2 + 25);
                        }
                    }
                    else
                    {
                        if (((PC)ch).SkillAptitude.ContainsKey("second attack"))
                        {
                            chance = ((PC)ch).SkillAptitude["second attack"];
                        }
                        else
                        {
                            chance = 0;
                        }
                    }

                    if( chance > 95 )
                        chance = 95;

                    if( MUDMath.NumberPercent() < chance )
                    {
                        ch.PracticeSkill( "second attack" );
                        SingleAttack(ch, victim, skill, ObjTemplate.WearLocation.hand_three);
                        if( ch.Fighting != victim )
                        {
                            return false;
                        }
                    }
                }
            }

            chance = ch.GetAttackChance(3);
            if( MUDMath.NumberPercent() < chance )
            {
                ch.PracticeSkill( "third attack" );
                SingleAttack(ch, victim, skill, ObjTemplate.WearLocation.hand_one);
                if( ch.Fighting != victim )
                {
                    return false;
                }
            }

            chance = ch.GetAttackChance(4);
            if( MUDMath.NumberPercent() < chance )
            {
                ch.PracticeSkill( "fourth attack" );
                SingleAttack(ch, victim, skill, ObjTemplate.WearLocation.hand_one);
                if( ch.Fighting != victim )
                {
                    return false;
                }
            }

            // Check for dual wield.  May want to allow a second swing when dual wielding.
            // We'll wait and see what combat looks like before we decide - Xangis
            wield = Object.GetEquipmentOnCharacter( ch, ObjTemplate.WearLocation.hand_two );
            if( wield )
            {
                if( wield.HasWearFlag( ObjTemplate.WEARABLE_WIELD ) )
                {
                    ch.PracticeSkill( "dual wield" );
                    if (ch.IsNPC())
                    {
                        chance = ch.Level;
                    }
                    else
                    {
                        if (((PC)ch).SkillAptitude.ContainsKey("dual wield"))
                        {
                            chance = ((PC)ch).SkillAptitude["dual wield"] * 2 / 3;
                        }
                        else
                        {
                            chance = 0;
                        }
                    }
                    chance += ch.IsClass(CharClass.Names.ranger) ? 10 : 0;
                    if( MUDMath.NumberPercent() < chance )
                    {
                        SingleAttack(ch, victim, skill, ObjTemplate.WearLocation.hand_two);
                    }
                }
                if( ch.Fighting != victim )
                {
                    return false;
                }
            }

            // Check for fourth arm on thrikreen
            if( ch.GetRace() == Race.RACE_THRIKREEN && ( wield = Object.GetEquipmentOnCharacter( ch, ObjTemplate.WearLocation.hand_four ) ) )
            {
                if( wield.HasWearFlag( ObjTemplate.WEARABLE_WIELD ) )
                {
                    ch.PracticeSkill( "dual wield" );
                    chance = ch.IsNPC() ? ( ch.Level * 3 / 2 + 20 ) : ( (PC)ch ).SkillAptitude[ "dual wield" ];
                    if( chance > 95 )
                    {
                        chance = 95;
                    }
                    if( MUDMath.NumberPercent() < chance )
                    {
                        SingleAttack(ch, victim, skill, ObjTemplate.WearLocation.hand_four);
                    }
                }
                if( ch.Fighting != victim )
                {
                    return false;
                }
            }

            // Don't hurt a corpse.
            if( victim.CurrentPosition == Position.dead || victim.Hitpoints < -10 )
            {
                StopFighting( ch, false );
                return true;
            }

            return false;
        }
Exemple #20
0
        /// <summary>
        /// Test for special abilities based on an attacker's race.
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="victim"></param>
        /// <param name="skill"></param>
        /// <returns></returns>
        static bool CheckRaceSpecial( CharData ch, CharData victim, string skill )
        {
            if( !MUDString.StringsNotEqual( Race.RaceList[ ch.GetRace() ].Name, "Earth Elemental" ) )
            {
                SingleAttack(ch, victim, skill, ObjTemplate.WearLocation.hand_one);
                if( MUDMath.NumberPercent() < 9 )
                {
                    Spell.SpellList["dust blast"].Invoke(ch, ch.Level, victim );
                }
                else if( MUDMath.NumberPercent() < 6 )
                {
                    Spell.SpellList["pebble"].Invoke(ch, ch.Level, victim );
                }
                else if( MUDMath.NumberPercent() < 3 )
                {
                    Spell.SpellList["dirt cloud"].Invoke(ch, ch.Level, victim);
                }
                return true;
            }

            if( !MUDString.StringsNotEqual( Race.RaceList[ ch.GetRace() ].Name, "Fire Elemental" ) )
            {
                SingleAttack(ch, victim, skill, ObjTemplate.WearLocation.hand_one);
                if( MUDMath.NumberPercent() < 9 )
                {
                    Spell.SpellList["fire bolt"].Invoke(ch, ch.Level, victim );
                }
                else if( MUDMath.NumberPercent() < 6 )
                {
                    Spell.SpellList["burning hands"].Invoke(ch, ch.Level, victim );
                }
                else if( MUDMath.NumberPercent() < 3 )
                {
                    Spell.SpellList["spark"].Invoke(ch, ch.Level, victim);
                }
                return true;
            }

            if( !MUDString.StringsNotEqual( Race.RaceList[ ch.GetRace() ].Name, "Air Elemental" ) )
            {
                SingleAttack(ch, victim, skill, ObjTemplate.WearLocation.hand_one);
                if( MUDMath.NumberPercent() < 9 )
                {
                    Spell.SpellList["ice bolt"].Invoke(ch, ch.Level, victim);
                }
                else if( MUDMath.NumberPercent() < 6 )
                {
                    Spell.SpellList["cutting breeze"].Invoke(ch, ch.Level, victim);
                }
                else if( MUDMath.NumberPercent() < 3 )
                {
                    Spell.SpellList["cutting breeze"].Invoke(ch, ch.Level, victim);
                }
                return true;
            }

            if( !MUDString.StringsNotEqual( Race.RaceList[ ch.GetRace() ].Name, "Water Elemental" ) )
            {
                SingleAttack(ch, victim, skill, ObjTemplate.WearLocation.hand_one);
                if( MUDMath.NumberPercent() < 9 )
                {
                    Spell.SpellList["water bolt"].Invoke(ch, ch.Level, victim);
                }
                else if( MUDMath.NumberPercent() < 6 )
                {
                    Spell spell = Spell.SpellList["chill touch"];
                    if (spell != null)
                    {
                        spell.Invoke(ch, ch.Level, victim);
                    }
                }
                else if( MUDMath.NumberPercent() < 3 )
                {
                    Spell.SpellList["water blast"].Invoke(ch, ch.Level, victim);
                }
                return true;
            }

            if( !MUDString.StringsNotEqual( Race.RaceList[ ch.GetRace() ].Name, "Dragon" ) )
            {
                if( MUDMath.NumberPercent() < ch.Level )
                {
                    return true;
                }
            }

            return false;
        }
Exemple #21
0
        /// <summary>
        /// Create an instance of a mobile from the provided template.
        /// </summary>
        /// <param name="mobTemplate"></param>
        /// <returns></returns>
        public static CharData CreateMobile( MobTemplate mobTemplate )
        {
            int count;

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

            CharData mob = new CharData();

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

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

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

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

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

            mob.Hitpoints = mob.GetMaxHit();

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

            // Insert in list.
            CharList.Add( mob );
            // Increment count of in-game instances of mob.
            mobTemplate.NumActive++;
            return mob;
        }
Exemple #22
0
        /*
        * Compute xp for a kill.
        * Also adjust alignment of killer.
        * Edit this function to change xp computations.
        */
        static int ComputeExperience( CharData killer, CharData victim )
        {
            int percent = 100;
            int sign;
            int alignDir;

            // Uses a semi-exponential table called ExperienceTable.Table
            // no exp is awarded for anything 20 levels below you.
            // exp is reduced by 10% per level of the creature below you
            // for the first 9 levels, and then another 1% for the next 9 levels.
            // It actually counts down starting at 91%.
            /* If victim is lower level */
            if( victim.Level < killer.Level )
            {
                /* If victim is less than 10 levels below */
                if( killer.Level - victim.Level < 10 )
                {
                    percent = 101 - ( ( killer.Level - victim.Level ) * 10 );
                }
                /* If victim is less than 20 levels below */
                else if( killer.Level - victim.Level < 20 )
                {
                    percent = 20 - ( killer.Level - victim.Level );
                }
                else
                {
                    percent = 0;
                }
            }
            /* If victim is over 10 levels over */
            else if( victim.Level > ( killer.Level + 10 ) && killer.Level <= 20 )
            {
                // Experience penalty for killing stuff way higher than you, 33 level difference and you
                // get about nothing.
                // Tweaked this slightly, 96 % at 10 levels above, 96% at 10 levels, etc
                percent = 129 - ( ( victim.Level - killer.Level ) * 4 );
                if( percent < 2 )
                    percent = 2;
            }
            else
                percent += ( victim.Level - killer.Level );

            if( killer.Alignment > 0 )
                sign = 1;
            else
                sign = -1;
            if( victim.Alignment > 0 )
                alignDir = -1;
            else
                alignDir = 1;
            int chance = Math.Abs( killer.Alignment - victim.Alignment ) - sign * killer.Alignment;
            chance /= 10;
            if( chance < 0 )
                chance *= -1;
            if( killer.Level > victim.Level )
                chance -= ( killer.Level - victim.Level );
            chance = Macros.Range( 0, chance, 100 );

            string lbuf = String.Format( "ComputeExperience: {0} has a {1} chance of gaining {2} align.",
                                         killer.Name, chance, alignDir );
            ImmortalChat.SendImmortalChat( null, ImmortalChat.IMMTALK_SPAM, 0, lbuf );
            if( MUDMath.NumberPercent() < chance && killer.Alignment != -1000 )
            {
                killer.Alignment += alignDir;
                if( killer.Alignment <= -1000 )
                    killer.SendText( "&+RThe d&+rarkside t&+lakes over...&n\r\n" );
            }

            killer.Alignment = Macros.Range( -1000, killer.Alignment, 1000 );

            // 25% bonus for sanctuary
            if (victim.IsAffected(Affect.AFFECT_SANCTUARY))
            {
                percent = ( percent * 5 ) / 4;
            }

            // 10% bonus for fireshield
            if( victim.IsAffected( Affect.AFFECT_FIRESHIELD ) )
            {
                percent = ( percent * 11 ) / 10;
            }

            // 12.5% bonus for an armed opponent
            Object obj = Object.GetEquipmentOnCharacter( victim, ObjTemplate.WearLocation.hand_one );
            if( obj )
            {
                percent = ( percent * 9 ) / 8;
            }

            // 8.25% bonus for secondary weapon
            obj = Object.GetEquipmentOnCharacter( victim, ObjTemplate.WearLocation.hand_two );
            if( obj )
            {
                percent = ( percent * 13 ) / 12;
            }

            // 10% bonus for racially hated mobs
            if( MUDString.NameContainedIn( Race.RaceList[ victim.GetRace() ].Name, Race.RaceList[ killer.GetOrigRace() ].Hate ) )
            {
                percent = ( percent * 11 ) / 10;
            }

            // 10% penalty for killing same race
            if( victim.GetRace() == killer.GetOrigRace() )
            {
                percent = ( percent * 9 ) / 10;
            }

            // Lowbie experience bonus was eliminated since the ExperienceTable.Table
            // made it no longer necessary

            if( victim.IsNPC() )
            {
                // 5% bonus for aggros
                if( victim.HasActionBit(MobTemplate.ACT_AGGRESSIVE ) )
                {
                    percent = ( percent * 21 ) / 20;
                }

                // 50% penalty for killing shopkeepers
                if( victim.MobileTemplate.ShopData != null )
                    percent = percent / 2;

                // No bonus for special function #1 because they get that by having a class.
                // 10% bonus for each extra special function.
                int count = victim.SpecialFunction.Count;
                percent = ( percent * ( 10 + count ) ) / 10;
            }
            else
            {
                // Player-vs-player experience
                //
                // Killing a level 1-5 makes you lose a small amount of experience
                // and you get no experience for anyone under level 10.
                //
                // Those 11-20 are worth one fifth experience.
                if( victim.Level < 6 )
                {
                    killer.SendText( "You killed a newbie!  You feel like a twink!\r\n" );
                    return (victim.Level - 6);
                }
                if( victim.Level < 11 )
                {
                    return 0;
                }
                if( victim.Level < 20 )
                {
                    percent /= 5;
                }
                else
                {
                    percent *= 2;
                }

                if( !killer.IsRacewar( victim ) )
                {
                    if( !killer.HasActionBit( PC.PLAYER_BOTTING ))
                    {
                        killer.SendText("You gain no experience for killing your own side.\r\n");
                        return 0;
                    }
                    // Same-side bot kills are worth normal experience.
                    killer.SendText("You gain experience for vanquishing an automaton.\r\n");
                }
                else if( killer.HasActionBit( PC.PLAYER_BOTTING ))
                {
                    // Racewar bot kills.  50% bonus exp.
                    killer.SendText("You gain bonus experience for killing an automaton.\r\n");
                    percent = percent * 3/2;
                }
            }

            int xp = ( percent * ExperienceTable.Table[ victim.Level ].MobExperience ) / 100;
            xp = Math.Max( 0, xp );
            return xp;
        }
Exemple #23
0
        /// <summary>
        /// Try to find hidden things.
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="str"></param>
        public static void Search(CharData ch, string[] str)
        {
            if( ch == null ) return;

            Room toRoom;
            Exit reverseExit;
            Exit exit = null;
            Object obj;
            bool isArg;
            Exit.Direction door;

            if (ch.InRoom == null)
            {
                ch.SendText("There's no searching to be done here.\r\n");
                return;
            }

            /* Calculate the probability that ch finds something. */
            int chance = ch.GetCurrInt() * 35 / 100;
            chance += ch.GetCurrWis() * 35 / 100;
            chance += ch.GetCurrLuck() * 10 / 100;

            // Dwarves, being natural architects, can search better - Xangis
            if (ch.GetRace() == Race.RACE_DWARF)
                chance += 25;

            if (chance > 95)
                chance = 95;
            if (chance < 10)
                chance = 10;

            /* Searching with arguments. */
            if (str.Length != 0)
            {
                isArg = true;
                obj = ch.GetObjHere(str[0]);
                if (obj == null)
                {
                    ch.SendText("You don't see that object here.\r\n");
                    return;
                }
                switch (obj.ItemType)
                {
                    case ObjTemplate.ObjectType.quiver:
                    case ObjTemplate.ObjectType.container:
                    case ObjTemplate.ObjectType.npc_corpse:
                    case ObjTemplate.ObjectType.pc_corpse:
                        if (Macros.IsSet(obj.Values[1], ObjTemplate.CONTAINER_CLOSED.Vector))
                        {
                            SocketConnection.Act("$p&n is closed.", ch, obj, null, SocketConnection.MessageTarget.character);
                            return;
                        }
                        break;
                    default:
                        ch.SendText("That is not a container!\r\n");
                        return;
                }
            }
            else
            {
                isArg = false;
                obj = null;
            }

            /* Lag ch from searching. */
            if (ch.Level < Limits.LEVEL_AVATAR)
            {
                ch.WaitState(MUDMath.FuzzyNumber(18));
            }

            List<Object> list;
            if (obj != null)
            {
                list = obj.Contains;
            }
            else
            {
                list = ch.InRoom.Contents;
            }
            foreach (Object obj2 in list)
            {
                if (obj2.HasFlag(ObjTemplate.ITEM_SECRET) && chance > MUDMath.NumberPercent()
                        && obj2.FlyLevel == ch.FlightLevel)
                {
                    obj2.RemoveFlag(ObjTemplate.ITEM_SECRET);
                    SocketConnection.Act("You find $p&n.", ch, obj2, null, SocketConnection.MessageTarget.character);
                    SocketConnection.Act("$n&n points out $p&n!", ch, obj, null, SocketConnection.MessageTarget.room);
                    return;
                }
            }

            /* Look for a hidden exit. */
            door = Exit.Direction.invalid;
            for (int doornum = 0; doornum <= Limits.MAX_DIRECTION; doornum++)
            {
                /* If there's a secret exit that leads to a room. */
                exit = ch.InRoom.GetExit((Exit.Direction)doornum);
                if (exit && exit.HasFlag(Exit.ExitFlag.secret) && exit.TargetRoom)
                {
                    door = (Exit.Direction)doornum;
                    break;
                }
            }

            if (isArg)
            {
                door = Exit.Direction.invalid;
            }
            if (door != Exit.Direction.invalid)
            {
                if (exit == null)
                {
                    Log.Error("Command.Search: null exit found", 0);
                    return;
                }
                if (exit.TargetRoom == null)
                {
                    Log.Error("Command.Search: exit to null room found", 0);
                    return;
                }
                if (MUDMath.NumberPercent() < chance)
                {
                    if (ch.FlightLevel > 0)
                    {
                        ch.SendText("You're too high to be sure of what you saw.\r\n");
                        return;
                    }
                    ch.SendText("You found a hidden exit!\r\n");
                    SocketConnection.Act("$n&n points out a secret exit!", ch, null, null, SocketConnection.MessageTarget.room);

                    /* Search out one side. */
                    exit.RemoveFlag(Exit.ExitFlag.secret);
                    /* And the other side, if it exists. */
                    toRoom = Room.GetRoom(exit.IndexNumber);
                    if (toRoom && (reverseExit = toRoom.GetExit(Exit.ReverseDirection(door))) && (reverseExit.TargetRoom == ch.InRoom))
                    {
                        reverseExit.RemoveFlag(Exit.ExitFlag.secret);
                    }
                    return;
                }
            }

            if (!isArg)
            {
                // Chance of finding people hiding in the room
                foreach (CharData roomChar in ch.InRoom.People)
                {
                    if (!roomChar.IsAffected(Affect.AFFECT_HIDE) || roomChar.FlightLevel != ch.FlightLevel)
                        continue;
                    if (MUDMath.NumberPercent() < chance)
                    {
                        roomChar.RemoveAffect(Affect.AFFECT_HIDE);
                        /* People without DI can't search out invis hiding pplz. */
                        if (CharData.CanSee(ch, roomChar))
                        {
                            SocketConnection.Act("$n&n points out $N&n lurking here!", ch, null, roomChar, SocketConnection.MessageTarget.room);
                            SocketConnection.Act("You point out $N&n lurking here!", ch, null, roomChar, SocketConnection.MessageTarget.character);
                            SocketConnection.Act("$n&n reveals your hiding spot!", ch, null, roomChar, SocketConnection.MessageTarget.victim);
                            return;
                        }
                        roomChar.SetAffectBit(Affect.AFFECT_HIDE);
                    }
                }
            }

            ch.SendText("You find nothing new.\r\n");
            return;
        }
Exemple #24
0
        /// <summary>
        /// Turns a character into a corpse.
        /// 
        /// TODO: Add a corpse to the corpse list when a corpse is created.
        /// TODO: Also remove corpses from the corpse list when a corpse decays.
        /// </summary>
        /// <param name="ch"></param>
        static void MakeCorpse( CharData ch )
        {
            Object corpse;
            string name;
            int corpseIndexNumber;
            int timer;
            int level;

            // Need a bailout here if undead corpses are supposed to disintegrate.
            if( LeavesNoCorpse( ch ) )
            {
                return;
            }

            // Different corpse settings for players and mobs - Xangis
            if( ch.IsNPC() )
            {
                corpseIndexNumber = StaticObjects.OBJECT_NUMBER_CORPSE_NPC;
                name = ch.ShortDescription;
                timer = MUDMath.NumberRange( 15, 30 );
                level = ch.Level;  // Corpse level
            }
            else
            {
                corpseIndexNumber = StaticObjects.OBJECT_NUMBER_CORPSE_PC;
                name = ch.Name;
                timer = MUDMath.NumberRange( 180, 240 ) + ( ch.Level * 2 );
                level = ch.Level; // Corpse level
            }

            /*
            * This longwinded corpse creation routine comes about because
            * we dont want anything created AFTER a corpse to be placed
            * INSIDE a corpse.  This had caused crashes from ObjectUpdate()
            * in Object.Extract().
            */

            if( ch.GetCash() > 0 )
            {
                Object coins = Object.CreateMoney( ch.GetCopper(), ch.GetSilver(), ch.GetGold(), ch.GetPlatinum() );
                corpse = Database.CreateObject( Database.GetObjTemplate( corpseIndexNumber ), 0 );
                corpse.AddToObject( coins );
                ch.SetCoins( 0, 0, 0, 0 );
            }
            else
            {
                corpse = Database.CreateObject( Database.GetObjTemplate( corpseIndexNumber ), 0 );
            }

            corpse.Timer = timer;
            corpse.Values[ 0 ] = (int)Race.RaceList[ ch.GetRace() ].BodyParts;

            corpse.Level = level; // corpse level

            string buf = String.Format( "corpse of {0}", name );
            corpse.Name = buf;

            buf = String.Format( corpse.ShortDescription, name );
            corpse.ShortDescription = buf;

            buf = String.Format( corpse.FullDescription, name );
            corpse.FullDescription = buf;

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

                // Remove items flagged inventory-only from all corpses.
                if (obj.HasFlag(ObjTemplate.ITEM_INVENTORY))
                {
                    Log.Trace("Removing inventory-item " + obj + " from character before creating corpse: " + corpse);
                    obj.RemoveFromWorld();
                }
                else
                {
                    if (ch.IsNPC() && ch.MobileTemplate.ShopData
                            && obj.WearLocation == ObjTemplate.WearLocation.none)
                    {
                        obj.RemoveFromChar();
                        obj.RemoveFromWorld();
                    }
                    else
                    {
                        obj.RemoveFromChar();
                        corpse.AddToObject(obj);
                    }
                }
            }

            corpse.AddToRoom( ch.InRoom );
            if( !corpse.InRoom )
            {
                Log.Error( "MakeCorpse: corpse " + corpse.ToString() + " sent to null room, deleting.", 0 );
                corpse.RemoveFromWorld();
            }

            return;
        }
Exemple #25
0
        /// <summary>
        /// Sign language for Drow only.
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="str"></param>
        public static void Sign(CharData ch, string[] str)
        {
            if( ch == null ) return;

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

            if (ch.GetRace() != Race.RACE_DROW && !ch.IsImmortal())
            {
                ch.SendText("You wiggle your fingers around.\r\n");
                SocketConnection.Act("$n wiggles $s fingers around, looking foolish.", ch, null, null, SocketConnection.MessageTarget.room);
                return;
            }

            string text = String.Join(" ", str, 1, (str.Length - 1));

            // We don't want to let them know they're drunk.
            SocketConnection.Act("You sign '&n$T&n'", ch, null, text, SocketConnection.MessageTarget.character);

            text = DrunkSpeech.MakeDrunk(text, ch);
            foreach (CharData roomChar in ch.InRoom.People)
            {
                if (roomChar == ch || roomChar.IsNPC())
                    continue;

                string text2;
                if (roomChar.IsImmortal() || roomChar.GetOrigRace() == Race.RACE_DROW)
                {
                    text2 = String.Format("{0} signs '&n$T&n'", ch.ShowNameTo(roomChar, true));
                }
                else
                {
                    text2 = String.Format("{0} wiggles {1} fingers around.", ch.ShowNameTo(roomChar, true),
                              ch.Gender == MobTemplate.Sex.male ? "his" :
                              ch.Gender == MobTemplate.Sex.female ? "her" : "its");
                }

                SocketConnection.Act(text, roomChar, null, text2, SocketConnection.MessageTarget.character);
            }

            //    ch.door_trigger( argument );

            return;
        }
Exemple #26
0
        /// <summary>
        /// Sends a damage message to a player.
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="victim"></param>
        /// <param name="damage"></param>
        /// <param name="skill"></param>
        /// <param name="weapon"></param>
        /// <param name="immune"></param>
        static void SendDamageMessage( CharData ch, CharData victim, int damage, string skill, ObjTemplate.WearLocation weapon, bool immune )
        {
            if( victim.CurrentPosition == Position.sleeping )
            {
                SocketConnection.Act( "$n&n has a rude awakening!", victim, null, null, SocketConnection.MessageTarget.room );
                victim.CurrentPosition = Position.resting;
                SetFighting( victim, ch );
            }

            if (skill == "bash")
            {
                SocketConnection.Act( "You send $N&n crashing to the &n&+yground&n with your powerful bash.", ch, null, victim, SocketConnection.MessageTarget.character );
                SocketConnection.Act( "$n&n's powerful bash sends you sprawling!", ch, null, victim, SocketConnection.MessageTarget.victim );
                SocketConnection.Act( "$n&n sends $N&n sprawling with a powerful bash!", ch, null, victim, SocketConnection.MessageTarget.room_vict );
                return;
            }

            if (skill == "headbutt")
            {
                if( ch != victim && damage > victim.Hitpoints + 10 )
                {
                    // a killing blow needs some nice verbage
                    SocketConnection.Act( "You swiftly split $N&n's skull with your forehead, sending &+Rblood&n&+r and brains&n flying!",
                        ch, null, victim, SocketConnection.MessageTarget.character );
                    SocketConnection.Act( "$n&n rears back and splits $N&n's skull with $s forehead!", ch, null, victim, SocketConnection.MessageTarget.everyone_but_victim );
                    SocketConnection.Act( "&+RBlood&n&+r and brains&n splatter everywhere as $N&n goes limp and collapses.",
                        ch, null, victim, SocketConnection.MessageTarget.everyone_but_victim );
                    SocketConnection.Act( "$n&n's forehead smashes into you, crushing your skull and bringing on a wave of &+Lblackness&n.",
                        ch, null, victim, SocketConnection.MessageTarget.victim );
                    //deal some decent damage
                }
                else if( ch != victim && damage > 100 )
                {
                    // a pretty nasty headbutt
                    SocketConnection.Act( "Your headbutt smashes into $N&n's skull.", ch, null, victim, SocketConnection.MessageTarget.character );
                    SocketConnection.Act( "$n&n's headbutt smashes into $N&n's skull.", ch, null, victim, SocketConnection.MessageTarget.everyone_but_victim );
                    SocketConnection.Act( "$n&n's head smashes into you, sending you reeling.", ch, null, victim, SocketConnection.MessageTarget.victim );
                    //deal some decent damage
                }
                else if( ch != victim )
                {
                    SocketConnection.Act( "$n&n's headbutt leaves a red welt on $N&n's forehead.", ch,
                        null, victim, SocketConnection.MessageTarget.everyone_but_victim );
                    SocketConnection.Act( "Your headbutt leaves a red welt on $N&n's forehead.", ch,
                        null, victim, SocketConnection.MessageTarget.character );
                    SocketConnection.Act( "$n&n's headbutt leaves a red welt on your forehead.", ch,
                        null, victim, SocketConnection.MessageTarget.victim );
                }

                /* left the damage to self messages in the Command.Headbutt() function
                * because they are a little too tricky to implement through
                * this function */
                return;
            }

            if (skill == "bodyslam" && ch != victim)
            {
                SocketConnection.Act( "You bodyslam $N&n!", ch, null, victim, SocketConnection.MessageTarget.character );
                SocketConnection.Act( "$n&n bodyslams you!\r\nYou are stunned!", ch, null, victim, SocketConnection.MessageTarget.victim );
                SocketConnection.Act( "$n&n bodyslams $N&n.", ch, null, victim, SocketConnection.MessageTarget.room_vict );
            }

            if (skill == "instant kill")
            {
                switch( MUDMath.NumberRange( 1, 3 ) )
                {
                    case 1:
                    case 2:
                        SocketConnection.Act( "You place your weapon in the back of $N&n, resulting in some strange noises, some blood, and a corpse!", ch, null, victim, SocketConnection.MessageTarget.character );
                        SocketConnection.Act( "You realize you should have kept your vital organs somewhere safe as $n&n stabs you to death.", ch, null, victim, SocketConnection.MessageTarget.victim );
                        SocketConnection.Act( "$n&n places $s weapon in the back of $N&n, resulting in some strange noises, some blood, and a corpse!", ch, null, victim, SocketConnection.MessageTarget.room_vict );
                        break;
                    case 3:
                        SocketConnection.Act( "You place your weapon in the back of $N&n with such force that it comes out the other side!", ch, null, victim, SocketConnection.MessageTarget.character );
                        SocketConnection.Act( "$n&n ends your life with a well-placed backstab.", ch, null, victim, SocketConnection.MessageTarget.victim );
                        SocketConnection.Act( "$n&n places $s weapon in the back of $N&n with such force that it comes out the other side!", ch, null, victim, SocketConnection.MessageTarget.room_vict );
                        break;
                }
                return;
            }

            // Multiple backstab messages, feel free to add more.
            if (skill == "backstab" && damage > 0)
            {
                switch( MUDMath.NumberRange( 1, 4 ) )
                {
                    case 1:
                        SocketConnection.Act( "$N&n howls in agony as you pierce $S backbone!", ch, null, victim, SocketConnection.MessageTarget.character );
                        SocketConnection.Act( "You howl in agony as you feel &+rpain&n in your back!", ch, null, victim, SocketConnection.MessageTarget.victim );
                        SocketConnection.Act( "$N&N howls in agony as $n&n pierces $S backbone!", ch, null, victim, SocketConnection.MessageTarget.room_vict );
                        break;
                    case 2:
                        SocketConnection.Act( "You place your $p&n silently and skillfully through the spine of $N&n.", ch, Object.GetEquipmentOnCharacter( ch, weapon ), victim, SocketConnection.MessageTarget.character );
                        SocketConnection.Act( "Your spine feels $p&n neatly slicing through it.", ch, Object.GetEquipmentOnCharacter( ch, weapon ), victim, SocketConnection.MessageTarget.victim );
                        SocketConnection.Act( "$n&n places $s $p&n into $N&n's back!", ch, Object.GetEquipmentOnCharacter( ch, weapon ), victim, SocketConnection.MessageTarget.room_vict );
                        break;
                    case 3:
                        SocketConnection.Act( "Blood flies everywhere as you stab $N&n in the back!", ch, null, victim, SocketConnection.MessageTarget.character );
                        SocketConnection.Act( "You feel a sharp stabbing sensation in your back!", ch, null, victim, SocketConnection.MessageTarget.victim );
                        SocketConnection.Act( "Blood flies everywhere as $n&n places $s $p&n into $N&n's back!", ch, Object.GetEquipmentOnCharacter( ch, weapon ), victim, SocketConnection.MessageTarget.room_vict );
                        break;
                    case 4:
                        SocketConnection.Act( "You smile with perverse pleasure as your $p&n plunges through $N&n's soft tissue, piercing vital organs.", ch, Object.GetEquipmentOnCharacter( ch, weapon ), victim, SocketConnection.MessageTarget.character );
                        SocketConnection.Act( "$n&n smiles with perverse pleasure as $s $p&n plunges through $N&n's soft tissue, piercing vital organs.", ch, Object.GetEquipmentOnCharacter( ch, weapon ), victim, SocketConnection.MessageTarget.victim );
                        SocketConnection.Act( "$n&n smile with perverse pleasure as $s $p&n plunges through $N&n's soft tissue, piercing vital organs.", ch, Object.GetEquipmentOnCharacter( ch, weapon ), victim, SocketConnection.MessageTarget.room_vict );
                        break;

                }
                return;
            }
            if (skill == "poison weapon" || skill == "poison"
                    || skill == "poison bite")
                return;

            string vp1;
            string attack;
            string buf1;
            string buf2;
            string buf3;
            string buf4;
            string buf5;

            // Adjectives based on amount of damage done.
            string adjective = String.Empty;
            if( damage > 100 )
            {
                adjective = " godly";
            }
            else if( damage > 75 )
            {
                adjective = " devastating";
            }
            else if( damage > 55 )
            {
                adjective = " mighty";
            }
            else if( damage > 40 )
            {
                adjective = " awesome";
            }
            else if( damage > 25 )
            {
                adjective = " powerful";
            }
            else if( damage > 4 )
            {
                adjective = String.Empty;
            }  // no message modifier for normal hits
            else if( damage > 2 )
            {
                adjective = " mediocre";
            }
            else if( damage > 0 )
            {
                adjective = " feeble";
            }

            string vp2 = String.Empty;
            if( damage == 0 )
            {
                vp1 = "misses";
                vp2 = String.Empty;
            }
            else
            {
                damage *= 100;
                if( victim.Hitpoints > 0 )
                    damage /= victim.Hitpoints;

                if( damage <= 1 )
                {
                    vp1 = "scratches";
                }
                else if( damage <= 2 )
                {
                    vp1 = "grazes";
                }
                else if( damage <= 3 )
                {
                    vp1 = "hits";
                }
                else if( damage <= 4 )
                {
                    vp1 = "hits";
                    vp2 = " hard";
                }
                else if( damage <= 5 )
                {
                    vp1 = "hits";
                    vp2 = " very hard";
                }
                else if( damage <= 10 )
                {
                    vp1 = "mauls";
                }
                else if( damage <= 15 )
                {
                    vp1 = "decimates";
                }
                else if( damage <= 20 )
                {
                    vp1 = "makes";
                    vp2 = " stagger in pain";
                }
                else if( damage <= 25 )
                {
                    vp1 = "maims";
                }
                else if( damage <= 30 )
                {
                    vp1 = "mutilates";
                }
                else if( damage <= 40 )
                {
                    vp1 = "disembowels";
                }
                else if( damage <= 50 )
                {
                    vp1 = "eviscerates";
                }
                else if( damage <= 75 )
                {
                    vp1 = "enshrouds";
                    vp2 = " in a mist of blood";
                }
                else
                {
                    vp1 = "beats the crap out of";
                }
            }

            string punct = ( damage <= 40 ) ? "." : "!";

            if (skill == "barehanded fighting")
            {
                if( ch.GetRace() >= Race.RaceList.Length )
                {
                    Log.Error( "SendDamageMessage:  {0} invalid race", ch.GetRace() );
                    ch.SetPermRace( 0 );
                }

                attack = Race.RaceList[ ch.GetRace() ].DamageMessage;

                buf1 = String.Format( "Your{0} {1} {2} $N&n{3}{4}", adjective, attack, vp1, vp2, punct );
                buf2 = String.Format("$n&n's{0} {1} {2} you{3}{4}", adjective, attack, vp1, vp2, punct);
                buf3 = String.Format("$n&n's{0} {1} {2} $N&n{3}{4}", adjective, attack, vp1, vp2, punct);
                buf4 = String.Format("You{0} {1} {2} yourself{3}{4}", adjective, attack, vp1, vp2, punct);
                buf5 = String.Format("$n&n's{0} {1} {2} $m{3}{4}", adjective, attack, vp1, vp2, punct);
            }
            else
            {
                if (!String.IsNullOrEmpty(skill))
                    attack = Skill.SkillList[skill].DamageText;
                else
                {
                    string buf = String.Format( "SendDamageMessage: bad damage type {0} for {1} damage caused by {2} to {3} with weapon {4}.",
                                                skill,
                                                damage,
                                                ch.Name,
                                                victim.Name,
                                                weapon );
                    Log.Error( buf, 0 );
                    skill = "barehanded fighting";
                    attack = AttackType.Table[ 0 ].Name;
                }

                if( immune )
                {
                    buf1 = String.Format("$N&n seems unaffected by your {0}!", attack);
                    buf2 = String.Format("$n&n's {0} seems powerless against you.", attack);
                    buf3 = String.Format("$N&n seems unaffected by $n&n's {0}!", attack);
                    buf4 = String.Format("Luckily, you seem immune to {0}.", attack);
                    buf5 = String.Format("$n&n seems unaffected by $s own {0}.", attack);
                }
                else
                {
                    if (skill != "barehanded fighting" && IsWieldingPoisoned(ch, weapon))
                    {
                        buf1 = String.Format("Your poisoned {0} {1} $N&n{2}{3}", attack, vp1, vp2, punct);
                        buf2 = String.Format("$n&n's poisoned {0} {1} you{2}{3}", attack, vp1, vp2, punct);
                        buf3 = String.Format("$n&n's poisoned {0} {1} $N&n{2}{3}", attack, vp1, vp2, punct);
                        buf4 = String.Format("Your poisoned {0} {1} you{2}{3}", attack, vp1, vp2, punct);
                        buf5 = String.Format("$n&n's poisoned {0} {1} $m{2}{3}", attack, vp1, vp2, punct);
                    }
                    else
                    {
                        buf1 = String.Format("Your{0} {1} {2} $N&n{3}{4}", adjective, attack, vp1, vp2, punct);
                        buf2 = String.Format("$n&n's{0} {1} {2} you{3}{4}", adjective, attack, vp1, vp2, punct);
                        buf3 = String.Format("$n&n's{0} {1} {2} $N&n{3}{4}", adjective, attack, vp1, vp2, punct);
                        buf4 = String.Format("You{0} {1} {2} yourself{3}{4}", adjective, attack, vp1, vp2, punct);
                        buf5 = String.Format("$n&n's{0} {1} {2} $m{3}{4}", adjective, attack, vp1, vp2, punct);
                    }
                }
            }

            if( victim != ch )
            {
                SocketConnection.Act( buf1, ch, null, victim, SocketConnection.MessageTarget.character, true );
                SocketConnection.Act( buf2, ch, null, victim, SocketConnection.MessageTarget.victim, true );
                SocketConnection.Act( buf3, ch, null, victim, SocketConnection.MessageTarget.room_vict, true );
            }
            else
            {
                SocketConnection.Act( buf4, ch, null, victim, SocketConnection.MessageTarget.character, true );
                SocketConnection.Act( buf5, ch, null, victim, SocketConnection.MessageTarget.room, true );
            }

            return;
        }
Exemple #27
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;
        }
Exemple #28
0
        /// <summary>
        /// Sends death cry message to current room and nearby rooms.
        /// </summary>
        /// <param name="ch"></param>
        void DeathCry( CharData ch )
        {
            int door;

            string msg = "You hear the animal shriek of $n&n's death cry.";
            Race.Parts parts = Race.RaceList[ ch.GetRace() ].BodyParts;

            if( ch == null )
            {
                Log.Error( "Death cry: death cry called with no arguments for CharData!", 0 );
                return;
            }
            if( !ch.InRoom )
            {
                Log.Error( "Death cry called with ch in no room.", 0 );
                return;
            }

            switch( MUDMath.NumberRange(1, 10))
            {
                default:
                    msg = "$n&n pitches toward the &n&+yground&n... &+Ldead&n.";
                    break;
                case 1:
                    msg = "You hear the animal shriek of $n&n's death cry.";
                    break;
                case 2:
                    msg = "$n&n splatters &n&+rbl&+Ro&n&+ro&+Rd&n all over you.";
                    break;
                case 3:
                    msg = "$n&n expires quietly.";
                    break;
                case 4:
                    msg = "$n&n dies writhing in agony.";
                    break;
            }

            string mesg = String.Format( "{0}", msg );
            SocketConnection.Act( mesg, ch, null, null, SocketConnection.MessageTarget.room );

            if( ch.IsNPC() )
                msg = "&+lA pained and guttural scream assaults your ears.&n";
            else
                msg = "&+rYour heart races as you hear a death cry nearby.&n";

            Room wasInRoom = ch.InRoom;
            for( door = 0; door < Limits.MAX_DIRECTION; door++ )
            {
                Exit exit;

                if( ( exit = wasInRoom.ExitData[ door ] ) && exit.TargetRoom && exit.TargetRoom != wasInRoom )
                {
                    ch.InRoom = Room.GetRoom(exit.IndexNumber);
                    SocketConnection.Act( msg, ch, null, null, SocketConnection.MessageTarget.room );
                }
            }
            ch.InRoom = wasInRoom;

            return;
        }
Exemple #29
0
        /*
        * Modified to up the damage and allow for a
        * chance to stun victim or self
        *   damage = (level) d2, for an average of 75 hp at level 50
        *   stun damage = (level) d3, for an average of 100 hp at level 50
        * Player vs player damage is reduced in damage()
        */
        /// <summary>
        /// Headbutt. Usable to initiate combat and during combat.
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="str"></param>
        public static void Headbutt(CharData ch, string[] str)
        {
            if( ch == null ) return;

            int chance;
            int ko;
            string text;

            /* Check player's level and class, mobs can use this skill */
            if ((!ch.HasSkill("headbutt")))
            {
                ch.SendText("Your skull is much too soft to headbutt anyone.\r\n");
                return;
            }

            if (ch.IsBlind())
            {
                return;
            }

            CharData victim = ch.Fighting;

            if (str.Length != 0)
            {
                if (!(victim = ch.GetCharRoom(str[0])) || victim.CurrentPosition == Position.dead)
                {
                    ch.SendText("They are nowhere to be seen.\r\n");
                    return;
                }
            }
            else
            {
                if (!victim || victim.CurrentPosition == Position.dead)
                {
                    ch.SendText("You aren't fighting anyone.\r\n");
                    return;
                }
            }

            /* anti headbutt me code */
            if (ch == victim)
            {
                ch.SendText("You get dizzy as you ponder the mechanics of headbutting yourself.\r\n");
                return;
            }

            if (ch.CurrentPosition < Position.fighting)
            {
                ch.SendText("You need to stand up to do that.\r\n");
                return;
            }
            /* Check size of ch vs. victim. */
            /* If ch is too small. */
            /* Made it 2 sizes */
            if (ch.CurrentSize - 2 > victim.CurrentSize)
            {
                SocketConnection.Act("You would crush such a small and delicate being with your mass.", ch, null, victim, SocketConnection.MessageTarget.character);
                return;
            }
            /* Ch 2 or more sizes larger than victim => bad! */
            if (ch.CurrentSize + 1 < victim.CurrentSize)
            {
                SocketConnection.Act("You can't reach their head!", ch, null, victim, SocketConnection.MessageTarget.character);
                SocketConnection.Act("$n&n slams $s head into your thigh.", ch, null, victim, SocketConnection.MessageTarget.victim);
                SocketConnection.Act("$n&n slams $s head into $N's thigh.", ch, null, victim, SocketConnection.MessageTarget.room_vict);

                ch.WaitState((Skill.SkillList["headbutt"].Delay * 9) / 10);
                if (victim.Fighting == null)
                {
                    Combat.SetFighting(victim, ch);
                }
                return;
            }

            ch.WaitState(MUDMath.FuzzyNumber(Skill.SkillList["headbutt"].Delay));
            ch.PracticeSkill("headbutt");

            if (!ch.Fighting)
            {
                Combat.SetFighting(ch, victim);
            }
            if (!victim.Fighting)
            {
                Combat.SetFighting(victim, ch);
            }

            /* Added a PC skill level
            */
            // Chance was over-downgraded at some point.  Was skill level - 5%,
            // then it was changed to skill level / 2 giving a level 50 a headbutt
            // success rate of about 47%.  I've upped it to 4/5 of skill level,
            // meaning that a level 50 has a success rate of 76%, which is a good
            // target success rate.  Keep in mind minotaur will have a success rate of
            // about 83%.
            if (ch.IsNPC())
            {
                chance = 50 + ch.Level;
            }
            else
            {
                chance = ((PC)ch).SkillAptitude["headbutt"] * 4 / 5;
            }

            // Minotaur headbutt bonus
            if (ch.GetRace() == Race.RACE_MINOTAUR)
            {
                chance += 7;
            }

            if (victim.CurrentPosition < Position.fighting)
            {
                chance /= 3;
            }

            if (MUDMath.NumberPercent() < chance)
            /*  Headbutt successful, possible KO */
            {
                /* First give the victim a chance to dodge */
                if (Combat.CheckDodge(ch, victim))
                {
                    return;
                }
                /* OK, lets settle for stun right now
                * a skill level of 100% has a 20% chance of stun
                * a skill level of 50% has a 2.5% chance of stun
                * a skill level of 23% has a 1% chance of stun
                * immortals get a 15% bonus
                */
                // The stun math was bad.  Stun was way more often that it should have
                // been.  Now we have a flat /4 chance, meaning a the following stun chances
                // at each skill level:
                // 25 = 5%  50 = 10 %  75 = 15%  95 = 19%
                ko = chance / 4;
                if (ch.IsImmortal())
                {
                    ko += 15;
                }
                text = String.Format("Commandheadbutt: {0}&n attempting a KO with {1}%% chance.", ch.Name, ko);
                ImmortalChat.SendImmortalChat(null, ImmortalChat.IMMTALK_SPAM, 0, text);
                if (MUDMath.NumberPercent() < ko + 1)
                {
                    // deal some decent damage
                    // This was previously level d 3 which was fairly pathetic.
                    // Level d 8 = 50 min, 400 max at level 50 with an average of 225
                    // PvP damage is quartered, so headbutt will do about 56 against a player.
                    if (ch.GetRace() != Race.RACE_MINOTAUR)
                    {
                        Combat.InflictDamage(ch, victim, MUDMath.Dice(ch.Level, 8), "headbutt", ObjTemplate.WearLocation.none, AttackType.DamageType.bludgeon);
                    }
                    else
                    {
                        Combat.InflictDamage(ch, victim, MUDMath.Dice(ch.Level, 9), "headbutt", ObjTemplate.WearLocation.none, AttackType.DamageType.bludgeon);
                    }
                    if (victim.CurrentPosition > Position.stunned)
                    {
                        SocketConnection.Act("$n&n staggers about, then collapses in a heap.", victim, null, null, SocketConnection.MessageTarget.room);
                        victim.SendText("You fall to the ground &+Wstunned&n.\r\n");
                        SocketConnection.Act("$n&n is &+Wstunned!&n", victim, null, null, SocketConnection.MessageTarget.room);
                        victim.CurrentPosition = Position.stunned;
                        victim.WaitState((Skill.SkillList["headbutt"].Delay));
                        text = String.Format("Commandheadbutt: {0}&n stunned {1}&n.", ch.Name, victim.Name);
                        ImmortalChat.SendImmortalChat(null, ImmortalChat.IMMTALK_SPAM, 0, text);
                    }
                }
                else
                {
                    // just your ordinary headbutt damage
                    // This was previously level d 2 which was fairly pathetic.
                    // Level d 6 = 50 min, 300 max at level 50 with an average of 175
                    // PvP damage is quartered, so headbutt will do about 43 against a player.
                    if (ch.GetRace() != Race.RACE_MINOTAUR)
                    {
                        if (!Combat.InflictDamage(ch, victim, MUDMath.Dice(ch.Level, 6), "headbutt", ObjTemplate.WearLocation.none, AttackType.DamageType.bludgeon))
                        {
                            // Someone blasts you in the head it'll definitely stun you for 3/4 of a second.
                            victim.WaitState(3);
                        }
                    }
                    else
                    {
                        if (!Combat.InflictDamage(ch, victim, MUDMath.Dice(ch.Level, 7), "headbutt", ObjTemplate.WearLocation.none, AttackType.DamageType.bludgeon))
                        {
                            // Someone blasts you in the head with horns it'll definitely stun you for a second.
                            // -- Xangis
                            victim.WaitState(4);
                        }
                    }
                }
            }
            else /* Headbutt failed, possible damgage to self, possible KO of self */
            {    /* Don't allow char to kill self, just mort self */
                /* Give them a chance to not take any damage */
                // Checking chance instead of player's level.  Since this should be based on skill
                // this should be about right (average of 24% chance of screwing yourself at level 50
                // instead of 50%, 17% chance for minos).
                if (MUDMath.NumberPercent() < chance)
                {
                    ch.SendText("Your headbutt fails to strike its target.\r\n");
                    SocketConnection.Act("$n&n tries to headbutt $N&n but can't quite connect.", ch, null,
                        victim, SocketConnection.MessageTarget.everyone_but_victim);
                    SocketConnection.Act("$n&n bobs around you in a feeble attempt at a headbutt.", ch,
                        null, victim, SocketConnection.MessageTarget.victim);
                    return;
                }
                SocketConnection.Act("You bang your head against the brick wall of $N&n.", ch, null,
                    victim, SocketConnection.MessageTarget.character);
                SocketConnection.Act("$n&n tries a headbutt but $N&n gets the best of $m.", ch, null,
                    victim, SocketConnection.MessageTarget.everyone_but_victim);
                SocketConnection.Act("$n&n bangs into you in a feeble attempt at a headbutt.", ch,
                    null, victim, SocketConnection.MessageTarget.victim);
                // KO chance of 24% for normals, 17% for minos.
                // You have to fail three checks to get your ass kicked by KO, one for the actual skill check,
                // one for the damage check and finally one for the KO check.
                // keep in mind this KO does damage of about 100 to self at level 50, which is a hell of a lot
                // for a failed skill.
                // The chance of ko'ing yourself at each skill level is as follows: (after all 3 checks)
                // Skill 25 = 59.2%  Skill 50 = 29.6%  Skill 75 = 14.4%  Skill 95 = 9.38%
                ko = 108 - chance;
                int dam;
                if (MUDMath.NumberPercent() < ko)
                {
                    // doh! This is gonna hurt
                    //deal some decent damage...to self!
                    if (ch.GetRace() != Race.RACE_MINOTAUR)
                    {
                        dam = MUDMath.Dice(ch.Level, 3);
                    }
                    else
                    {
                        dam = MUDMath.Dice(ch.Level, 2);
                    }
                    if (dam > ch.Hitpoints)
                    {
                        dam = ch.Hitpoints + 1;
                    }
                    if (Combat.InflictDamage(ch, ch, dam, "headbutt", ObjTemplate.WearLocation.none, AttackType.DamageType.bludgeon))
                    {
                        // ch invalidated, can't send messages.
                        return;
                    }
                    SocketConnection.Act("$n&n staggers about, then collapses in a heap.", ch, null, null, SocketConnection.MessageTarget.room);
                    ch.SendText("You fall to the ground stunned.\r\n");
                    SocketConnection.Act("$n&n is stunned!", ch, null, null, SocketConnection.MessageTarget.room);
                    ch.CurrentPosition = Position.stunned;
                    ch.WaitState((Skill.SkillList["headbutt"].Delay * 2));
                    text = String.Format("Commandheadbutt: {0}&n stunned self.", ch.Name);
                    ImmortalChat.SendImmortalChat(null, ImmortalChat.IMMTALK_SPAM, 0, text);
                }
                else
                {
                    // Was previously level d 2, which averaged 30 damage at 20 and 75 at 50.  PC to PC
                    // damage is not quartered when it is done to yourself, so this it kind of high at the
                    // upper levels.  This has been reduced by level / 5, so the damage at 50 averages 65
                    // instead of 65.
                    // Keep in mind that the real penalties come from KO and comparitively someone that
                    // fails a bash doesen't take insane damage.
                    dam = MUDMath.Dice(ch.Level, 2) - ch.Level / 5;
                    if (dam > ch.Hitpoints)
                    {
                        dam = ch.Hitpoints + 1;
                    }
                    Combat.InflictDamage(ch, ch, dam, "headbutt", ObjTemplate.WearLocation.none, AttackType.DamageType.bludgeon);
                }
            } //end if() headbutt failed
            return;
        }
Exemple #30
0
        /// <summary>
        /// Checks whether the object can be worn by the character and provides a message
        /// to the character if it can't be.
        /// </summary>
        /// <param name="ch"></param>
        /// <returns></returns>
        public bool IsWearableBy(CharData ch)
        {
            if (ch.IsImmortal() && ch.HasActionBit(PC.PLAYER_GODMODE))
                return true;

            if (ch.IsClass(CharClass.Names.monk))
            {
                if (_weight > (1 + (ch.Level / 15)))
                {
                    SocketConnection.Act("$p&n is too heavy for you to use.", ch, this, null, SocketConnection.MessageTarget.character);
                    return false;
                }
            }

            if (HasWearFlag(ObjTemplate.USE_ANYONE))
                return true;

            switch (ch.Gender)
            {
                case MobTemplate.Sex.male:
                    if (HasAntiFlag(ObjTemplate.USE_ANTIMALE))
                    {
                        SocketConnection.Act("$p&n is too dainty for one of such as yourself.", ch, this, null, SocketConnection.MessageTarget.character);
                        return false;
                    }
                    break;
                case MobTemplate.Sex.female:
                    if (HasAntiFlag(ObjTemplate.USE_ANTIFEMALE))
                    {
                        SocketConnection.Act("$p&n is too bulky and poorly designed for one as skilled as you.", ch, this, null, SocketConnection.MessageTarget.character);
                        return false;
                    }
                    break;
                case MobTemplate.Sex.neutral:
                    if (HasAntiFlag(ObjTemplate.USE_ANTINEUTER))
                    {
                        SocketConnection.Act("$p&n was not designed for your form.", ch, this, null, SocketConnection.MessageTarget.character);
                        return false;
                    }
                    break;
                default:
                    SocketConnection.Act("$p&n cannot be used by you because your sex is buggy.", ch, this, null, SocketConnection.MessageTarget.character);
                    return false;
            }

            switch (ch.CharacterClass.ClassNumber)
            {
                default:
                    break;
                case CharClass.Names.warrior:
                    if (!HasAntiFlag(ObjTemplate.USE_WARRIOR))
                    {
                        SocketConnection.Act("You won't abide such inferiority as found in $p&n.", ch, this, null, SocketConnection.MessageTarget.character);
                        return false;
                    }
                    break;
                case CharClass.Names.ranger:
                case CharClass.Names.hunter:
                    if (!HasAntiFlag(ObjTemplate.USE_RANGER))
                    {
                        SocketConnection.Act("Your professionalism prevents you from using $p&n.", ch, this, null, SocketConnection.MessageTarget.character);
                        return false;
                    }
                    break;
                case CharClass.Names.paladin:
                    if (!HasAntiFlag(ObjTemplate.USE_PALADIN))
                    {
                        SocketConnection.Act("Your convictions prevents you from using $p&n.", ch, this, null, SocketConnection.MessageTarget.character);
                        return false;
                    }
                    break;
                case CharClass.Names.antipaladin:
                    if (!HasAntiFlag(ObjTemplate.USE_ANTI))
                    {
                        SocketConnection.Act("Your skill and pride prevents you from using $p&n.", ch, this, null, SocketConnection.MessageTarget.character);
                        return false;
                    }
                    break;
                case CharClass.Names.cleric:
                    if (!HasAntiFlag(ObjTemplate.USE_CLERIC))
                    {
                        SocketConnection.Act("Your faith prevents you from using $p&n.", ch, this, null, SocketConnection.MessageTarget.character);
                        return false;
                    }
                    break;
                case CharClass.Names.druid:
                    if (!HasAntiFlag(ObjTemplate.USE_DRUID))
                    {
                        SocketConnection.Act("Your path prevents you from using $p&n.", ch, this, null, SocketConnection.MessageTarget.character);
                        return false;
                    }
                    break;
                case CharClass.Names.shaman:
                    if (!HasAntiFlag(ObjTemplate.USE_SHAMAN))
                    {
                        SocketConnection.Act("You lack the proper know-how to use $p&n.", ch, this, null, SocketConnection.MessageTarget.character);
                        return false;
                    }
                    break;
                case CharClass.Names.sorcerer:
                case CharClass.Names.illusionist:
                    if (!HasAntiFlag(ObjTemplate.USE_SORCERER))
                    {
                        SocketConnection.Act("You neglected use of $p&n in deference to your magics.", ch, this, null, SocketConnection.MessageTarget.character);
                        return false;
                    }
                    break;
                case CharClass.Names.elementAir:
                case CharClass.Names.elementEarth:
                case CharClass.Names.elementFire:
                case CharClass.Names.elementWater:
                    if (!HasAntiFlag(ObjTemplate.USE_ELEMENTAL))
                    {
                        SocketConnection.Act("You have better things to waste time on than $p&n.", ch, this, null, SocketConnection.MessageTarget.character);
                        return false;
                    }
                    break;
                case CharClass.Names.thief:
                    if (!HasAntiFlag( ObjTemplate.USE_THIEF))
                    {
                        SocketConnection.Act("Using $p&n would only hinder your abilities.", ch, this, null, SocketConnection.MessageTarget.character);
                        return false;
                    }
                    break;
                case CharClass.Names.psionicist:
                    if (!HasAntiFlag(ObjTemplate.USE_PSI))
                    {
                        SocketConnection.Act("The thought of using $p&n makes your brain hurt.", ch, this, null, SocketConnection.MessageTarget.character);
                        return false;
                    }
                    break;
                case CharClass.Names.assassin:
                    if (!HasAntiFlag(ObjTemplate.USE_ASSASSIN))
                    {
                        SocketConnection.Act("You never studied the art behind $p&n.", ch, this, null, SocketConnection.MessageTarget.character);
                        return false;
                    }
                    break;
                case CharClass.Names.mercenary:
                    if (!HasAntiFlag( ObjTemplate.USE_MERCENARY))
                    {
                        SocketConnection.Act("Your training never addressed using $p&n.", ch, this, null, SocketConnection.MessageTarget.character);
                        return false;
                    }
                    break;
                case CharClass.Names.mystic:
                case CharClass.Names.monk:
                    if (!HasAntiFlag( ObjTemplate.USE_MONK))
                    {
                        SocketConnection.Act("You cannot use $p&n.", ch, this, null, SocketConnection.MessageTarget.character);
                        return false;
                    }
                    break;
            }

            switch (ch.GetRace())
            {
                default:
                    break;
                case Race.RACE_HUMAN:
                    if (HasAntiFlag( ObjTemplate.USE_NOHUMAN))
                    {
                        SocketConnection.Act("Your race is ill fit to use $p&n.", ch, this, null, SocketConnection.MessageTarget.character);
                        return false;
                    }
                    break;
                case Race.RACE_GREYELF:
                    if (HasAntiFlag(ObjTemplate.USE_NOGREYELF))
                    {
                        SocketConnection.Act("Your race is too weak to handle $p&n.", ch, this, null, SocketConnection.MessageTarget.character);
                        return false;
                    }
                    break;
                case Race.RACE_HALFELF:
                    if (HasAntiFlag( ObjTemplate.USE_NOHALFELF))
                    {
                        SocketConnection.Act("Your bastardized nature prevents you from using $p&n.", ch, this, null, SocketConnection.MessageTarget.character);
                        return false;
                    }
                    break;
                case Race.RACE_DWARF:
                    if (HasAntiFlag( ObjTemplate.USE_NODWARF))
                    {
                        SocketConnection.Act("Your body wasn't designed to use $p&n.", ch, this, null, SocketConnection.MessageTarget.character);
                        return false;
                    }
                    break;
                case Race.RACE_HALFLING:
                    if (HasAntiFlag( ObjTemplate.USE_NOGNOME))
                    {
                        SocketConnection.Act("Just contemplating $p&n makes you long for food.", ch, this, null, SocketConnection.MessageTarget.character);
                        return false;
                    }
                    break;
                case Race.RACE_BARBARIAN:
                    if (HasAntiFlag( ObjTemplate.USE_NOBARBARIAN))
                    {
                        SocketConnection.Act("Your size and mass prevents you from using $p&n.", ch, this, null, SocketConnection.MessageTarget.character);
                        return false;
                    }
                    break;
                case Race.RACE_DUERGAR:
                    if (HasAntiFlag( ObjTemplate.USE_NODUERGAR))
                    {
                        SocketConnection.Act("Of what use is $p&n to a &n&+rduergar&n?", ch, this, null, SocketConnection.MessageTarget.character);
                        return false;
                    }
                    break;
                case Race.RACE_DROW:
                    if (HasAntiFlag( ObjTemplate.USE_NODROW))
                    {
                        SocketConnection.Act("The design of $p&n is too inferior for use by a &n&+mdrow&n.", ch, this, null, SocketConnection.MessageTarget.character);
                        return false;
                    }
                    break;
                case Race.RACE_TROLL:
                    if (HasAntiFlag( ObjTemplate.USE_NOTROLL))
                    {
                        SocketConnection.Act("You try to use $p&n, but become quickly frustrated.", ch, this, null, SocketConnection.MessageTarget.character);
                        return false;
                    }
                    break;
                case Race.RACE_OGRE:
                    if (HasAntiFlag( ObjTemplate.USE_NOOGRE))
                    {
                        SocketConnection.Act("You can't quite figure out how to use $p&n.", ch, this, null, SocketConnection.MessageTarget.character);
                        return false;
                    }
                    break;
                case Race.RACE_ORC:
                    if (HasAntiFlag( ObjTemplate.USE_NOORC))
                    {
                        SocketConnection.Act("Obviously, $p&n was not crafted for an &+Lorc&n.", ch, this, null, SocketConnection.MessageTarget.character);
                        return false;
                    }
                    break;
                case Race.RACE_CENTAUR:
                    if (HasAntiFlag( ObjTemplate.USE_NOCENTAUR))
                    {
                        SocketConnection.Act("Your find $p&n's design unsuitable for a &n&+gcen&+Ltaur&n.", ch, this, null, SocketConnection.MessageTarget.character);
                        return false;
                    }
                    break;
                case Race.RACE_GITHYANKI:
                    if (HasAntiFlag( ObjTemplate.USE_NOGITHYANKI))
                    {
                        SocketConnection.Act("You find $p&n to be unfitting for a &+Wgith&+Gyanki&n.", ch, this, null, SocketConnection.MessageTarget.character);
                        return false;
                    }
                    break;
                case Race.RACE_GITHZERAI:
                    if (HasAntiFlag( ObjTemplate.USE_NOGITHZERAI))
                    {
                        SocketConnection.Act("Your nature prevents you from using $p&n.", ch, this, null, SocketConnection.MessageTarget.character);
                        return false;
                    }
                    break;
                case Race.RACE_MINOTAUR:
                    if (HasAntiFlag( ObjTemplate.USE_NOMINOTAUR))
                    {
                        SocketConnection.Act("Your distinctive build prevents your use of $p&n.", ch, this, null, SocketConnection.MessageTarget.character);
                        return false;
                    }
                    break;
                case Race.RACE_GOBLIN:
                    if (HasAntiFlag( ObjTemplate.USE_NOGOBLIN))
                    {
                        SocketConnection.Act("Your stature and build make it impossible for you to use $p&n.", ch, this, null, SocketConnection.MessageTarget.character);
                        return false;
                    }
                    break;
                case Race.RACE_RAKSHASA:
                    if (HasAntiFlag( ObjTemplate.USE_NORAKSHASA))
                    {
                        SocketConnection.Act("Your feline structure inhibits you from using $p&n.", ch, this, null, SocketConnection.MessageTarget.character);
                        return false;
                    }
                    break;
                case Race.RACE_GNOLL:
                    if (HasAntiFlag( ObjTemplate.USE_NOGNOLL))
                    {
                        SocketConnection.Act("Your canine features hinder the use of $p&n.", ch, this, null, SocketConnection.MessageTarget.character);
                        return false;
                    }
                    break;
            }

            switch (ch.GetRacewarSide())
            {
                case Race.RacewarSide.good:
                    if (HasAntiFlag( ObjTemplate.USE_ANTIGOODRACE))
                    {
                        SocketConnection.Act("Your &n&+cs&+Co&n&+cu&+Cl&n is too &+Wpure&n to use $p&n.", ch, this, null, SocketConnection.MessageTarget.character);
                        return false;
                    }
                    break;
                case Race.RacewarSide.evil:
                    if (HasAntiFlag( ObjTemplate.USE_ANTIEVILRACE))
                    {
                        SocketConnection.Act("Your &+Lblack &n&+rhe&+Ra&n&+rr&+Rt&n prevents use of $p&n.", ch, this, null, SocketConnection.MessageTarget.character);
                        return false;
                    }
                    break;
                default:
                    break;
            }

            return true;
        }