#pragma once #include "90CN_seria_room_catalog.h" #include namespace dnf90_seria { inline const TownRow* FindTown(int town) { for (size_t i = 0; i < sizeof(kTowns)/sizeof(kTowns[0]); ++i) if (kTowns[i].town == town) return kTowns+i; return 0; } inline const GlyphRow* FindGlyph(int town) { for (size_t i = 0; i < sizeof(kGlyphs)/sizeof(kGlyphs[0]); ++i) if (kGlyphs[i].town == town) return kGlyphs+i; return 0; } struct Scene { uintptr_t world; int town; int area; }; inline bool Shared(const Scene& scene) { return scene.world && scene.town == 38 && scene.area == 1; } inline bool ValidOrigin(const Scene& scene) { const TownRow* row = FindTown(scene.town); return scene.world && row && scene.area >= 0 && scene.area < 64 && (row->areas & (uint64_t(1) << scene.area)) != 0; } struct Owner { uintptr_t world; int town; int region; unsigned serial; }; struct Notice { Scene before; bool bound; }; struct Lifecycle { Owner context; uintptr_t seedWorld; int seedTown; unsigned serial; void Clear() { context = Owner(); seedWorld = 0; seedTown = 0; ++serial; } void Seed(uintptr_t world, int town) { Clear(); if (world && FindTown(town)) { seedWorld = world; seedTown = town; } } bool Bind(Notice& notice, const Scene& after) { if (notice.bound || after.world != notice.before.world || !Shared(after)) return false; int town = seedWorld == after.world ? seedTown : (ValidOrigin(notice.before) ? notice.before.town : 0); seedWorld = 0; seedTown = 0; if (town) { const TownRow* row = FindTown(town); context = Owner{after.world, town, row->region, ++serial}; } else if (!(Shared(notice.before) && context.world == after.world)) { context = Owner(); ++serial; } notice.bound = true; return true; } void Finish(Notice& notice, const Scene& after) { if (!after.world || notice.before.world != after.world) return; if (!Shared(after)) Clear(); else Bind(notice, after); } }; inline bool OriginalSharedRect(const int* rect) { if (!rect) return false; for (int i = 0; i != 4; ++i) if (rect[i] != kNativeSharedProjectRect[i]) return false; return true; } // Unknown non-NULL native geometry wins. Native owner38 needs no synthetic row. inline const GlyphRow* BorrowGlyph(int town, bool nativeNull, const int* originalRect) { return (nativeNull || OriginalSharedRect(originalRect)) ? FindGlyph(town) : 0; } }