Пример #1
0
        /// <summary>
        /// Bodyslam an opponent.  Can only be used to initiate combat.
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="str"></param>
        public static void Bodyslam(CharData ch, string[] str)
        {
            if( ch == null ) return;

            CharData victim;

            /* Check player's level and class, mobs can use this skill */
            if (!ch.HasInnate(Race.RACE_BODYSLAM))
            {
                ch.SendText("You don't feel massive enough to manhandle that.\r\n");
                return;
            }

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

            if (str.Length != 0)
            {
                if (!(victim = ch.GetCharRoom(str[0])) || victim.CurrentPosition == Position.dead)
                {
                    ch.SendText("They aren't here.\r\n");
                    return;
                }
            }
            else
            {
                ch.SendText("Bodyslam who?\r\n");
                return;
            }

            // Added size restrictions -- Xangis
            if (victim.CurrentSize > ch.CurrentSize)
            {
                if (ch.HasInnate(Race.RACE_SLAM_LARGER))
                {
                    // allowing centaurs to slam one size up if it's an ogre
                    if (victim.CurrentSize > (ch.CurrentSize + 1))
                    {
                        ch.SendText("You can't bodyslam something that much bigger than you.\r\n");
                        return;
                    }
                }
                else
                {
                    ch.SendText("You can't bodyslam something bigger than you.\r\n");
                    return;
                }
            }

            if ((ch.CurrentSize > victim.CurrentSize) && ((ch.CurrentSize - victim.CurrentSize) > 3))
            {
                ch.SendText("They're too small to slam.\r\n");
                return;
            }

            /* Bodyslam self?  Ok! */
            if (ch == victim)
            {
                ch.SendText("You slam yourself to the ground!\r\n");
                SocketConnection.Act("$n&n throws $mself to the ground in a fit of clumsiness.",
                     ch, null, victim, SocketConnection.MessageTarget.room_vict);
                ch.WaitState((Skill.SkillList["bodyslam"].Delay / 2));
                ch.CurrentPosition = Position.reclining;
                Combat.InflictDamage(ch, ch, MUDMath.NumberRange(1, 6), "bodyslam", ObjTemplate.WearLocation.none, AttackType.DamageType.bludgeon);
                return;
            }

            ch.WaitState(Skill.SkillList["bodyslam"].Delay);
            ch.PracticeSkill("bodyslam");

            int chance = (ch.Level * 3) / 2 + 15;
            chance += ch.GetCurrAgi() - victim.GetCurrAgi();
            chance -= (victim.Level - ch.Level);

            switch (victim.CurrentPosition)
            {
                case Position.dead:
                    return;
                case Position.mortally_wounded:
                    chance += 15;
                    break;
                case Position.incapacitated:
                    chance += 10;
                    break;
                case Position.unconscious:
                    chance += 5;
                    break;
                case Position.stunned:
                    chance += 3;
                    break;
                case Position.sleeping:
                    chance += 2;
                    break;
                case Position.reclining:
                    chance -= 45;
                    break;
                case Position.resting:
                    chance -= 30;
                    break;
                case Position.sitting:
                    chance -= 20;
                    break;
                case Position.kneeling:
                    chance -= 15;
                    break;
                case Position.fighting:
                case Position.standing:
                default:
                    break;
            }

            // Small penalty for the small buggers -- Xangis
            if (victim.CurrentSize < (ch.CurrentSize - 1))
            {
                chance -= 15;
            }

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

            // Shaman bodyslam penalty.
            if (ch.IsClass(CharClass.Names.shaman) || ch.IsClass(CharClass.Names.druid))
            {
                chance = (chance * 2) / 3;
            }

            if (victim.IsAffected(Affect.AFFECT_AWARE))
            {
                chance -= 15;
            }
            else if (victim.IsAffected( Affect.AFFECT_SKL_AWARE))
            {
                if (ch.HasSkill("springleap"))
                {
                    if (ch.IsNPC())
                    {
                        if (MUDMath.NumberPercent() < ((ch.Level * 3) / 2 + 15))
                        {
                            chance -= 15;
                        }
                    }
                    else if (MUDMath.NumberPercent() < ((PC)ch).SkillAptitude["awareness"])
                    {
                        ch.PracticeSkill("awareness");
                        chance -= 15;
                    }
                    else
                    {
                        ch.PracticeSkill("awareness");
                    }
                }
            }

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

            if (ch.IsNPC() || MUDMath.NumberPercent() < chance)
            {
                if (victim.IsAffected( Affect.AFFECT_SINGING))
                {
                    victim.RemoveAffect(Affect.AFFECT_SINGING);
                    SocketConnection.Act("$n&n suddenly loses track of the key $e was singing in.", victim, null, null, SocketConnection.MessageTarget.room);
                    victim.SendText("You get the wind knocked out of you!\r\n");
                }
                if (victim.IsAffected( Affect.AFFECT_CASTING))
                {
                    victim.RemoveAffect(Affect.AFFECT_CASTING);
                    SocketConnection.Act("$n&n's thoughts of casting are scattered about as $e is slammed into the ground.", victim, null, null, SocketConnection.MessageTarget.room);
                    victim.SendText("Your brain slamming against your skull disrupts your concentration.\r\n");
                }
                // Moved damage to bottom because it would crash when a person died, because
                // it still tried to access them as a valid character.  Also added tumble check for
                // thieves.
                if (!Combat.CheckTumble(victim))
                {
                    victim.WaitState(Skill.SkillList["bodyslam"].Delay);
                    victim.CurrentPosition = Position.reclining;
                    Combat.InflictDamage(ch, victim, MUDMath.NumberRange(1, ch.Level), "bodyslam", ObjTemplate.WearLocation.none, AttackType.DamageType.bludgeon);
                }
                else
                {
                    if (!Combat.InflictDamage(ch, victim, MUDMath.NumberRange(1, (ch.Level / 3)), "bodyslam", 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.", ch, null, null, SocketConnection.MessageTarget.room);
                    }
                }
            }
            else
            {
                ch.Hitpoints -= MUDMath.NumberRange(1, 5);
                SocketConnection.Act("As $N&n avoids your slam, you smack headfirst into the &n&+yground&n.", ch, null, victim, SocketConnection.MessageTarget.character);
                SocketConnection.Act("$n&n throws $mself to the &n&+yground&n in a fit of clumsiness.", ch, null, victim, SocketConnection.MessageTarget.victim);
                SocketConnection.Act("$n&n misses a bodyslam on $N&n and slams $s head into the &n&+yground&n.", ch, null, victim, SocketConnection.MessageTarget.room_vict);
                ch.CurrentPosition = Position.reclining;
            }

            return;
        }
Пример #2
0
        /// <summary>
        /// Innate command.  Shows and activates innate abilitiies.
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="str"></param>
        public static void Innate(CharData ch, string[] str)
        {
            if( ch == null ) return;

            string text;
            Affect af = new Affect();

            // Use innates here
            if (str.Length > 0 && !String.IsNullOrEmpty(str[0]))
            {
                if (!MUDString.IsPrefixOf(str[0], "strength"))
                {
                    if (ch.HasInnate(Race.RACE_STRENGTH))
                    {
                        if (ch.IsAffected(Affect.AFFECT_STRENGTH_INCREASED))
                        {
                            ch.SendText("You are already affected by strength.");
                            return;
                        }
                        if (ch.HasInnateTimer(InnateTimerData.Type.strength))
                        {
                            ch.SendText("You need to rest a bit first.\r\n");
                            return;
                        }

                        af.Type = Affect.AffectType.spell;
                        af.Value = "strength";
                        af.Duration = MUDMath.Dice(8, 5);
                        af.AddModifier(Affect.Apply.strength, MUDMath.Dice(2, 4) + 15);
                        af.SetBitvector(Affect.AFFECT_STRENGTH_INCREASED);
                        ch.AddAffect(af);
                        ch.SendText("You feel stronger.\r\n");
                        ch.AddInnateTimer(InnateTimerData.Type.strength, 24);

                        ch.WaitState(14);

                    }
                    else
                    {
                        ch.SendText("You don't know how to do that.\r\n");
                        return;
                    }
                }
                else if (!MUDString.IsPrefixOf(str[0], "levitate"))
                {
                    if (ch.HasInnate(Race.RACE_LEVITATE))
                    {
                        if (ch.IsAffected( Affect.AFFECT_LEVITATE))
                        {
                            ch.SendText("You are already levitating.");
                            return;
                        }
                        if (ch.HasInnateTimer(InnateTimerData.Type.levitate))
                        {
                            ch.SendText("You need to rest a bit first.\r\n");
                            return;
                        }

                        af.Type = Affect.AffectType.spell;
                        af.Value = "levitation";
                        af.Duration = MUDMath.Dice(8, 5);
                        af.SetBitvector(Affect.AFFECT_LEVITATE);
                        ch.AddAffect(af);
                        ch.SendText("Your feet rise off the ground.\r\n");
                        ch.AddInnateTimer(InnateTimerData.Type.levitate, 24);

                        ch.WaitState(6);
                    }
                    else
                    {
                        ch.SendText("You don't know how to do that.\r\n");
                        return;
                    }
                }
                else if (!MUDString.IsPrefixOf(str[0], "faerie"))
                {
                    if (ch.HasInnate(Race.RACE_FAERIE_FIRE))
                    {
                        CharData victim = ch.GetCharRoom(str[0]);

                        if (victim == null)
                            ch.SendText("You do not see them here.");
                        else
                        {
                            Spell spl = Spell.SpellList["faerie fire"];
                            if (spl != null)
                            {
                                spl.Invoke(ch, ch.Level, victim);
                            }
                        }
                    }
                    else
                    {
                        ch.SendText("You don't know how to do that.\r\n");
                        return;
                    }
                }
                else if (!MUDString.IsPrefixOf(str[0], "invisibility"))
                {
                    if (ch.HasInnate(Race.RACE_INVIS))
                    {
                        if (ch.IsAffected( Affect.AFFECT_INVISIBLE))
                        {
                            ch.SendText("You are already invisible!\r\n");
                            return;
                        }
                        if (ch.HasInnateTimer(InnateTimerData.Type.invisibility))
                        {
                            ch.SendText("You need to rest a bit first.\r\n");
                            return;
                        }

                        af.Type = Affect.AffectType.spell;
                        af.Value = "invisibility";
                        af.Duration = MUDMath.Dice(2, 8) + 4;
                        af.SetBitvector(Affect.AFFECT_INVISIBLE);

                        SocketConnection.Act("$n&n fades out of existence.", ch, null, null, SocketConnection.MessageTarget.room);
                        ch.SendText("You vanish.\r\n");

                        ch.AddAffect(af);
                        ch.AddInnateTimer(InnateTimerData.Type.invisibility, 24);

                        ch.WaitState(24);
                    }
                    else
                    {
                        ch.SendText("You don't know how to do that.\r\n");
                        return;
                    }
                }
                else if (!MUDString.IsPrefixOf(str[0], "enlarge"))
                {
                    if (ch.HasInnate(Race.RACE_ENLARGE))
                    {
                        if (ch.IsAffected(Affect.AFFECT_ENLARGED))
                        {
                            ch.SendText("You are already enlarged.\r\n");
                            return;
                        }
                        if (ch.HasInnateTimer(InnateTimerData.Type.enlarge))
                        {
                            ch.SendText("You need to rest a bit first.\r\n");
                            return;
                        }

                        af.Type = Affect.AffectType.spell;
                        af.Value = "enlarge";
                        af.Duration = MUDMath.Dice(8, 5);
                        af.AddModifier(Affect.Apply.size, 1);
                        af.SetBitvector(Affect.AFFECT_NONE);
                        ch.AddAffect(af);

                        ch.SendText("&nYou grow to almost twice your normal size!\r\n");
                        SocketConnection.Act("$n&n grows to almost twice $s normal size!&n", ch, null, null, SocketConnection.MessageTarget.room);
                        ch.AddInnateTimer(InnateTimerData.Type.enlarge, 24);

                        ch.WaitState(10);
                    }
                    else
                    {
                        ch.SendText("You don't know how to do that.\r\n");
                        return;
                    }
                }
                else if (!MUDString.IsPrefixOf(str[0], "shift"))
                {
                    if (str.Length > 1 && !MUDString.IsPrefixOf(str[1], "astral"))
                    {
                        if (ch.HasInnate(Race.RACE_SHIFT_ASTRAL))
                        {
                            if (ch.HasInnateTimer(InnateTimerData.Type.shift_astral))
                            {
                                ch.SendText("You need to rest a bit first.\r\n");
                                return;
                            }
                            Spell spell = StringLookup.SpellLookup("plane shift");
                            if (!spell)
                            {
                                ch.SendText("Something seems to be blocking your ability to shift.");
                                Log.Error("Innate Shift: 'plane shift' spell not found. Check the spells file.");
                                return;
                            }
                            spell.Invoke(ch, ch.Level, new Target(str[1]));
                            ch.AddInnateTimer(InnateTimerData.Type.shift_astral, 8);

                            ch.WaitState(10);
                        }
                        else
                        {
                            ch.SendText("You don't know how to do that.\r\n");
                            return;
                        }
                    }
                    else if (str.Length > 1 && !MUDString.IsPrefixOf(str[1], "prime"))
                    {
                        if (ch.HasInnate(Race.RACE_SHIFT_PRIME))
                        {
                            if (ch.HasInnateTimer(InnateTimerData.Type.shift_prime))
                            {
                                ch.SendText("You need to rest a bit first.\r\n");
                                return;
                            }
                            Spell spell = StringLookup.SpellLookup("plane shift");
                            if (!spell)
                            {
                                ch.SendText("Something seems to be blocking your ability to shift.");
                                Log.Error("Innate Shift: 'plane shift' spell not found. Check the spells file.");
                                return;
                            }
                            spell.Invoke(ch, ch.Level, new Target(str[1]));
                            ch.AddInnateTimer(InnateTimerData.Type.shift_prime, 8);

                            ch.WaitState(10);
                        }
                        else
                        {
                            ch.SendText("You don't know how to do that.\r\n");
                            return;
                        }
                    }
                }
                else
                {
                    ch.SendText("That's not implemented yet. :(\r\n");
                }
                return;
            }

            text = String.Format("&+BInnate abilities available to your race and class:&n\r\n");

            if (ch.HasInnate(Race.RACE_BODYSLAM))
                text += "&n  bodyslam\r\n";
            if (ch.HasInnate(Race.RACE_CHARGE))
                text += "&n  charge\r\n";
            if (ch.HasInnate(Race.RACE_FLY))
                text += "&n  fly\r\n";
            if (ch.HasInnate(Race.RACE_PASSDOOR))
                text += "&n  pass door\r\n";
            if (ch.HasInnate(Race.RACE_SWIM))
                text += "&n  swim\r\n";
            if (ch.HasInnate(Race.RACE_WATERBREATH))
                text += "&n  water breathing\r\n";
            if (ch.HasInnate(Race.RACE_INFRAVISION))
                text += "&n  infravision\r\n";
            if (ch.HasInnate(Race.RACE_ULTRAVISION))
                text += "&n  ultravision\r\n";
            if (ch.HasInnate(Race.RACE_DETECT_ALIGN)
                    || ch.IsClass(CharClass.Names.antipaladin)
                    || ch.IsClass(CharClass.Names.paladin))
                text += "&n  detect align\r\n";
            if (ch.HasInnate(Race.RACE_DETECT_INVIS))
                text += "&n  detect invis\r\n";
            if (ch.HasInnate(Race.RACE_DETECT_HIDDEN))
                text += "&n  detect hidden\r\n";
            if (ch.HasInnate(Race.RACE_MUTE))
                text += "&n  mute\r\n";
            if (ch.HasInnate(Race.RACE_DOORBASH))
                text += "&n  doorbash\r\n";
            if (ch.HasInnate(Race.RACE_SHRUG))
                text += "&n  shrug\r\n";
            if (ch.HasInnate(Race.RACE_ODSNEAK))
                text += "&n  outdoor sneak\r\n";
            if (ch.HasInnate(Race.RACE_UDSNEAK))
                text += "&n  underdark sneak\r\n";
            if (ch.HasInnate(Race.RACE_STRENGTH))
                text += "&n  strength\r\n";
            if (ch.HasInnate(Race.RACE_FAERIE_FIRE))
                text += "&n  faerie fire\r\n";
            //    if( ch.HasInnate( Race.RACE_STEAL ))
            //      buf += "&n  steal\r\n" );
            if (ch.HasInnate(Race.RACE_ENLARGE))
                text += "&n  enlarge\r\n";
            if (ch.HasInnate(Race.RACE_INVIS))
                text += "&n  invisibility\r\n";
            //    if( ch.HasInnate( Race.RACE_SUMMON_HOARDE ))
            //      buf += "&n  summon hoarde\r\n" );
            if (ch.HasInnate(Race.RACE_SHIFT_PRIME))
                text += "&n  shift prime\r\n";
            if (ch.HasInnate(Race.RACE_SHIFT_ASTRAL))
                text += "&n  shift astral\r\n";
            if (ch.HasInnate(Race.RACE_LEVITATE))
                text += "&n  levitate\r\n";
            if (ch.HasInnate(Race.RACE_BITE))
                text += "&n  bite\r\n";

            ch.SendText(text);

            return;
        }
Пример #3
0
        /// <summary>
        /// Looks at an object, mobile, or room.
        /// </summary>
        /// <param name="ch">The acting character.</param>
        /// <param name="str">Command arguments.</param>
        public static void LookCommand(CharData ch, string[] str)
        {
            if( ch == null ) return;

            // Build argument list, stripping articles.
            bool inside = false;
            List<String> args = new List<string>(str);
            for (int i = (args.Count - 1); i >= 0; i-- )
            {
                if (args[i].Equals("in", StringComparison.CurrentCultureIgnoreCase) || args[i].Equals("i", StringComparison.CurrentCultureIgnoreCase))
                {
                    args.RemoveAt(i);
                    inside = true;
                }
                else if (args[i].Equals("at", StringComparison.CurrentCultureIgnoreCase))
                {
                    args.RemoveAt(i);
                }
            }

            // If it's a mob that isn't switched, bail.
            if (ch.Socket == null)
                return;

            if (ch.CurrentPosition < Position.sleeping)
            {
                ch.SendText("&nYou can't see anything but &+Ystars&n!  See how pretty!\r\n");
                return;
            }

            if (ch.CurrentPosition == Position.sleeping)
            {
                ch.SendText("&nYou can't see anything, you're &+Lsleeping&n!  Zzz.\r\n");
                return;
            }

            if (ch.IsBlind())
                return;

            // Look panel for ships.
            if ( args.Count > 0 && args[0].Equals("panel", StringComparison.CurrentCultureIgnoreCase))
            {
                CommandType.Interpret(ch, "Lookpanel");
                return;
            }
            // Look out for ships.
            if (args.Count > 0 && args[0].Equals("out", StringComparison.CurrentCultureIgnoreCase))
            {
                CommandType.Interpret(ch, "Lookout");
                return;
            }

            Object obj;
            Exit exit;
            string pdesc;
            int number = 0;
            string output = String.Empty;

            // 'look' or 'look auto' or 'look room'
            if (args.Count == 0 || args[0].Equals( "auto", StringComparison.CurrentCultureIgnoreCase) ||
                args[0].Equals("room", StringComparison.CurrentCultureIgnoreCase))
            {
                if (ch.InRoom == null)
                {
                    ch.SendText("You are not in a room.  You are just floating in empty space.  This should never happen.  You should <petition> someone for help.\r\n");
                    Log.Error("Character executing Commandlook command from null room: " + ch.Name);
                    return;
                }
                if (ch.FlightLevel > 0)
                {
                    switch (ch.FlightLevel)
                    {
                        case CharData.FlyLevel.low:
                            ch.SendText("Hovering above ");
                            break;
                        case CharData.FlyLevel.medium:
                            ch.SendText("Flying above ");
                            break;
                        case CharData.FlyLevel.high:
                            ch.SendText("Flying high above ");
                            break;
                    }
                }
                if (!ch.HasActionBit(PC.PLAYER_GODMODE) && ch.InRoom.IsDark()
                        && !ch.HasInnate(Race.RACE_ULTRAVISION)
                        && !ch.IsAffected( Affect.AFFECT_ULTRAVISION))
                {
                    ch.SendText("&+lSomewhere\r\n");
                }
                else if (!ch.HasActionBit(PC.PLAYER_GODMODE))
                {
                    String roomOpen = String.Empty;
                    String roomClose = String.Empty;
                    if (!ch.IsNPC() && ch.Socket.Terminal == SocketConnection.TerminalType.TERMINAL_ENHANCED)
                    {
                        roomOpen = "<zone>" + ch.InRoom.Area.Name + "</zone><roomTitle>";
                        roomClose = "</roomTitle>";
                    }
                    else
                    {
                        roomClose = "&n\r\n";
                    }
                    // Added support for both manual and automatic descriptions on the worldmap.
                    if (!ch.InRoom.Area.HasFlag(Area.AREA_WORLDMAP) || ch.InRoom.Title.Length > 1)
                    {
                        output += roomOpen + ch.InRoom.Title + roomClose;
                    }
                    else
                    {
                        output += roomOpen + "No room title." + roomClose;
                    }
                }
                else
                {
                    if (!ch.IsNPC() && ch.Socket.Terminal == SocketConnection.TerminalType.TERMINAL_ENHANCED)
                    {
                        ch.SendText("<zone>" + ch.InRoom.Area.Name + "</zone>");
                    }
                    Look.ShowRoomInfo(ch, ch.InRoom);
                }

                if (!ch.IsNPC() && !ch.HasActionBit(PC.PLAYER_GODMODE) && ch.InRoom.IsDark()
                    && !ch.HasInnate(Race.RACE_ULTRAVISION) && !ch.IsAffected( Affect.AFFECT_ULTRAVISION))
                {
                    ch.SendText("&+LIt is pitch black...&n \r\n");
                    Look.ShowCharacterToCharacter(ch.InRoom.People, ch);
                    return;
                }

                if (!ch.IsNPC() && (args.Count > 0 && (args[0].Equals("room", StringComparison.CurrentCultureIgnoreCase) ||
                    args[0].Equals("auto", StringComparison.CurrentCultureIgnoreCase))))
                {
                    String roomDescOpen = String.Empty;
                    String roomDescClose = String.Empty;
                    String mapSpace = String.Empty;

                    if (!ch.IsNPC() && ch.Socket.Terminal == SocketConnection.TerminalType.TERMINAL_ENHANCED)
                    {
                        roomDescOpen = "<roomDescription>";
                        roomDescClose = "</roomDescription>";
                    }
                    else
                    {
                        roomDescClose = "&n\r\n";
                        mapSpace = "    ";
                    }
                    if( !ch.HasActionBit(PC.PLAYER_BRIEF) && !ch.InRoom.Area.HasFlag(Area.AREA_WORLDMAP))
                    {
                        // Added support for both manual and automatic descriptions on the worldmap.
                        if (ch.InRoom.Description.Length > 0)
                        {
                            output += roomDescOpen + "    " + (ch.InRoom.Description.Trim()) + roomDescClose;
                        }
                        //else if (ch._inRoom.WorldmapTerrainType < Database.SystemData.MapInfo.Length)
                        //    output += roomDescOpen + mapSpace + Database.SystemData.MapInfo[ch._inRoom.WorldmapTerrainType].RoomDescription + roomDescClose;
                        else
                        {
                            output += roomDescOpen + "    No room description." + roomDescClose;
                        }
                    }
                }
                if (!String.IsNullOrEmpty(output))
                {
                    ch.SendText(output);
                }

                if (ch.InRoom.Area.HasFlag(Area.AREA_WORLDMAP))
                {
                    if (ch.HasActionBit(PC.PLAYER_MAP))
                    {
                        Command.Worldmap(ch, null);
                    }
                    else if (!ch.IsNPC() && ch.Socket.Terminal != SocketConnection.TerminalType.TERMINAL_ENHANCED)
                    {
                        ch.SendText("\r\n");
                    }
                }

                if (ch.InRoom.HasFlag(RoomTemplate.ROOM_SILENT))
                {
                    ch.SendText("&nIt seems preternaturally quiet.\r\n");
                }

                CommandType.Interpret(ch, "exits auto");

                Look.ShowRoomAffects(ch, ch.InRoom);

                Look.ShowListToCharacter(ch.InRoom.Contents, ch, false, false);
                Look.ShowCharacterToCharacter(ch.InRoom.People, ch);
                return;
            }

            // 'look direction'
            int door = -1;
            if (args.Count > 0)
            {
                if ("north".StartsWith(args[0], StringComparison.CurrentCultureIgnoreCase))
                    door = 0;
                else if ("east".StartsWith(args[0], StringComparison.CurrentCultureIgnoreCase))
                    door = 1;
                else if ("south".StartsWith(args[0], StringComparison.CurrentCultureIgnoreCase))
                    door = 2;
                else if ("west".StartsWith(args[0], StringComparison.CurrentCultureIgnoreCase))
                    door = 3;
                else if ("up".StartsWith(args[0], StringComparison.CurrentCultureIgnoreCase))
                    door = 4;
                else if ("down".StartsWith(args[0], StringComparison.CurrentCultureIgnoreCase))
                    door = 5;
                else if ("northwest".StartsWith(args[0], StringComparison.CurrentCultureIgnoreCase))
                    door = 6;
                else if ("southwest".StartsWith(args[0], StringComparison.CurrentCultureIgnoreCase))
                    door = 7;
                else if ("northeast".StartsWith(args[0], StringComparison.CurrentCultureIgnoreCase))
                    door = 8;
                else if ("southeast".StartsWith(args[0], StringComparison.CurrentCultureIgnoreCase))
                    door = 9;
                else if ("nw".StartsWith(args[0], StringComparison.CurrentCultureIgnoreCase))
                    door = 6;
                else if ("sw".StartsWith(args[0], StringComparison.CurrentCultureIgnoreCase))
                    door = 7;
                else if ("ne".StartsWith(args[0], StringComparison.CurrentCultureIgnoreCase))
                    door = 8;
                else if ("se".StartsWith(args[0], StringComparison.CurrentCultureIgnoreCase))
                    door = 9;
            }
            if (door != -1)
            {
                // If no exit data, then return.
                exit = ch.InRoom.ExitData[door];
                if (!exit)
                {
                    ch.SendText("There's nothing to see in that direction.\r\n");
                    return;
                }

                if (exit.HasFlag(Exit.ExitFlag.walled))
                {
                    ch.SendText("There's a wall in the way.\r\n");
                    return;
                }

                // Check for farsee
                if ((ch.IsAffected( Affect.AFFECT_FARSEE) || ch.HasActionBit(PC.PLAYER_GODMODE))
                        && !exit.HasFlag(Exit.ExitFlag.closed))
                {
                    if (exit.TargetRoom)
                    {
                        Room room = ch.InRoom;
                        ch.RemoveFromRoom();
                        ch.AddToRoom(Room.GetRoom(exit.IndexNumber));
                        CommandType.Interpret(ch, "look");
                        ch.RemoveFromRoom();
                        ch.AddToRoom(room);
                        return;
                    }
                    ch.SendText("Nothing special there.\r\n");
                }

                if (exit.Description.Length != 0)
                {
                    ch.SendText(exit.Description);
                }
                else
                {
                    ch.SendText("Nothing special there.\r\n");
                }

                if (exit.Keyword.Length != 0)
                {
                    if (exit.HasFlag(Exit.ExitFlag.bashed))
                        SocketConnection.Act("The $d has been bashed from its &n&+whinges&n.",
                             ch, null, exit.Keyword, SocketConnection.MessageTarget.character);
                    else if (exit.HasFlag(Exit.ExitFlag.closed))
                        SocketConnection.Act("The $d is closed.", ch, null, exit.Keyword, SocketConnection.MessageTarget.character);
                    else if (exit.HasFlag(Exit.ExitFlag.secret))
                        SocketConnection.Act("The $d is secret.", ch, null, exit.Keyword, SocketConnection.MessageTarget.character);
                    else if (exit.HasFlag(Exit.ExitFlag.blocked))
                        SocketConnection.Act("The $d is blocked.", ch, null, exit.Keyword, SocketConnection.MessageTarget.character);
                }
                else
                {
                    if (exit.HasFlag(Exit.ExitFlag.bashed))
                    {
                        SocketConnection.Act("The door has been bashed from its &n&+whinges&n.",
                             ch, null, null, SocketConnection.MessageTarget.character);
                    }
                    else if (exit.HasFlag(Exit.ExitFlag.closed))
                        SocketConnection.Act("The door is closed.", ch, null, null, SocketConnection.MessageTarget.character);
                    else if (exit.HasFlag(Exit.ExitFlag.is_door))
                        SocketConnection.Act("The door is open.", ch, null, null, SocketConnection.MessageTarget.character);
                    else if (exit.HasFlag(Exit.ExitFlag.secret))
                        SocketConnection.Act("The door is secret.", ch, null, exit.Keyword, SocketConnection.MessageTarget.character);
                    else if (exit.HasFlag(Exit.ExitFlag.blocked))
                        SocketConnection.Act("The $d is blocked.", ch, null, exit.Keyword, SocketConnection.MessageTarget.character);
                }
                // If exit found, don't keep looking.
                return;
            }

            // Look inside something ('look in').
            if (inside)
            {
                // 'look in'
                if (args.Count < 1)
                {
                    ch.SendText("Look in what?\r\n");
                    return;
                }

                obj = ch.GetObjHere(args[0]);
                if (!obj)
                {
                    ch.SendText("You do not see that here.\r\n");
                    return;
                }

                switch (obj.ItemType)
                {
                    default:
                        ch.SendText("That is not a container.\r\n");
                        break;

                    case ObjTemplate.ObjectType.drink_container:
                        if (obj.Values[1] == -1)
                        {
                            ch.SendText("It is full.\r\n");
                            break;
                        }

                        if (obj.Values[1] <= 0)
                        {
                            ch.SendText("It is empty.\r\n");
                            break;
                        }

                        output += "It's ";
                        if (obj.Values[1] < obj.Values[0] / 4)
                            output += "less than half";
                        else if (obj.Values[1] < (3 * obj.Values[0] / 4))
                            output += "about half";
                        else if (obj.Values[1] < obj.Values[0])
                            output += "more than half";
                        else
                            output += "completely";
                        output += " full of a " + Liquid.Table[obj.Values[2]].Color + "liquid.\r\n";

                        ch.SendText(output);
                        break;

                    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))
                        {
                            ch.SendText("It is closed.\r\n");
                            break;
                        }

                        SocketConnection.Act("$p&n contains:", ch, obj, null, SocketConnection.MessageTarget.character, true);
                        Look.ShowListToCharacter(obj.Contains, ch, true, true);
                        break;
                    case ObjTemplate.ObjectType.portal:
                        SocketConnection.Act("A $p&n leads to:", ch, obj, null, SocketConnection.MessageTarget.character);
                        output += Room.GetRoom(obj.Values[0]).Title + "\r\n";
                        output += Room.GetRoom(obj.Values[0]).Description;
                        output += "\r\n";
                        ch.SendText(output);
                        break;
                }
                return;
            }

            // Look at another char.
            if (args.Count > 0)
            {
                CharData victim = ch.GetCharRoom(args[0]);
                if (victim != null)
                {
                    Look.ShowCharacterToCharacterFull(victim, ch);
                    return;
                }
            }

            // Look at an object.
            if (args.Count > 0)
            {
                // Check inventory.
                obj = ch.GetObjCarrying(args[0]);
                // If not in inventory, check eq.
                if (obj == null)
                    obj = ch.GetObjWear(args[0]);
                // If not on character, check room.
                if (obj == null)
                    obj = Object.GetObjFromList(ch.InRoom.Contents, ch, args[0]);
                // If object found, show it to the char.
                if (obj != null)
                {
                    pdesc = (Database.GetExtraDescription(args[0], obj.ExtraDescription));
                    if (pdesc.Length != 0)
                    {
                        ch.SendText(pdesc);
                    }
                    else if ((pdesc = (Database.GetExtraDescription(args[0], obj.ObjIndexData.ExtraDescriptions))).Length > 0)
                    {
                        ch.SendText(pdesc);
                    }
                    else if (obj.FullDescription.Length > 0)
                    {
                        ch.SendText(obj.FullDescription);
                        ch.SendText("\r\n");
                    }
                    if (obj.HasAffect(Affect.AffectType.skill, "poison weapon"))
                    {
                        if (ch.IsClass(CharClass.Names.thief) || ch.IsClass(CharClass.Names.assassin)
                                || MUDMath.NumberPercent() < ch.GetCurrInt() / 2)
                            ch.SendText("It has a &+Gsickly &+Lcolored&n hue.\r\n");
                    }
                    return;
                }
            }

            // Look at an object in the room
            if (args.Count > 0)
            {
                int count = 0;
                foreach (Object iobj in ch.InRoom.Contents)
                {
                    if (CharData.CanSeeObj(ch, iobj))
                    {
                        pdesc = (Database.GetExtraDescription(args[0], iobj.ExtraDescription));
                        if (pdesc.Length != 0)
                        {
                            if (++count == number)
                            {
                                ch.SendText(pdesc);
                                return;
                            }
                            continue;
                        }
                        pdesc = (Database.GetExtraDescription(args[0], iobj.ObjIndexData.ExtraDescriptions));
                        if (pdesc.Length != 0)
                        {
                            if (++count == number)
                            {
                                ch.SendText(pdesc);
                                return;
                            }
                            continue;
                        }
                        if (MUDString.NameContainedIn(args[0], iobj.Name))
                        {
                            if (++count == number)
                            {
                                ch.SendText(iobj.FullDescription);
                                ch.SendText("\r\n");
                                return;
                            }
                            continue;
                        }
                    }
                }
            }

            // Check for room extra descriptions
            if (args.Count > 0)
            {
                pdesc = (Database.GetExtraDescription(args[0], ch.InRoom.ExtraDescriptions));
                if (!String.IsNullOrEmpty(pdesc))
                {
                    ch.SendText(pdesc);
                    return;
                }
            }

            ch.SendText("You do not see that here.\r\n");
            return;
        }
