| 27 | namespace TEN::Collision::Los |
| 28 | { |
| 29 | static std::vector<ItemInfo*> GetNearbyItems(const std::vector<int>& roomNumbers) |
| 30 | { |
| 31 | // Collect neighbor room numbers. |
| 32 | auto neighborRoomNumbers = std::set<int>{}; |
| 33 | for (int roomNumber : roomNumbers) |
| 34 | { |
| 35 | const auto& room = g_Level.Rooms[roomNumber]; |
| 36 | neighborRoomNumbers.insert(room.NeighborRoomNumbers.begin(), room.NeighborRoomNumbers.end()); |
| 37 | } |
| 38 | |
| 39 | // Run through neighbor rooms. |
| 40 | auto items = std::vector<ItemInfo*>{}; |
| 41 | for (int neighborRoomNumber : neighborRoomNumbers) |
| 42 | { |
| 43 | const auto& neighborRoom = g_Level.Rooms[neighborRoomNumber]; |
| 44 | if (!neighborRoom.Active()) |
| 45 | continue; |
| 46 | |
| 47 | // Run through items in room. |
| 48 | int itemNumber = neighborRoom.itemNumber; |
| 49 | while (itemNumber != NO_VALUE) |
| 50 | { |
| 51 | auto& item = g_Level.Items[itemNumber]; |
| 52 | |
| 53 | // HACK: For some reason, infinite loop may sometimes occur. |
| 54 | if (itemNumber == item.NextItem) |
| 55 | break; |
| 56 | itemNumber = item.NextItem; |
| 57 | |
| 58 | // 1) Ignore bridges (handled as part of room collision). |
| 59 | if (item.IsBridge()) |
| 60 | continue; |
| 61 | |
| 62 | // 2) Check collidability. |
| 63 | const auto& object = Objects[item.ObjectNumber]; |
| 64 | if (!item.Collidable || item.Flags & IFLAG_KILLED || |
| 65 | object.collision == nullptr || object.Hidden) |
| 66 | { |
| 67 | continue; |
| 68 | } |
| 69 | |
| 70 | // 3) Check status. |
| 71 | if (item.Status == ItemStatus::ITEM_INVISIBLE || item.Status == ItemStatus::ITEM_DEACTIVATED) |
| 72 | continue; |
| 73 | |
| 74 | items.push_back(&item); |
| 75 | } |
| 76 | } |
| 77 | |
| 78 | return items; |
| 79 | } |
| 80 | |
| 81 | static std::vector<StaticMesh*> GetNearbyStatics(const std::vector<int>& roomNumbers) |
| 82 | { |