/// 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); }