Пример #4
0
        /// <summary>
        /// Shows available room exits.
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="str"></param>
        public static void Exits(CharData ch, string[] str)
        {
            if( ch == null ) return;

            Exit exit;
            int door;

            bool auto = (str.Length != 0 && !MUDString.StringsNotEqual(str[0], "auto"));

            if (ch.IsBlind() || !ch.InRoom)
            {
                return;
            }

            string text;
            if (!ch.IsNPC() && ch.Socket.Terminal == SocketConnection.TerminalType.TERMINAL_ENHANCED && auto)
            {
                text = "<exits>";
            }
            else
            {
                text = auto ? "&+cExits: &n" : "&+cVisible exits:&n\r\n";
            }

            bool found = false;

            // Show the direction with an asterisk if it
            // has a closed door, and in exits command it shows up as a
            // closed <whatever>.
            for (door = 0; door < Limits.MAX_DIRECTION; ++door)
            {
                exit = ch.InRoom.ExitData[door];
                if (exit && exit.TargetRoom)
                {
                    if (exit.HasFlag(Exit.ExitFlag.secret))
                    {
                        /* Mortals do not see secret exits. */
                        if (ch.Level < Limits.LEVEL_AVATAR)
                            continue;
                        /* Mark secret exits for immortals. */
                        text += "&+LS&n&+c";
                    }
                    if (exit.HasFlag(Exit.ExitFlag.blocked))
                    {
                        /* Mortals do not see secret exits. */
                        if (ch.Level < Limits.LEVEL_AVATAR)
                            continue;
                        /* Mark secret exits for immortals. */
                        text += "&+yB&n&+c";
                    }
                    found = true;
                    if (auto)
                    {
                        if (exit.HasFlag(Exit.ExitFlag.walled) && exit.HasFlag(Exit.ExitFlag.illusion))
                            continue;
                        if (exit.HasFlag(Exit.ExitFlag.closed))
                            text += "&n&+y#&n&+c";
                        // Don't show exits to impassable rooms.
                        // Show a yellow exclamation point to those with holylight on though.
                        if (exit.TargetRoom && exit.TargetRoom.TerrainType == TerrainType.underground_impassable)
                        {
                            if (!ch.HasActionBit(PC.PLAYER_GODMODE))
                            {
                                continue;
                            }
                            text += "&+Y!&n";
                        }
                        text += door.ToString();
                        text += " ";
                    }
                    else
                    {
                        if (exit.HasFlag(Exit.ExitFlag.walled))
                        {
                            text += String.Format("&n{0} - (Walled)&n\r\n",
                                MUDString.PadStr(door.ToString().ToUpper(), 5));
                        }
                        else if (!exit.HasFlag(Exit.ExitFlag.closed))
                        {
                            // gods with holylight on can go to useless exits.
                            if (exit.TargetRoom && exit.TargetRoom.TerrainType == TerrainType.underground_impassable)
                            {
                                if (!ch.HasActionBit(PC.PLAYER_GODMODE))
                                {
                                    continue;
                                }
                                text += "&+Y!&n";
                            }
                            text += String.Format("&n {0} - {1}&n\r\n", MUDString.PadStr(door.ToString().ToUpper(), 5),
                                    (!ch.HasInnate(Race.RACE_ULTRAVISION) && Room.GetRoom(exit.IndexNumber).IsDark())
                                      ? "&nToo dark to tell" : exit.TargetRoom.Title);
                        }
                        else
                        {
                            text += String.Format("&+y#&n{0} - Closed {1}\r\n",
                                MUDString.PadStr(door.ToString().ToUpper(), 5), exit.Keyword);
                        }
                    }
                }
            }

            if (!found)
            {
                text += auto ? " none" : "&nNone.\r\n";
            }

            if (!ch.IsNPC() && ch.Socket.Terminal == SocketConnection.TerminalType.TERMINAL_ENHANCED && auto)
            {
                text += "&n</exits>";
            }
            else if (auto)
            {
                text += "&n\r\n";
            }

            ch.SendText(text);
            return;
        }
