From 21d7e41b006b88aa79821610661fefc8fe14b7ca Mon Sep 17 00:00:00 2001 From: Treeki Date: Mon, 27 Feb 2012 18:54:32 +0100 Subject: switching between multiple maps --- src/koopatlas/core.cpp | 113 ++++++++++++++++++++++++++++++++++++------ src/koopatlas/core.h | 8 +++ src/koopatlas/mapdata.h | 9 +++- src/koopatlas/pathmanager.cpp | 42 ++++++++++++++-- 4 files changed, 153 insertions(+), 19 deletions(-) (limited to 'src/koopatlas') diff --git a/src/koopatlas/core.cpp b/src/koopatlas/core.cpp index 7eaa339..f7acf00 100644 --- a/src/koopatlas/core.cpp +++ b/src/koopatlas/core.cpp @@ -47,7 +47,8 @@ dScKoopatlas_c *dScKoopatlas_c::build() { bool WMInit_StartLoading(void*); bool WMInit_LoadSIAnims(void*); bool WMInit_EndLoading(void*); -bool WMInit_LoadResources(void*); +bool WMInit_LoadResources1(void*); +bool WMInit_LoadResources2(void*); bool WMInit_SetupWait(void*); bool WMInit_SetupExtra(void*); bool WMInit_SetupWipe(void*); @@ -56,14 +57,15 @@ ChainedFunc initFunctions[] = { WMInit_StartLoading, WMInit_LoadSIAnims, WMInit_EndLoading, - WMInit_LoadResources, + WMInit_LoadResources1, + WMInit_LoadResources2, WMInit_SetupWait, WMInit_SetupExtra, WMInit_SetupWipe }; dScKoopatlas_c::dScKoopatlas_c() : state(this) { - initChain.setup(initFunctions, 7); + initChain.setup(initFunctions, 8); setInitChain(initChain); } @@ -154,13 +156,28 @@ bool WMInit_EndLoading(void *ptr) { return true; } -bool WMInit_LoadResources(void *ptr) { - SpammyReport("WMInit_LoadResources returning true\n"); +bool WMInit_LoadResources1(void *ptr) { + SpammyReport("WMInit_LoadResources1 returning true\n"); dScKoopatlas_c *wm = (dScKoopatlas_c*)ptr; - return - wm->mapData.load("/Maps/yat.kpbin") && - wm->levelInfoLoader.load("/NewerRes/LevelInfo.bin"); + + bool result1 = wm->mapListLoader.load("/Maps/List.txt"); + bool result2 = wm->levelInfoLoader.load("/NewerRes/LevelInfo.bin"); + return result1 && result2; +} + +bool WMInit_LoadResources2(void *ptr) { + SpammyReport("WMInit_LoadResources2 returning true\n"); + + dScKoopatlas_c *wm = (dScKoopatlas_c*)ptr; + + if (wm->mapPath == 0) { + wm->mapPath = wm->getMapNameForIndex(wm->currentMapID); + if (wm->mapPath == 0) + wm->mapPath = wm->getMapNameForIndex(0); + } + + return wm->mapData.load(wm->mapPath); } bool WMInit_SetupWait(void *ptr) { @@ -339,13 +356,12 @@ int dScKoopatlas_c::onCreate() { SpammyReport("setting NewerMapDrawFunc\n"); *CurrentDrawFunc = NewerMapDrawFunc; - // level info - /*SpammyReport("loading level info file\n"); - levelInfoFile.open("/NewerRes/LevelInfo.bin"); - SpammyReport("preparing level info\n"); - levelInfo.load(levelInfoFile.ptr());*/ - SpammyReport("onCreate() completed\n"); + + // Prepare this first + SaveBlock *save = GetSaveFile()->GetBlock(-1); + currentMapID = save->current_world; + return true; } @@ -361,6 +377,7 @@ int dScKoopatlas_c::onDelete() { DVD_FreeFile(GetDVDClass2(), "SI_star"); levelInfoLoader.unload(); + mapListLoader.unload(); return true; } @@ -831,6 +848,74 @@ void dScKoopatlas_c::startLevel(dLevelInfo_c::entry_s *entry) { } +u32 dScKoopatlas_c::iterateMapList(u32(*callback)(u32,const char *,int,int), u32 userData, int *ptrIndex) { + u8 *ptr = (u8*)mapListLoader.buffer; + u8 *strStart = ptr; + u8 *end = ptr + mapListLoader.size; + int index = 0; + + while (true) { + u8 chr = *ptr; + if (chr == 13) { + ++ptr; + continue; + } + + if (chr == 10 || chr == 0 || ptr >= end) { + if (strStart == ptr) { + // Blank string, ignore + ++strStart; + ++ptr; + continue; + } + + // Change the linefeed to a NUL so we can use the line as a C string later + if (ptr < end) + *ptr = 0; + + u32 ret = callback(userData, (const char*)strStart, ptr - strStart, index); + if (ptrIndex) + *ptrIndex = index; + if (ret > 0) + return ret; + + strStart = ++ptr; + ++index; + + if (ptr >= end) + break; + + } else { + ++ptr; + } + } + + return 0; +} + +static u32 _cb_getIndex(u32 userData, const char *str, int size, int index) { + if (index == userData) + return (u32)str; + else + return 0; +} + +static u32 _cb_searchName(u32 userData, const char *str, int size, int index) { + if (strncmp(str, (const char*)userData, size) == 0) + return (u32)(index+1); + else + return 0; +} + +const char *dScKoopatlas_c::getMapNameForIndex(int index) { + return (const char *)iterateMapList(&_cb_getIndex, (u32)index, 0); +} + +int dScKoopatlas_c::getIndexForMapName(const char *name) { + return ((int)iterateMapList(&_cb_searchName, (u32)name, 0)) - 1; +} + + void NewerMapDrawFunc() { Reset3DState(); SetCurrentCameraID(0); diff --git a/src/koopatlas/core.h b/src/koopatlas/core.h index 9ca1935..6a76cc4 100644 --- a/src/koopatlas/core.h +++ b/src/koopatlas/core.h @@ -92,9 +92,17 @@ class dScKoopatlas_c : public dScene_c { dWMHud_c *hud; dWMMap_c *map; + int currentMapID; + const char *mapPath; dKPMapData_c mapData; dWMPathManager_c pathManager; + dDvdLoader_c mapListLoader; + + u32 iterateMapList(u32(*callback)(u32,const char *,int,int), u32 userData, int *ptrIndex = 0); + const char *getMapNameForIndex(int index); + int getIndexForMapName(const char *name); + dDvdLoader_c levelInfoLoader; dLevelInfo_c levelInfo; diff --git a/src/koopatlas/mapdata.h b/src/koopatlas/mapdata.h index e75925d..913c933 100644 --- a/src/koopatlas/mapdata.h +++ b/src/koopatlas/mapdata.h @@ -67,10 +67,17 @@ struct dKPNode_s { NodeTypes type; union { struct { u8 levelNumber[2]; }; - struct { char *destMap; u8 thisID, foreignID, transition; }; + struct { const char *destMap; u8 thisID, foreignID, transition; }; }; + dKPPath_s *getAnyExit() { + for (int i = 0; i < 4; i++) + if (exits[i]) + return exits[i]; + return 0; + } + dKPPath_s *getOppositeExitTo(dKPPath_s *path); }; diff --git a/src/koopatlas/pathmanager.cpp b/src/koopatlas/pathmanager.cpp index 609b3a2..923d08c 100644 --- a/src/koopatlas/pathmanager.cpp +++ b/src/koopatlas/pathmanager.cpp @@ -11,10 +11,35 @@ void dWMPathManager_c::setup() { pathLayer = dScKoopatlas_c::instance->mapData.pathLayer; SaveBlock *save = GetSaveFile()->GetBlock(-1); - if (save->current_path_node >= pathLayer->nodeCount) { - currentNode = pathLayer->nodes[0]; + + // Figure out what path node to start at + if (dScKoopatlas_c::instance->settings & 0x10000000) { + // Start off from a "Change" + u8 changeID = dScKoopatlas_c::instance->settings & 0xFF; + + bool found = false; + + for (int i = 0; i < pathLayer->nodeCount; i++) { + dKPNode_s *node = pathLayer->nodes[i]; + + if (node->type == dKPNode_s::CHANGE && node->thisID == changeID) { + found = true; + currentNode = node; + + startMovementTo(node->getAnyExit()); + } + } + + if (!found) { + OSReport("Couldn't find target node %d!\n", changeID); + } + } else { - currentNode = pathLayer->nodes[save->current_path_node]; + if (save->current_path_node >= pathLayer->nodeCount) { + currentNode = pathLayer->nodes[0]; + } else { + currentNode = pathLayer->nodes[save->current_path_node]; + } } // unlock all needed paths @@ -100,7 +125,16 @@ void dWMPathManager_c::moveThroughPath() { player->pos.x = to->x; player->pos.y = -to->y; - if (to->type != dKPNode_s::PASS_THROUGH) { + if (to->type == dKPNode_s::CHANGE) { + // Go to another map + isMoving = false; + + SaveBlock *save = GetSaveFile()->GetBlock(-1); + save->current_world = dScKoopatlas_c::instance->getIndexForMapName(to->destMap); + + DoSceneChange(WORLD_MAP, 0x10000000 | to->foreignID, 0); + + } else if (to->type != dKPNode_s::PASS_THROUGH) { // Stop here player->startAnimation(0, 1.2, 10.0, 0.0); -- cgit v1.2.3