#include "buildingplan.h" #include #include #include #include #include #include using namespace DFHack; bool canReserveRoom(df::building *building) { if (!building) return false; if (building->jobs.size() > 0 && building->jobs[0]->job_type == df::job_type::DestroyBuilding) return false; return building->is_room; } std::vector getUniqueNoblePositions(df::unit *unit) { std::vector np; Units::getNoblePositions(&np, unit); for (auto iter = np.begin(); iter != np.end(); iter++) { if (iter->position->code == "MILITIA_CAPTAIN") { np.erase(iter); break; } } return np; } /* * ReservedRoom */ ReservedRoom::ReservedRoom(df::building *building, std::string noble_code) { this->building = building; config = DFHack::World::AddPersistentData("buildingplan/reservedroom"); config.val() = noble_code; config.ival(1) = building->id; pos = df::coord(building->centerx, building->centery, building->z); } ReservedRoom::ReservedRoom(PersistentDataItem &config, color_ostream &) { this->config = config; building = df::building::find(config.ival(1)); if (!building) return; pos = df::coord(building->centerx, building->centery, building->z); } bool ReservedRoom::checkRoomAssignment() { if (!isValid()) return false; auto np = getOwnersNobleCode(); bool correctOwner = false; for (auto iter = np.begin(); iter != np.end(); iter++) { if (iter->position->code == getCode()) { correctOwner = true; break; } } if (correctOwner) return true; for (auto iter = df::global::world->units.active.begin(); iter != df::global::world->units.active.end(); iter++) { df::unit* unit = *iter; if (!Units::isCitizen(unit)) continue; if (!Units::isActive(unit)) continue; np = getUniqueNoblePositions(unit); for (auto iter = np.begin(); iter != np.end(); iter++) { if (iter->position->code == getCode()) { Buildings::setOwner(building, unit); break; } } } return true; } void ReservedRoom::remove() { DFHack::World::DeletePersistentData(config); } bool ReservedRoom::isValid() { if (!building) return false; if (Buildings::findAtTile(pos) != building) return false; return canReserveRoom(building); } int32_t ReservedRoom::getId() { if (!isValid()) return 0; return building->id; } std::string ReservedRoom::getCode() { return config.val(); } void ReservedRoom::setCode(const std::string &noble_code) { config.val() = noble_code; } std::vector ReservedRoom::getOwnersNobleCode() { if (!building->owner) return std::vector (); return getUniqueNoblePositions(building->owner); } /* * RoomMonitor */ std::string RoomMonitor::getReservedNobleCode(int32_t buildingId) { for (auto iter = reservedRooms.begin(); iter != reservedRooms.end(); iter++) { if (buildingId == iter->getId()) return iter->getCode(); } return ""; } void RoomMonitor::toggleRoomForPosition(int32_t buildingId, std::string noble_code) { bool found = false; for (auto iter = reservedRooms.begin(); iter != reservedRooms.end(); iter++) { if (buildingId != iter->getId()) { continue; } else { if (noble_code == iter->getCode()) { iter->remove(); reservedRooms.erase(iter); } else { iter->setCode(noble_code); } found = true; break; } } if (!found) { ReservedRoom room(df::building::find(buildingId), noble_code); reservedRooms.push_back(room); } } void RoomMonitor::doCycle() { for (auto iter = reservedRooms.begin(); iter != reservedRooms.end();) { if (iter->checkRoomAssignment()) { ++iter; } else { iter->remove(); iter = reservedRooms.erase(iter); } } } void RoomMonitor::reset(color_ostream &out) { reservedRooms.clear(); std::vector items; DFHack::World::GetPersistentData(&items, "buildingplan/reservedroom"); for (auto i = items.begin(); i != items.end(); i++) { ReservedRoom rr(*i, out); if (rr.isValid()) addRoom(rr); } } void RoomMonitor::addRoom(ReservedRoom &rr) { for (auto iter = reservedRooms.begin(); iter != reservedRooms.end(); iter++) { if (iter->getId() == rr.getId()) return; } reservedRooms.push_back(rr); } RoomMonitor roomMonitor;