Пример #5
0
        /// <summary>
        /// Formats an object for display to a character.
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="ch"></param>
        /// <param name="shortDisplay"></param>
        /// <returns></returns>
        public static string FormatObjectToCharacter(Object obj, CharData ch, bool shortDisplay)
        {
            string text = String.Empty;

            if (obj == null || ch == null)
            {
                Log.Error("format_obj_to_char: null ch or obj.", 0);
                return null;
            }

            if (shortDisplay)
            {
                if (obj.ShortDescription.Length > 0)
                {
                    text += obj.ShortDescription;
                }
                text += " ";
            }

            if (obj.HasFlag(ObjTemplate.ITEM_NOSHOW) && ch.IsImmortal())
            {
                text += "&n(&+LNoshow&n) ";
            }
            else if (obj.HasFlag(ObjTemplate.ITEM_NOSHOW))
            {
                return text;
            }
            if (obj.HasFlag(ObjTemplate.ITEM_INVIS))
            {
                text += "&n(&+LInvis&n) ";
            }
            if ((ch.IsAffected( Affect.AFFECT_DETECT_EVIL) || ch.HasInnate(Race.RACE_DETECT_ALIGN)
                    || ch.IsClass(CharClass.Names.antipaladin) || ch.IsClass(CharClass.Names.paladin))
                    && obj.HasFlag(ObjTemplate.ITEM_EVIL))
            {
                text += "&n(&+LDark Aura&n) ";
            }
            if ((ch.IsAffected(Affect.AFFECT_DETECT_GOOD) || ch.HasInnate(Race.RACE_DETECT_ALIGN)
                    || ch.IsClass(CharClass.Names.antipaladin) || ch.IsClass(CharClass.Names.paladin))
                    && obj.HasFlag(ObjTemplate.ITEM_BLESS))
            {
                text += "&n(&+WLight Aura&n) ";
            }
            if (obj.HasFlag(ObjTemplate.ITEM_MAGIC) && (ch.IsAffected(Affect.AFFECT_DETECT_MAGIC) ||
                (!ch.IsNPC() && ch.HasActionBit(PC.PLAYER_GODMODE))))
            {
                text += "&n(&+BMagic&n) ";
            }
            if (obj.HasFlag(ObjTemplate.ITEM_GLOW))
            {
                text += "&n(&+CGlowing&n) ";
            }
            if (obj.HasFlag(ObjTemplate.ITEM_LIT))
            {
                text += "&n(&+WIlluminating&n) ";
            }
            if (obj.HasFlag(ObjTemplate.ITEM_SECRET) && (ch.IsAffected(Affect.AFFECT_DETECT_HIDDEN) ||
                (!ch.IsNPC() && ch.HasActionBit(PC.PLAYER_GODMODE))))
            {
                text += "&n(&+yHidden&n) ";
            }

            if (!shortDisplay)
            {
                if (obj.ItemType == ObjTemplate.ObjectType.pc_corpse && (ch.IsImmortal() || (int)ch.GetRacewarSide() == obj.Values[4]))
                {
                    text += "The " + obj.ShortDescription + " is lying here.";
                }
                else if (obj.FullDescription.Length > 0)
                {
                    text += obj.FullDescription;
                }
            }

            text += "&n";

            return text;
        }
