summaryrefslogtreecommitdiff
path: root/src/koopatlas/pathmanager.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/koopatlas/pathmanager.cpp108
1 files changed, 107 insertions, 1 deletions
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);
}