Example #1
0
        /// stops infinite loops from the call to obj_to_room
        public static void obj_fall(ObjectInstance obj, bool through)
        {
            if (obj.InRoom == null || is_falling)
            {
                return;
            }

            if (fall_count > 30)
            {
                LogManager.Instance.Bug("Object falling in loop more than 30 times");
                obj.Extract();
                fall_count = 0;
                return;
            }

            if (obj.InRoom.Flags.IsSet((int)RoomFlags.NoFloor) &&
                Macros.CAN_GO(obj, (int)DirectionTypes.Down) &&
                !obj.ExtraFlags.IsSet((int)ItemExtraFlags.Magical))
            {
                var exit    = obj.InRoom.GetExit(DirectionTypes.Down);
                var to_room = exit.GetDestination();

                if (through)
                {
                    fall_count++;
                }
                else
                {
                    fall_count = 0;
                }

                if (obj.InRoom == to_room)
                {
                    LogManager.Instance.Bug("Object falling into same room {0}", to_room.ID);
                    obj.Extract();
                    return;
                }

                if (obj.InRoom.Persons.Any())
                {
                    comm.act(ATTypes.AT_PLAIN, "$p falls far below...", obj.InRoom.Persons.First(), obj, null, ToTypes.Room);
                    comm.act(ATTypes.AT_PLAIN, "$p falls far below...", obj.InRoom.Persons.First(), obj, null, ToTypes.Character);
                }

                obj.InRoom.RemoveFrom(obj);
                is_falling = true;
                to_room.AddTo(obj);
                is_falling = false;

                if (obj.InRoom.Persons.Any())
                {
                    comm.act(ATTypes.AT_PLAIN, "$p falls from above...", obj.InRoom.Persons.First(), obj, null, ToTypes.Room);
                    comm.act(ATTypes.AT_PLAIN, "$p falls from above...", obj.InRoom.Persons.First(), obj, null, ToTypes.Character);
                }

                if (!obj.InRoom.Flags.IsSet((int)RoomFlags.NoFloor) && through)
                {
                    var dam = fall_count * obj.Weight / 2;

                    // Damage players in room
                    if (obj.InRoom.Persons.Any() && SmaugRandom.D100() > 15)
                    {
                        foreach (var rch in obj.InRoom.Persons)
                        {
                            comm.act(ATTypes.AT_WHITE, "$p falls on $n!", rch, obj, null, ToTypes.Room);
                            comm.act(ATTypes.AT_WHITE, "$p falls on you!", rch, obj, null, ToTypes.Character);

                            if (rch.IsNpc() && rch.Act.IsSet((int)ActFlags.Hardhat))
                            {
                                comm.act(ATTypes.AT_WHITE, "$p bounces harmlessly off your head!", rch, obj, null,
                                         ToTypes.Character);
                            }
                            else
                            {
                                rch.CauseDamageTo(rch, dam * rch.Level, -1);
                            }
                        }
                    }

                    // Damage the falling object
                    switch (obj.ItemType)
                    {
                    case ItemTypes.Weapon:
                    case ItemTypes.Armor:
                        if (obj.Values.CurrentAC - dam <= 0)
                        {
                            if (obj.InRoom.Persons.Any())
                            {
                                comm.act(ATTypes.AT_PLAIN, "$p is destroyed in the fall!",
                                         obj.InRoom.Persons.First(), obj, null, ToTypes.Room);
                                comm.act(ATTypes.AT_PLAIN, "$p is destroyed in the fall!",
                                         obj.InRoom.Persons.First(), obj, null, ToTypes.Character);
                            }
                            ObjectFactory.CreateScraps(obj);
                        }
                        else
                        {
                            obj.Values.CurrentAC -= dam;
                        }
                        break;

                    default:
                        if (dam * 15 > obj.GetResistance())
                        {
                            if (obj.InRoom.Persons.Any())
                            {
                                comm.act(ATTypes.AT_PLAIN, "$p is destroyed in the fall!",
                                         obj.InRoom.Persons.First(), obj, null, ToTypes.Room);
                                comm.act(ATTypes.AT_PLAIN, "$p is destroyed in the fall!",
                                         obj.InRoom.Persons.First(), obj, null, ToTypes.Character);
                            }
                            ObjectFactory.CreateScraps(obj);
                        }
                        break;
                    }
                }
            }

            obj_fall(obj, true);
        }