Пример #6
0
        /// <summary>
        /// Charge into someone. Helps to have horns on your head.
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="str"></param>
        public static void Charge(CharData ch, string[] str)
        {
            if( ch == null ) return;

            CharData victim;

            /* Check player's level and class, mobs can use this skill */
            if (!ch.HasInnate(Race.RACE_CHARGE))
            {
                ch.SendText("You can't do that.\r\n");
                return;
            }

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

            if (str.Length != 0)
            {
                if (!(victim = ch.GetCharRoom(str[0])) || victim.CurrentPosition == Position.dead)
                {
                    ch.SendText("They aren't here.\r\n");
                    return;
                }
            }
            else
            {
                ch.SendText("Charge who?\r\n");
                return;
            }

            /* charge me trap */
            if (ch == victim)
            {
                ch.SendText("You chase your tail for a while.\r\n");
                return;
            }

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

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

            // Chance is based on level of charger and victim.
            int chance = (ch.Level * 2) - victim.Level + 25;
            if (chance > 95)
            {
                chance = 95;
            }

            if (ch.IsNPC() || MUDMath.NumberPercent() < chance)
            {
                Combat.InflictDamage(ch, victim, MUDMath.NumberRange(1, ch.Level), "charge", ObjTemplate.WearLocation.none, AttackType.DamageType.bludgeon);
            }
            else
            {
                Combat.InflictDamage(ch, victim, 0, "charge", ObjTemplate.WearLocation.none, AttackType.DamageType.bludgeon);
            }

            return;
        }
