summaryrefslogtreecommitdiff
path: root/src/koopatlas
diff options
context:
space:
mode:
Diffstat (limited to 'src/koopatlas')
-rw-r--r--src/koopatlas/mapdata.cpp10
-rw-r--r--src/koopatlas/mapdata.h10
-rw-r--r--src/koopatlas/pathmanager.cpp108
-rw-r--r--src/koopatlas/pathmanager.h7
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