#include class RandomTileData { public: enum Type { CHECK_NONE = 0, CHECK_HORZ = 1, CHECK_VERT = 2, CHECK_BOTH = 3 }; class Entry { public: u8 lowerBound, upperBound; u8 count, type; u32 tileNumOffset; u8 *getTileNums() { return ((u8*)this) + tileNumOffset; } }; class Section { public: u32 nameOffset; u32 entryCount; Entry entries[1]; // variable size const char *getName() { return ((char*)this) + nameOffset; } }; u32 magic; u32 sectionCount; u32 offsets[1]; // variable size Section *getSection(int id) { return (Section*)(((char*)this) + offsets[id]); } Section *getSection(const char *name); static RandomTileData *instance; }; class RTilemapClass : public TilemapClass { public: // NEWER ADDITIONS RandomTileData::Section *sections[4]; }; RandomTileData::Section *RandomTileData::getSection(const char *name) { for (int i = 0; i < sectionCount; i++) { RandomTileData::Section *sect = getSection(i); if (strcmp(name, sect->getName()) == 0) { return sect; } } return 0; } // Real tile handling code RandomTileData *RandomTileData::instance = 0; dDvdLoader_c RandTileLoader; extern "C" bool RandTileLoadHook() { OSReport("Trying to load..."); void *buf = RandTileLoader.load("/NewerRes/RandTiles.bin"); if (buf == 0) { OSReport("Failed.\n"); return false; } else { OSReport("Successfully loaded RandTiles.bin.\n"); RandomTileData::instance = (RandomTileData*)buf; return true; } } extern "C" void IdentifyTilesets(RTilemapClass *self) { self->_C0C = 0xFFFFFFFF; for (int i = 0; i < 4; i++) { const char *tilesetName = BGDatClass::instance->getTilesetName(self->areaID, i); self->sections[i] = RandomTileData::instance->getSection(tilesetName); } } extern "C" void TryAndRandomise(RTilemapClass *self, BGRender *bgr) { int fullTile = bgr->tileToPlace & 0x3FF; int tile = fullTile & 0xFF; int tileset = fullTile >> 8; RandomTileData::Section *rtSect = self->sections[tileset]; if (rtSect == 0) return; for (int i = 0; i < rtSect->entryCount; i++) { RandomTileData::Entry *entry = &rtSect->entries[i]; if (tile >= entry->lowerBound && tile <= entry->upperBound) { // Found it!! // Try to make one until we meet the conditions u8 *tileNums = entry->getTileNums(); u16 chosen = 0xFF; u16 *top = 0, *left = 0, *right = 0, *bottom = 0; if (entry->type == RandomTileData::CHECK_HORZ || entry->type == RandomTileData::CHECK_BOTH) { left = self->getPointerToTile(bgr->curX - 1, bgr->curY); right = self->getPointerToTile(bgr->curX + 1, bgr->curY); } if (entry->type == RandomTileData::CHECK_VERT || entry->type == RandomTileData::CHECK_BOTH) { top = self->getPointerToTile(bgr->curX, bgr->curY - 1); bottom = self->getPointerToTile(bgr->curX, bgr->curY + 1); } while (true) { // is there even a point to using that special random function? chosen = (tileset << 8) | tileNums[MakeRandomNumberForTiles(entry->count)]; if (top != 0 && *top == chosen) continue; if (bottom != 0 && *bottom == chosen) continue; if (left != 0 && *left == chosen) continue; if (right != 0 && *right == chosen) continue; break; } bgr->tileToPlace = chosen; return; } } }