Пример #7
0
        /// <summary>
        /// Knock a door from its hinges with brute force.
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="str"></param>
        public static void DoorBash(CharData ch, string[] str)
        {
            if( ch == null ) return;
            Exit.Direction door;
            Room toRoom;

            if (ch.IsNPC() || (!ch.HasSkill("doorbash") && !ch.HasInnate(Race.RACE_DOORBASH)))
            {
                ch.SendText("You don't feel massive enough!\r\n");
                return;
            }

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

            if (ch.Fighting)
            {
                ch.SendText("You can't break off your fight.\r\n");
                return;
            }

            if ((door = Movement.FindDoor(ch, str[0])) >= 0)
            {
                Exit reverseExit;
                int chance;

                Exit exit = ch.InRoom.GetExit(door);
                if (!exit.HasFlag(Exit.ExitFlag.closed))
                {
                    ch.SendText("Calm down. It is already open.\r\n");
                    return;
                }

                ch.WaitState(Skill.SkillList["doorbash"].Delay);

                if (ch.IsNPC())
                {
                    chance = 0;
                }
                else if (!ch.HasSkill("doorbash"))
                {
                    chance = 20;
                }
                else
                {
                    chance = ((PC)ch).SkillAptitude["doorbash"] / 2;
                }

                if (exit.HasFlag(Exit.ExitFlag.locked))
                {
                    chance /= 2;
                }

                if (exit.HasFlag(Exit.ExitFlag.bashproof) && !ch.IsImmortal())
                {
                    SocketConnection.Act("WHAAAAM!!!  You bash against the $d, but it doesn't budge.",
                         ch, null, exit.Keyword, SocketConnection.MessageTarget.character);
                    SocketConnection.Act("WHAAAAM!!!  $n&n bashes against the $d, but it holds strong.",
                         ch, null, exit.Keyword, SocketConnection.MessageTarget.room);
                    Combat.InflictDamage(ch, ch, (ch.GetMaxHit() / 20), "doorbash", ObjTemplate.WearLocation.none, AttackType.DamageType.bludgeon);
                    if (exit.HasFlag(Exit.ExitFlag.spiked))
                    {
                        SocketConnection.Act("You are impaled by spikes protruding from the $d!",
                            ch, null, exit.Keyword, SocketConnection.MessageTarget.character);
                        SocketConnection.Act("$n&n is impaled by spikes protruding from the $d!",
                            ch, null, exit.Keyword, SocketConnection.MessageTarget.room);
                        Combat.InflictDamage(ch, ch, (ch.GetMaxHit() / 5), "doorbash", ObjTemplate.WearLocation.none, AttackType.DamageType.pierce);
                    }
                    return;
                }

                if (exit.HasFlag(Exit.ExitFlag.spiked))
                {
                    SocketConnection.Act("You are impaled by spikes protruding from the $d!",
                        ch, null, exit.Keyword, SocketConnection.MessageTarget.character);
                    SocketConnection.Act("$n&n is impaled by spikes protruding from the $d!",
                        ch, null, exit.Keyword, SocketConnection.MessageTarget.room);
                    Combat.InflictDamage(ch, ch, (ch.GetMaxHit() / 5), "doorbash", ObjTemplate.WearLocation.none, AttackType.DamageType.pierce);
                }

                if ((ch.GetCurrStr() >= 20) && MUDMath.NumberPercent() < (chance + 4 * (ch.GetCurrStr() - 20)))
                {
                    /* Success */

                    exit.RemoveFlag(Exit.ExitFlag.closed);
                    if (exit.HasFlag(Exit.ExitFlag.locked))
                    {
                        exit.RemoveFlag(Exit.ExitFlag.locked);
                    }

                    exit.AddFlag(Exit.ExitFlag.bashed);

                    SocketConnection.Act("Crash!  You bashed open the $d!",
                         ch, null, exit.Keyword, SocketConnection.MessageTarget.character);
                    SocketConnection.Act("$n&n bashes open the $d!",
                         ch, null, exit.Keyword, SocketConnection.MessageTarget.room);

                    Combat.InflictDamage(ch, ch, (ch.GetMaxHit() / 30), "doorbash", ObjTemplate.WearLocation.none, AttackType.DamageType.bludgeon);

                    /* Bash through the other side */
                    if ((toRoom = Room.GetRoom(exit.IndexNumber)) && (reverseExit = toRoom.GetExit(Exit.ReverseDirection(door)))
                        && reverseExit.TargetRoom == ch.InRoom)
                    {
                        reverseExit.RemoveFlag(Exit.ExitFlag.closed);
                        if (reverseExit.HasFlag(Exit.ExitFlag.locked))
                        {
                            reverseExit.RemoveFlag(Exit.ExitFlag.locked);
                        }

                        reverseExit.AddFlag(Exit.ExitFlag.bashed);

                        foreach (CharData irch in toRoom.People)
                        {
                            SocketConnection.Act("The $d crashes open!",
                                 irch, null, reverseExit.Keyword, SocketConnection.MessageTarget.character);
                        }

                        // Have any aggro mobs on the other side come after the player.
                        foreach (CharData charData in toRoom.People)
                        {
                            if (charData != ch && (charData.IsNPC() && !charData.IsAffected( Affect.AFFECT_CHARM))
                                && charData.IsAggressive(ch) && charData.IsAwake() && CharData.CanSee(charData, ch)
                                && !charData.Fighting)
                            {
                                Combat.StartHating(charData, ch);
                                Combat.StartHunting(charData, ch);
                            }
                        }

                    }
                }
                else
                {
                    /* Failure */
                    SocketConnection.Act("OW!  You bash against the $d, but it doesn't budge.",
                         ch, null, exit.Keyword, SocketConnection.MessageTarget.character);
                    SocketConnection.Act("$n&n bashes against the $d, but it holds strong.",
                         ch, null, exit.Keyword, SocketConnection.MessageTarget.room);
                    Combat.InflictDamage(ch, ch, (ch.GetMaxHit() / 10), "doorbash", ObjTemplate.WearLocation.none, AttackType.DamageType.bludgeon);
                }
            }

            /*
            * Check for "guards"... anyone bashing a door is considered as
            * a potential aggressor, and there's a 25% chance that mobs
            * will do unto before being done unto.
            * But first...let's make sure ch ain't dead?  That'd be a pain.
            */

            if (ch.Hitpoints <= 1)
                return;

            ch.PracticeSkill("doorbash");

            foreach (CharData guardChar in ch.InRoom.People)
            {
                if (guardChar != ch && guardChar.HasActionBit(MobTemplate.ACT_PROTECTOR) && (guardChar.IsNPC() &&
                    !guardChar.IsAffected( Affect.AFFECT_CHARM)) && guardChar.IsAwake() && CharData.CanSee(guardChar, ch) &&
                    !guardChar.Fighting && MUDMath.NumberBits(2) == 0)
                {
                    SocketConnection.Act("$n&n is very unhappy about you trying to destroy the door.", guardChar, null, ch, SocketConnection.MessageTarget.victim);
                    guardChar.AttackCharacter(ch);
                }
            }
            return;
        }
Пример #8
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 );
        }
Пример #9
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;
        }
Пример #10
0
        /// <summary>
        /// When a spell event terminates, we need something to happen.
        /// 
        /// By this point we should have terminated the spell/song event data
        /// and should only need the info about the character and the spell
        /// and the argument(s).
        /// 
        /// Passing of the correct function parameters should be handled by the
        /// event system.
        /// </summary>
        /// <param name="ch">The caster</param>
        /// <param name="spell">The spell number</param>
        /// <param name="target">The _targetType</param>
        public static void FinishSpell( CharData ch, Spell spell, Target target )
        {
            Object obj;
            int chance = 0;
            bool found = false;

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

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

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

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

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

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

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

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

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

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

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

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

                    Crime.CheckAttemptedMurder( ch, victim );

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

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

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

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

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

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

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

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

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

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

            if( ( spell.ValidTargets == TargetType.singleCharacterOffensive
                    || spell.ValidTargets == TargetType.singleCharacterRanged )
                    && victim && victim.Master != ch && victim != ch && victim.IsAwake() )
            {
                if( ch.InRoom == victim.InRoom )
                {
                    if( !victim.Fighting && CharData.CanSee( victim, ch ) )
                        victim.AttackCharacter( ch );
                }
                else
                {
                    // Range spell presumably, since different rooms
                    Combat.StartGrudge( victim, ch, true );
                    foreach( CharData roomChar in ch.InRoom.People )
                    {
                        if( roomChar == victim )
                            continue;
                        if( roomChar.FlightLevel != ch.FlightLevel )
                            continue;
                        //protectors will be aggro'd
                        if (roomChar.HasActionBit(MobTemplate.ACT_PROTECTOR) && (roomChar.GetRace() == victim.GetRace()))
                        {
                            Combat.StartGrudge( roomChar, ch, true );
                        }
                        // all aggro mobs will hunt down caster
                        if (roomChar.HasActionBit(MobTemplate.ACT_AGGRESSIVE))
                        {
                            Combat.StartGrudge(roomChar, ch, true);
                        }
                    }
                }
            }
            return;
        }
Пример #11
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;
        }
