diff options
-rw-r--r-- | src/koopatlas/mapdata.cpp | 10 | ||||
-rw-r--r-- | src/koopatlas/mapdata.h | 10 | ||||
-rw-r--r-- | src/koopatlas/pathmanager.cpp | 108 | ||||
-rw-r--r-- | src/koopatlas/pathmanager.h | 7 |
4 files changed, 128 insertions, 7 deletions
diff --git a/src/koopatlas/mapdata.cpp b/src/koopatlas/mapdata.cpp index 9c84c4a..dd4646b 100644 --- a/src/koopatlas/mapdata.cpp +++ b/src/koopatlas/mapdata.cpp @@ -173,6 +173,7 @@ void dKPMapData_c::fixup() { fixRef(data->layers); fixRef(data->tilesets); + fixRef(data->unlockData); for (int iLayer = 0; iLayer < data->layerCount; iLayer++) { dKPLayer_s *layer = fixRef(data->layers[iLayer]); @@ -225,10 +226,7 @@ void dKPMapData_c::fixup() { } - // before we finish here, create the Node Extra classes - - // before the first off, do the unlocking. - SaveBlock *save = GetSaveFile()->GetBlock(-1); + /*SaveBlock *save = GetSaveFile()->GetBlock(-1); for (int i = 0; i < pathLayer->pathCount; i++) { dKPPath_s *path = pathLayer->paths[i]; @@ -242,8 +240,10 @@ void dKPMapData_c::fixup() { else path->isAvailable = false; } - } + }*/ + + // before we finish here, create the Node Extra classes // first off, count how many we need... int count = 0; diff --git a/src/koopatlas/mapdata.h b/src/koopatlas/mapdata.h index 18dd9ee..b9a32f3 100644 --- a/src/koopatlas/mapdata.h +++ b/src/koopatlas/mapdata.h @@ -95,12 +95,18 @@ struct dKPNode_s { }; struct dKPPath_s { + enum Availability { + NOT_AVAILABLE = 0, + AVAILABLE = 1, + NEWLY_AVAILABLE = 2 + }; + dKPNode_s *start, *end; dKPLayer_s *tileLayer, *doodadLayer; u8 unlockType; // 0 = always, 1 = normal, 2 = secret u8 unlockLevelNumber[2]; - bool isAvailable; // computed on-the-fly - default from Koopatlas is true + u8 isAvailable; // computed on-the-fly - default from Koopatlas is 1 float speed; int animation; }; @@ -164,6 +170,8 @@ struct dKPMapFile_s { int tilesetCount; GXTexObj *tilesets; + u8 *unlockData; + dKPLayer_s::sector_s sectors[1]; // variable size }; diff --git a/src/koopatlas/pathmanager.cpp b/src/koopatlas/pathmanager.cpp index 41515a6..444684c 100644 --- a/src/koopatlas/pathmanager.cpp +++ b/src/koopatlas/pathmanager.cpp @@ -61,11 +61,115 @@ void dWMPathManager_c::setup() { } } - // unlock all needed paths SpammyReport("Unlocking paths\n"); + isEnteringLevel = false; + unlockPaths(); SpammyReport("done\n"); } +static u8 *PathAvailabilityData = 0; + +dWMPathManager_c::~dWMPathManager_c() { + if (PathAvailabilityData && !isEnteringLevel) { + delete[] PathAvailabilityData; + PathAvailabilityData = 0; + } +} + +void dWMPathManager_c::unlockPaths() { + u8 *oldAvData = PathAvailabilityData; + PathAvailabilityData = new u8[pathLayer->pathCount]; + + // unlock all needed paths + for (int i = 0; i < pathLayer->pathCount; i++) + PathAvailabilityData[i] = dKPPath_s::NOT_AVAILABLE; + + SaveBlock *save = GetSaveFile()->GetBlock(-1); + + u8 *in = (u8*)dScKoopatlas_c::instance->mapData.data->unlockData; + + while (*in != 0) { + // begin processing a block + bool value = evaluateUnlockCondition(in, save); + + // , get what it's supposed to affect + // for now we'll assume that it affects one or more paths + u8 affectedCount = *(in++); + + for (int i = 0; i < affectedCount; i++) { + u8 one = *(in++); + u8 two = *(in++); + u16 pathID = (one << 8) | two; + + dKPPath_s *path = pathLayer->paths[pathID]; + path->isAvailable = dKPPath_s::AVAILABLE; + PathAvailabilityData[pathID] = dKPPath_s::AVAILABLE; + // NEWLY_AVAILABLE is set later, when that stuff is figured out + } + + // now evaluate a condition. simple! + } + + // did anything become newly available?! + int whatsNew = 0; + + if (oldAvData) { + for (int i = 0; i < pathLayer->pathCount; i++) { + if ((PathAvailabilityData[i] > 0) && (oldAvData[i] == 0)) { + dKPPath_s *path = pathLayer->paths[i]; + path->isAvailable = dKPPath_s::NEWLY_AVAILABLE; + whatsNew++; + } + } + delete[] oldAvData; + } + + // todo: set a flag on Map to do the path fade/sound, with whatsNew +} + +bool dWMPathManager_c::evaluateUnlockCondition(u8 *&in, SaveBlock *save) { + u8 controlByte = *(in++); + + u8 conditionType = (controlByte >> 6); + + if (conditionType == 0) + return true; + + if (conditionType == 1) { + // Simple level + + bool isSecret = (controlByte & 0x10); + u8 worldNumber = controlByte & 0xF; + u8 levelNumber = *(in++); + + u32 conds = save->GetLevelCondition(worldNumber, levelNumber); + + if (isSecret) + return (conds & COND_SECRET) != 0; + else + return (conds & COND_NORMAL) != 0; + } + + // Type: 2 = AND, 3 = OR + bool isAnd = (conditionType == 2); + bool isOr = (conditionType == 3); + + bool value = isOr ? false : true; + + u8 termCount = (controlByte & 0x3F) + 1; + + for (int i = 0; i < termCount; i++) { + bool what = evaluateUnlockCondition(in, save); + + if (isOr) + value |= what; + else + value &= what; + } + + return value; +} + void dWMPathManager_c::execute() { int nowPressed = Remocon_GetPressed(GetActiveRemocon()); @@ -354,6 +458,8 @@ void dWMPathManager_c::activatePoint() { MapSoundPlayer(SoundRelatedClass, SE_SYS_GAME_START, 1); daWMPlayer_c::instance->startAnimation(170, 1.2, 10.0, 0.0); + isEnteringLevel = true; + dLevelInfo_c::entry_s *level = dScKoopatlas_c::instance->levelInfo.search(w, l); dScKoopatlas_c::instance->startLevel(level); } diff --git a/src/koopatlas/pathmanager.h b/src/koopatlas/pathmanager.h index 969bdb2..5d35f4c 100644 --- a/src/koopatlas/pathmanager.h +++ b/src/koopatlas/pathmanager.h @@ -10,6 +10,7 @@ extern "C" bool SpawnEffect(const char*, int, Vec*, S16Vec*, Vec*); class dWMPathManager_c { public: void setup(); + ~dWMPathManager_c(); void execute(); bool canUseExit(dKPPath_s *path) { @@ -36,6 +37,12 @@ class dWMPathManager_c { bool reverseThroughPath; // direction we are going through the path bool mustComplainToMapCreator; + + private: + void unlockPaths(); + bool evaluateUnlockCondition(u8 *&in, SaveBlock *save); + + bool isEnteringLevel; }; #endif |