Пример #12
0
        /// <summary>
        /// Handles all spellcasting, whether it be willing, singing, or casting
        /// If they got here as a bard, they're using the SING command word,
        /// if they got here as a psionicist, they're using the WILL command word,
        /// and if they got here as anything else, they're using CAST.
        ///
        /// These are just cheesy details handled by CommandType.cs... we don't care.
        /// What we do care about is that we *know* it's safe to base all our
        /// messages/decisions on the character's class.
        ///
        /// This function is also *mob-safe*, meaning that mobs can cast spells
        /// too.  However, this is not the preferred method (as far as I can tell)
        ///
        /// Shaman totems are checked for in this function.
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="argument"></param>
        public static void Cast( CharData ch, string argument )
        {
            // No casting while berzerked... Nor singing! Hah!
            if (ch.IsAffected(Affect.AFFECT_BERZERK))
            {
                ch.SendText( "Not while you're in a &+RBl&n&+ro&+Ro&n&+rd&+L Rage&n!\r\n" );
                return;
            }

            // No casting while thirsty... Nor singing! Hah!
            if (ch.IsAffected(Affect.AFFECT_THIRST) && ( ch.IsNPC() || ( (PC)ch ).Thirst < 10 ) )
            {
                ch.SendText( "&+BNo&+Ct w&+chi&+ble &+cyo&+Bu'&+cre &+Bso p&+carc&+Bhed&n!\r\n" );
                return;
            }

            String[] pieces = argument.Split( new Char[] {'\''}, StringSplitOptions.RemoveEmptyEntries);
            if (pieces.Length < 1)
            {
                ch.SendText("Spell names must always be in single quotes, such as:  cast 'magic missile' troll.\r\n");
                return;
            }
            if (pieces.Length > 1)
            {
                pieces[1] = pieces[1].Trim();
            }

            Spell spell;
            if (((spell = StringLookup.SpellLookup(pieces[0])) == null) || ((!ch.HasSpell(pieces[0])) && !ch.IsImmortal()))
            {
                ch.SendText( "You can't do that.\r\n" );
                return;
            }

            if( !CheckTotem( ch, spell ))
                return;

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

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

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

            if( !ch.InRoom.CheckCastable( ch, ch.IsClass( CharClass.Names.bard ), true) )
                return;

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

            int manaUsed = 0;
            // TODO: Rather than hard-code psionicist as a mana class, let that be set in the class files.
            if (ch.IsClass(CharClass.Names.psionicist))
            {
                manaUsed = Macros.ManaCost(ch, spell);
            }
            else if (ch.IsClass(CharClass.Names.bard))
            {
                manaUsed = spell.MinimumMana;
            }

            // Locate targets.
            if( ch.IsNPC() )
            {
                ImmortalChat.SendImmortalChat( null, ImmortalChat.IMMTALK_SPAM, 0, "Magic.Cast: Attempting to find _targetType for " + ch.ShortDescription + "&n." );
            }

            if (pieces.Length > 1)
            {
                ProcessSpellTargets(ch, spell, pieces[1]);
            }
            else
            {
                ProcessSpellTargets(ch, spell, null);
            }
        }
Пример #13
0
        /// <summary>
        /// Show a character to another character.
        /// </summary>
        /// <param name="victim"></param>
        /// <param name="ch"></param>
        public static void ShowCharacterToCharacterFull(CharData victim, CharData ch)
        {
            Object obj;
            string text = String.Empty;
            int percent;

            if (CharData.CanSee(victim, ch))
            {
                SocketConnection.Act("$n&n looks at you.", ch, null, victim, SocketConnection.MessageTarget.victim);
                if (victim != ch)
                {
                    SocketConnection.Act("$n&n looks at $N&n.", ch, null, victim, SocketConnection.MessageTarget.everyone_but_victim);
                }
                else
                {
                    SocketConnection.Act("$n&n looks at $mself.", ch, null, victim, SocketConnection.MessageTarget.everyone_but_victim);
                }
            }

            if (victim.Riding != null)
            {
                text += String.Format("&nMounted on {0}, ", victim.Riding.ShowNameTo(ch, false));
            }
            else if (victim.Rider != null)
            {
                text += String.Format("&nRidden by {0}, ", victim.Rider.ShowNameTo(ch, false));
            }

            if (!victim.IsNPC() && victim.IsGuild())
            {
                text += String.Format("&n{0} of {1}.\r\n", ((PC)victim).GuildRank.ToString().ToUpper(),
                          ((PC)victim).GuildMembership.Name);
            }

            SocketConnection.Act(text, ch, null, victim, SocketConnection.MessageTarget.character);

            if (!String.IsNullOrEmpty(victim.Description))
            {
                ch.SendText(victim.Description);
            }
            else
            {
                SocketConnection.Act("&nYou see nothing special about $M.", ch, null, victim, SocketConnection.MessageTarget.character);
            }

            if (victim.GetMaxHit() > 0)
            {
                percent = (100 * victim.Hitpoints) / victim.GetMaxHit();
            }
            else
            {
                percent = -1;
            }

            text = victim.ShowNameTo(ch, true);

            if (percent >= 100)
                text += " &nis in perfect &n&+ghealth&n.  ";
            else if (percent >= 90)
                text += " &nis slightly &n&+yscratched&n.  ";
            else if (percent >= 80)
                text += " &nhas a &+yfew bruises&n.  ";
            else if (percent >= 70)
                text += " &nhas &+Ysome cuts&n.  ";
            else if (percent >= 60)
                text += " &nhas &+Mseveral wounds&n.  ";
            else if (percent >= 50)
                text += " &nhas &+mmany nasty wounds&n.  ";
            else if (percent >= 40)
                text += " &nis &+Rbleeding freely&n.  ";
            else if (percent >= 30)
                text += " &nis &+Rcovered in blood&n.  ";
            else if (percent >= 20)
                text += " &nis &+rleaking guts&n.  ";
            else if (percent >= 10)
                text += " &nis &+ralmost dead&n.  ";
            else
                text += " &nis &+rDYING&n.  ";

            ch.SendText(text);

            // Show size on look at someone.
            text = MUDString.CapitalizeANSIString(String.Format("{0}&n is a {1} of {2} size.\r\n", victim.GetSexPronoun(),
                Race.RaceList[victim.GetRace()].ColorName, Race.SizeString(victim.CurrentSize)));
            ch.SendText(text);

            ShowAffectLines(ch, victim);

            bool found = false;
            foreach (ObjTemplate.WearLocation location in ObjTemplate.TopDownEquipment)
            {
                obj = Object.GetEquipmentOnCharacter(victim, location);
                if (obj && CharData.CanSeeObj(ch, obj))
                {
                    if (!found)
                    {
                        ch.SendText("\r\n");
                        SocketConnection.Act("&n$E is using:", ch, null, victim, SocketConnection.MessageTarget.character);
                        found = true;
                    }
                    if (obj.ItemType == ObjTemplate.ObjectType.weapon
                            && (location == ObjTemplate.WearLocation.hand_one
                                 || location == ObjTemplate.WearLocation.hand_three
                                 || location == ObjTemplate.WearLocation.hand_four
                                 || location == ObjTemplate.WearLocation.hand_two)
                            && obj.HasWearFlag(ObjTemplate.WEARABLE_WIELD))
                    {
                        if (obj.HasFlag(ObjTemplate.ITEM_TWOHANDED)
                                && !ch.HasInnate(Race.RACE_EXTRA_STRONG_WIELD))
                        {
                            ch.SendText("&+y(wielding twohanded)  &n");
                        }
                        else
                        {
                            ch.SendText("&+y(wielding)            &n");
                        }
                    }
                    else
                    {
                        if (obj.ItemType == ObjTemplate.ObjectType.shield
                                && (location == ObjTemplate.WearLocation.hand_one
                                     || location == ObjTemplate.WearLocation.hand_three
                                     || location == ObjTemplate.WearLocation.hand_four
                                     || location == ObjTemplate.WearLocation.hand_two)
                                && obj.HasWearFlag(ObjTemplate.WEARABLE_SHIELD))
                        {
                            ch.SendText("&+y(worn as shield)      &n");
                        }
                        else
                        {
                            ch.SendText(StringConversion.EquipmentLocationDisplay[(int)location]);
                        }
                    }
                    ch.SendText(FormatObjectToCharacter(obj, ch, true));
                    ch.SendText("\r\n");
                }
            }

            // Keep in mind that players can spam looking at someone in order
            // to increase their skill in peek - this will need to be fixed.
            if ((victim != ch && !ch.IsNPC()
                && ((((PC)ch).SkillAptitude.ContainsKey("peek") && MUDMath.NumberPercent() < ((PC)ch).SkillAptitude["peek"])
                || ch.Level >= Limits.LEVEL_AVATAR)) || ch.Riding == victim || ch.Rider == victim)
            {
                ch.SendText("\r\n&nYou peek at the inventory:\r\n");
                ch.PracticeSkill("peek");
                ShowListToCharacter(victim.Carrying, ch, true, true);
            }

            return;
        }
Пример #14
0
        /// <summary>
        /// Show a character to another character. This is the abbreviated version used in "look room"
        /// </summary>
        /// <param name="victim"></param>
        /// <param name="ch"></param>
        public static void ShowCharacterToCharacterAbbreviated(CharData victim, CharData ch)
        {
            string text = String.Empty;

            if (!victim || !ch)
            {
                Log.Error("ShowCharacterToCharacter0(): null ch or victim.", 0);
                return;
            }

            if (victim.Rider && victim.Rider.InRoom == ch.InRoom)
            {
                return;
            }

            // If invis, show char invis symbol first.
            if (victim.IsAffected(Affect.AFFECT_INVISIBLE))
            {
                text += "&+L*&n ";
            }

            // Show the player's description.
            if (((!ch.IsNPC() && victim.CurrentPosition == Position.standing)
                    || (victim.IsNPC() && victim.MobileTemplate != null
                        && victim.CurrentPosition == victim.MobileTemplate.DefaultPosition))
                    && (!String.IsNullOrEmpty(victim.FullDescription)) && !victim.Riding)
            {
                // Added long description does not have \r\n removed.  We may want to.
                text += victim.Description + "&n";
            }
            else
            {
                // Show the player's name.
                text += victim.ShowNameTo(ch, true) + "&n";

                // Show the player's title.
                // Show the player's race, only if PC, and on the same side of the racewar or a god.
                if (!victim.IsNPC() && ((PC)victim).Title.Length > 0)
                {
                    if (MUDString.StringsNotEqual(((PC)victim).Title, " &n") && (ch.IsNPC()))
                    {
                        text += ((PC)victim).Title;
                    }
                    if (victim.IsGuild() && (ch.IsNPC()))
                    {
                        text += " " + ((PC)victim).GuildMembership.WhoName;
                    }

                    if (!ch.IsRacewar(victim) || victim.IsImmortal() || ch.IsImmortal())
                    {
                        text += " (" + Race.RaceList[victim.GetRace()].ColorName + ")";
                    }
                }

                // Show the player's condition.
                text += " is ";
                if (victim.CurrentPosition == Position.standing && victim.CanFly())
                {
                    text += "flying";
                }
                else
                {
                    text += Position.PositionString(victim.CurrentPosition);
                }
                text += " here";
                if (victim.Fighting != null)
                {
                    text += "&n fighting ";
                    if (victim.Fighting == ch)
                    {
                        text += "&nyou!";
                    }
                    else if (victim.InRoom == victim.Fighting.InRoom)
                    {
                        text += victim.Fighting.ShowNameTo(ch, false);
                    }
                    else
                    {
                        text += "&nsomeone who left??";
                    }
                }

                if (victim.Riding && victim.Riding.InRoom == victim.InRoom)
                {
                    text += "&n, mounted on " + victim.Riding.ShowNameTo(ch, false);
                }
                text += "&n.";
            }

            if (victim.IsAffected(Affect.AFFECT_CASTING))
            {
                text += "&n&+y (casting)&n";
            }

            if (victim.IsAffected(Affect.AFFECT_MINOR_PARA))
            {
                text += "&n (&+Yparalyzed)&n";
            }
            if (!victim.IsNPC() && victim.HasActionBit(PC.PLAYER_WIZINVIS)
                    && victim.GetTrust() <= ch.GetTrust())
            {
                text += " &n&+g*&n";
            }
            if (victim.IsAffected(Affect.AFFECT_HIDE) && (ch.IsAffected(Affect.AFFECT_DETECT_HIDDEN) ||
                      ch.HasInnate(Race.RACE_DETECT_HIDDEN)))
            {
                text += " &n(&+LHiding&n)";
            }
            if (victim.IsAffected(Affect.AFFECT_CHARM) && ch.HasActionBit(PC.PLAYER_GODMODE))
            {
                text += " &n(&n&+mCharmed&n)";
            }
            if ((victim.IsAffected(Affect.AFFECT_PASS_DOOR) || victim.HasInnate(Race.RACE_PASSDOOR))
                    && ch.HasActionBit(PC.PLAYER_GODMODE))
            {
                text += " &n(&+WTranslucent&n)";
            }
            if ((victim.GetRace() == Race.RACE_UNDEAD || victim.GetRace() == Race.RACE_VAMPIRE)
                    && (ch.IsAffected( Affect.AFFECT_DETECT_UNDEAD) || ch.HasActionBit(PC.PLAYER_GODMODE)))
            {
                text += " &n(&+WPale&n)";
            }
            if (victim.IsAffected(Affect.AFFECT_FAERIE_FIRE))
            {
                text += " &n(&n&+mFa&+Me&n&+mr&+Mie&+L Aura&n)";
            }
            if (victim.IsEvil() && (ch.IsAffected(Affect.AFFECT_DETECT_EVIL)
                         || ch.HasInnate(Race.RACE_DETECT_ALIGN)
                         || ch.IsClass(CharClass.Names.paladin)
                         || ch.IsClass(CharClass.Names.antipaladin)))
            {
                text += " &n(&+rBlood&+L Aura&n)";
            }
            if (victim.IsGood() && (ch.IsAffected(Affect.AFFECT_DETECT_GOOD)
                         || ch.HasInnate(Race.RACE_DETECT_ALIGN)
                         || ch.IsClass(CharClass.Names.paladin)
                         || ch.IsClass(CharClass.Names.antipaladin)))
            {
                text += " &n(&+CLight&+L Aura&n)";
            }
            if (victim.IsAffected(Affect.AFFECT_SANCTUARY))
            {
                text += " &n(&+WWhite&+L Aura&n)";
            }
            if (!victim.IsNPC() && victim.HasActionBit(PC.PLAYER_AFK))
            {
                text += " &n&+b(&+RAFK&n&+b)&n";
            }
            if (!victim.IsNPC() && victim.HasActionBit(PC.PLAYER_BOTTING))
            {
                text += " &n&+b(&+YBot&n&+b)&n";
            }
            text += "\r\n";
            ch.SendText(text);
            return;
        }
Пример #15
0
        /// <summary>
        /// Put on a piece of equipment.
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="str"></param>
        public static void Wear(CharData ch, string[] str)
        {
            if( ch == null ) return;

            Object obj;

            if (ch.IsAffected(Affect.AFFECT_HOLD) || ch.IsAffected(Affect.AFFECT_MINOR_PARA))
            {
                ch.SendText("Your body refuses the call to movement.\r\n");
                return;
            }

            if (!ch.IsNPC() && ch.IsAffected( Affect.AFFECT_WRAITHFORM))
            {
                ch.SendText("You try, but your &n&+wghoul&n form resists your attempts.\r\n");
                return;
            }

            if (ch.Fighting || ch.CurrentPosition == Position.fighting)
            {
                ch.SendText("You can't wear stuff while you're fighting!\r\n");
                return;
            }

            if (str.Length == 0)
            {
                ch.SendText("Wear, wield, or hold what?\r\n");
                return;
            }

            if (str[0] == "all")
            {
                foreach (Object iobj in ch.Carrying)
                {
                    if (iobj.WearLocation != ObjTemplate.WearLocation.none || !CharData.CanSeeObj(ch, iobj))
                    {
                        continue;
                    }

                    if (iobj.HasWearFlag(ObjTemplate.WEARABLE_WIELD)
                            && !ch.HasInnate(Race.RACE_WEAPON_WIELD))
                    {
                        continue;
                    }

                    Object.WearObject(ch, iobj, false);
                    if (iobj.Trap != null && iobj.Trap.CheckTrigger( Trap.TriggerType.wear))
                    {
                        ch.SetOffTrap(iobj);
                        if (ch.CurrentPosition == Position.dead)
                        {
                            return;
                        }
                    }
                }
                return;
            }
            if (!(obj = ch.GetObjCarrying(str[0])))
            {
                ch.SendText("You do not have that item.\r\n");
                return;
            }

            if (obj.HasWearFlag(ObjTemplate.WEARABLE_WIELD)
                && !ch.HasInnate(Race.RACE_WEAPON_WIELD))
            {
                ch.SendText("You are not able to wield a weapon.\r\n");
                return;
            }

            Object.WearObject(ch, obj, true);
            if (obj.Trap != null && obj.Trap.CheckTrigger( Trap.TriggerType.wear))
            {
                ch.SetOffTrap(obj);
                if (ch.CurrentPosition == Position.dead)
                {
                    return;
                }
            }

            return;
        }
Пример #16
0
        /// <summary>
        /// Checks whether a character can see an objects.  Returns true if yes, false if no.
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static bool CanSeeObj( CharData ch, Object obj )
        {
            if( obj == null )
            {
                Log.Error("Calling CanSeeObj with no obj data!", 0);
                return false;
            }

            if( ch == null )
            {
                Log.Error("Calling CanSeeObj with no CharData!", 0);
                return false;
            }

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

            if (ch.IsAffected(Affect.AFFECT_BLIND) || ch.CurrentPosition <= Position.sleeping)
                return false;

            if( obj.ItemType == ObjTemplate.ObjectType.light && obj.Values[ 2 ] != 0 )
                return true;

            if( obj.HasFlag( ObjTemplate.ITEM_SECRET )
                    && !( ch.HasInnate( Race.RACE_DETECT_HIDDEN )
                         || ch.IsAffected( Affect.AFFECT_DETECT_HIDDEN ) ) )
                return false;

            if( obj.HasFlag( ObjTemplate.ITEM_INVIS )
                    && !ch.HasInnate( Race.RACE_DETECT_INVIS )
                    && !ch.IsAffected( Affect.AFFECT_DETECT_INVIS ) )
                return false;

            if( obj.HasFlag( ObjTemplate.ITEM_LIT ) )
                return true;

            if( ch.InRoom && ch.InRoom.IsDark() && !( ch.HasInnate( Race.RACE_ULTRAVISION )
                         || ch.IsAffected( Affect.AFFECT_ULTRAVISION ) ) )
                return false;

            return true;
        }
Пример #17
0
        /// <summary>
        /// Equip a weapon.  Now calls equip_hand to resolve the actual equipping 
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="str"></param>
        public static void Wield(CharData ch, string[] str)
        {
            if( ch == null ) return;

            Object obj;

            if (ch.IsAffected(Affect.AFFECT_HOLD) || ch.IsAffected( Affect.AFFECT_MINOR_PARA))
            {
                ch.SendText("Your body refuses the call to movement.\r\n");
                return;
            }

            if (!ch.IsNPC() && ch.IsAffected( Affect.AFFECT_WRAITHFORM))
            {
                ch.SendText("You try, but your &n&+wghoul&n form resists your  attempts.\r\n");
                return;
            }

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

            if (!(obj = ch.GetObjCarrying(str[0])))
            {
                ch.SendText("You do not have that item.\r\n");
                return;
            }

            if (!obj.HasWearFlag(ObjTemplate.WEARABLE_WIELD))
            {
                if (obj.ItemType == ObjTemplate.ObjectType.weapon)
                {
                    ch.SendText("That object is not usable as a weapon.\r\n");
                    return;
                }
                if (obj.ItemType == ObjTemplate.ObjectType.ranged_weapon && !obj.HasWearFlag(ObjTemplate.WEARABLE_HOLD))
                {
                    ch.SendText("That object is not usable as a missile weapon.\r\n");
                    return;
                }
                if (obj.ItemType == ObjTemplate.ObjectType.ranged_weapon)
                {
                    // Ranged weapons flagged wither wield or hold are fine to use -- Xangis
                }
                else
                {
                    ch.SendText("That object is not a weapon.\r\n");
                    return;
                }
            }

            if (!ch.HasInnate(Race.RACE_WEAPON_WIELD))
            {
                ch.SendText("You are not able to wield a weapon.\r\n");
                return;
            }

            if (!obj.IsWearableBy(ch))
                return;

            Object.EquipInHand(ch, obj, Object.EQUIP_WIELD);

            return;
        }
Пример #18
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;
        }
Пример #19
0
        /// <summary>
        /// Ask: Primarily used for quest files, but can be used in regular conversation too.
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="str"></param>
        public static void Ask(CharData ch, string[] str)
        {
            if( ch == null ) return;

            QuestTemplate quest;

            if (str.Length < 2)
            {
                ch.SendText("Ask who what?\r\n");
                return;
            }

            CharData victim = ch.GetCharRoom(str[0]);
            if (!victim)
            {
                ch.SendText("They're not here.\r\n");
                return;
            }

            if (ch.IsAffected( Affect.AFFECT_MUTE) || ch.HasInnate(Race.RACE_MUTE) || ch.InRoom.HasFlag(RoomTemplate.ROOM_SILENT))
            {
                ch.SendText("Your lips move but nothing escapes their bounds.\r\n");
                return;
            }

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

            SocketConnection.Act("$n&n asks $N&n a question.", ch, null, victim, SocketConnection.MessageTarget.everyone_but_victim);
            string buf = String.Format("&n&+c$n&n&+c asks you '&+c{0}&n&+c'&n", text);
            SocketConnection.Act(buf, ch, null, victim, SocketConnection.MessageTarget.victim);
            buf = String.Format("&n&+cYou ask $N&n&+c '{0}&n&+c'&n", text);
            SocketConnection.Act(buf, ch, null, victim, SocketConnection.MessageTarget.character);

            // players can't have talk files -- go home!
            if (!victim.IsNPC())
                return;

            bool questfound = false;
            foreach (QuestTemplate it in QuestTemplate.QuestList)
            {
                quest = it;
                if (quest.Messages == null || (quest.IndexNumber != victim.MobileTemplate.IndexNumber))
                    continue;
                foreach (TalkData message in quest.Messages)
                {
                    if (MUDString.NameContainedIn(text, message.Keywords))
                    {
                        ch.SendText("\r\n");
                        ch.SendText(message.Message);
                        questfound = true;
                    }
                }
            }

            // Only check chatterbot responses when there isn't a quest with the same keywords.
            if (!questfound && victim.ChatBot != null)
            {
                victim.ChatBot.CheckConversation(victim, ch, text);
            }
            return;
        }
Пример #20
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;
        }
Пример #21
0
        /// <summary>
        /// Shows items currently worn.
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="str"></param>
        public static void Equipment(CharData ch, string[] str)
        {
            if (ch == null) return;
            Object obj = null;
            String equipmentOpen = String.Empty;
            String equipmentClose = String.Empty;
            String separator = String.Empty;
            if (!ch.IsNPC() && ch.Socket.Terminal == SocketConnection.TerminalType.TERMINAL_ENHANCED)
            {
                equipmentOpen = "<equipment>";
                equipmentClose = "</equipment>";
                separator = ":";
            }
            else
            {
                equipmentOpen = "&nYou are using:\r\n";
                separator = "\r\n";
            }
            ch.SendText(equipmentOpen);
            bool found = false;
            foreach (ObjTemplate.WearLocation iWear in ObjTemplate.TopDownEquipment)
            {
                obj = Object.GetEquipmentOnCharacter(ch, iWear);
                if (!obj)
                    continue;

                // Added wielding
                if (obj.ItemType == ObjTemplate.ObjectType.weapon
                        && (iWear == ObjTemplate.WearLocation.hand_one
                             || iWear == ObjTemplate.WearLocation.hand_four
                             || iWear == ObjTemplate.WearLocation.hand_three
                             || iWear == ObjTemplate.WearLocation.hand_two)
                        && obj.HasWearFlag(ObjTemplate.WEARABLE_WIELD))
                {
                    if (obj.HasFlag(ObjTemplate.ITEM_TWOHANDED)
                            && !ch.HasInnate(Race.RACE_EXTRA_STRONG_WIELD))
                    {
                        if (!ch.IsNPC() && ch.Socket.Terminal == SocketConnection.TerminalType.TERMINAL_ENHANCED)
                        {
                            ch.SendText(((int)iWear).ToString() + ",");
                        }
                        else
                        {
                            ch.SendText("&+y(wielding twohanded)  &n");
                        }
                    }
                    else
                    {
                        if (!ch.IsNPC() && ch.Socket.Terminal == SocketConnection.TerminalType.TERMINAL_ENHANCED)
                        {
                            ch.SendText(((int)iWear).ToString() + ",");
                        }
                        else
                        {
                            ch.SendText("&+y(wielding)            &n");
                        }
                    }
                }
                else
                {
                    if (obj.ItemType == ObjTemplate.ObjectType.shield
                            && (iWear == ObjTemplate.WearLocation.hand_one
                                 || iWear == ObjTemplate.WearLocation.hand_four
                                 || iWear == ObjTemplate.WearLocation.hand_three
                                 || iWear == ObjTemplate.WearLocation.hand_two)
                            && obj.HasWearFlag(ObjTemplate.WEARABLE_SHIELD))
                    {
                        if (!ch.IsNPC() && ch.Socket.Terminal == SocketConnection.TerminalType.TERMINAL_ENHANCED)
                        {
                            ch.SendText(((int)iWear).ToString() + ",");
                        }
                        else
                        {
                            ch.SendText("&+y(worn as shield)      &n");
                        }
                    }
                    else
                    {
                        if (!ch.IsNPC() && ch.Socket.Terminal == SocketConnection.TerminalType.TERMINAL_ENHANCED)
                        {
                            ch.SendText(((int)iWear).ToString() + ",");
                        }
                        else
                        {
                            ch.SendText(StringConversion.EquipmentLocationDisplay[(int)iWear]);
                        }
                    }
                }
                if (CharData.CanSeeObj(ch, obj))
                {
                    ch.SendText(Look.FormatObjectToCharacter(obj, ch, true));
                    ch.SendText(separator);
                }
                else
                {
                    ch.SendText("&nsomething.\r\n");
                }
                found = true;
            }

            if (!found)
                ch.SendText("&nNothing.\r\n");

            ch.SendText(equipmentClose);

            return;
        }
Пример #22
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;
        }
Пример #23
0
        public static void ReturnToLoad( CharData ch )
        {
            if( !ch || !ch.InRoom )
                return;
            if( ch.InRoom.Area != Room.GetRoom( ch.LoadRoomIndexNumber ).Area )
                return;

            Exit.Direction dir = FindPath( ch.InRoom.IndexNumber, ch.LoadRoomIndexNumber, ch, -40000, true );

            if( dir == Exit.Direction.invalid )
            {
                return;
            }

            if( ch.InRoom.ExitData[ (int)dir ].HasFlag( Exit.ExitFlag.closed ) &&
                    !ch.IsAffected( Affect.AFFECT_PASS_DOOR ) && !ch.HasInnate( Race.RACE_PASSDOOR ) )
            {
                CommandType.Interpret(ch, "unlock " + dir.ToString());
                CommandType.Interpret(ch, "open " + dir.ToString());
                return;
            }

            ch.Move( dir );

            if( !ch.InRoom )
            {
                string text = "Return_to_load: no ch._inRoom!  Mob #" + ch.MobileTemplate.IndexNumber + ", _name: " +
                       ch.Name + ".  Placing mob in limbo (mob.AddToRoom()).";
                Log.Error( text, 0 );
                ch.AddToRoom( Room.GetRoom( StaticRooms.GetRoomNumber("ROOM_NUMBER_LIMBO") ) );
                ImmortalChat.SendImmortalChat(ch, ImmortalChat.IMMTALK_SPAM, 0, text);
                return;
            }
            return;
        }
Пример #24
0
        /// <summary>
        /// Returns a visibility value based on how well the looker can see the target.
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="victim"></param>
        /// <returns></returns>
        public static Visibility HowSee(CharData ch, CharData victim)
        {
            if (ch == null)
            {
                Log.Error("how_see called with null ch.", 0);
                return Visibility.invisible;
            }

            if (victim == null)
            {
                Log.Error("how_see called with null victim.", 0);
                return Visibility.invisible;
            }

            // Char almost dead, or asleep.
            if (ch.CurrentPosition <= Position.sleeping)
            {
                return Visibility.invisible;
            }

            // All mobiles cannot see wizinvised immortals.
            if (ch.IsNPC() && !victim.IsNPC() && victim.HasActionBit(PC.PLAYER_WIZINVIS))
            {
                return Visibility.invisible;
            }

            // Handles Immortal Invis.
            if (!victim.IsNPC() && victim.HasActionBit(PC.PLAYER_WIZINVIS)
                    && ch.GetTrust() < victim.Level)
            {
                return Visibility.invisible;
            }

            // Handles Immmortal sight.
            if (!ch.IsNPC() && ch.HasActionBit(PC.PLAYER_GODMODE))
            {
                return Visibility.visible;
            }

            // Handles blindness.
            if (ch.IsAffected(Affect.AFFECT_BLIND))
            {
                return Visibility.invisible;
            }

            // Handles regular invisibility.
            if ((victim.IsAffected(Affect.AFFECT_INVISIBLE) || victim.IsAffected(Affect.AFFECT_MINOR_INVIS)))
            {
                if (ch.HasInnate(Race.RACE_DETECT_INVIS) || ch.IsAffected(Affect.AFFECT_DETECT_INVIS)
                    || (ch.IsAffected(Affect.AFFECT_ELEM_SIGHT) && (victim.GetRace() == Race.RACE_AIR_ELE
                    || victim.GetRace() == Race.RACE_WATER_ELE || victim.GetRace() == Race.RACE_FIRE_ELE
                    || victim.GetRace() == Race.RACE_EARTH_ELE)))
                {
                    if (victim.IsAffected(Affect.AFFECT_HIDE))
                    {
                        if (ch.IsAffected(Affect.AFFECT_DETECT_HIDDEN))
                        {
                            return Visibility.visible;
                        }
                        if (ch.HasInnate(Race.RACE_DETECT_HIDDEN)
                                || ch.IsAffected(Affect.AFFECT_SENSE_LIFE))
                        {
                            return Visibility.sense_hidden;
                        }
                        return Visibility.invisible;
                    }
                    return Visibility.visible;
                }
            }

            // Handles dark rooms. Added ultracheck.
            if (victim.InRoom.IsDark())
            {
                if (ch.HasInnate(Race.RACE_ULTRAVISION) || ch.IsAffected(Affect.AFFECT_ULTRAVISION))
                {
                    return Visibility.visible;
                }
                if ((ch.HasInnate(Race.RACE_INFRAVISION) || ch.IsAffected(Affect.AFFECT_INFRAVISION))
                    && !victim.InRoom.HasFlag(RoomTemplate.ROOM_UNDERWATER))
                {
                    return Visibility.sense_infravision;
                }
                if (!(ch.HasInnate(Race.RACE_ULTRAVISION) || ch.IsAffected(Affect.AFFECT_ULTRAVISION)))
                {
                    return Visibility.too_dark;
                }
            }

            // Handles hidden people.
            if (victim.IsAffected(Affect.AFFECT_HIDE))
            {
                if (ch.IsAffected(Affect.AFFECT_DETECT_HIDDEN))
                {
                    return Visibility.visible;
                }
                if (ch.HasInnate(Race.RACE_DETECT_HIDDEN) || ch.IsAffected(Affect.AFFECT_SENSE_LIFE))
                {
                    return Visibility.sense_hidden;
                }
                return Visibility.invisible;
            }

            return Visibility.visible;
        }