summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xinclude/game.h1
-rw-r--r--include/newer.h3
-rw-r--r--src/koopatlas/pathmanager.cpp11
-rw-r--r--src/koopatlas/starcoin.cpp224
-rw-r--r--src/koopatlas/starcoin.h4
-rw-r--r--src/newer.cpp25
6 files changed, 250 insertions, 18 deletions
diff --git a/include/game.h b/include/game.h
index 08c2a49..0a843c2 100755
--- a/include/game.h
+++ b/include/game.h
@@ -166,6 +166,7 @@ bool IsWideScreen();
#define COND_SECRET 0x20
#define COND_SGNORMAL 0x80
#define COND_SGSECRET 0x100
+#define COND_UNLOCKED 0x200 // NEWER EXCLUSIVE
// All of these are set by "SetWorldCompleteionBitfield" (I didn't name it)
diff --git a/include/newer.h b/include/newer.h
index a687073..af6f00b 100644
--- a/include/newer.h
+++ b/include/newer.h
@@ -1,6 +1,9 @@
#ifndef NEWER_H
#define NEWER_H
+void WriteAsciiToTextBox(nw4r::lyt::TextBox *tb, const char *source);
+
+int getUnspentStarCoinCount();
int getStarCoinCount();
void getNewerLevelNumberString(int world, int level, wchar_t *dest);
diff --git a/src/koopatlas/pathmanager.cpp b/src/koopatlas/pathmanager.cpp
index 95c545f..70f3fab 100644
--- a/src/koopatlas/pathmanager.cpp
+++ b/src/koopatlas/pathmanager.cpp
@@ -209,8 +209,15 @@ void dWMPathManager_c::unlockPaths() {
SpammyReport("UNLOCKING PATHS: All complete @ %p\n", in);
- for (int i = 0; i < pathLayer->nodeCount; i++)
- NodeAvailabilityData[i] = pathLayer->nodes[i]->isUnlocked();
+ for (int i = 0; i < pathLayer->nodeCount; i++) {
+ dKPNode_s *node = pathLayer->nodes[i];
+ NodeAvailabilityData[i] = node->isUnlocked();
+
+ if (node->type == node->LEVEL && node->isUnlocked() && node->levelNumber[1] != 99) {
+ save->completions[node->levelNumber[0]-1][node->levelNumber[1]-1] |= COND_UNLOCKED;
+ OSReport("beets: %d-%d\n", node->levelNumber[0], node->levelNumber[1]);
+ }
+ }
// did anything become newly available?!
newlyAvailablePaths = 0;
diff --git a/src/koopatlas/starcoin.cpp b/src/koopatlas/starcoin.cpp
index 3b8372e..49ff46f 100644
--- a/src/koopatlas/starcoin.cpp
+++ b/src/koopatlas/starcoin.cpp
@@ -92,9 +92,6 @@ int dWMStarCoin_c::onCreate() {
};
layout.getTextBoxes(tbNames, &LeftTitle, 8);
- WriteBMGToTextBox(BtnBackText, GetBMG(), 3, 1, 0);
- WriteBMGToTextBox(BtnWorldSelText, GetBMG(), 4, 11, 0);
-
layoutLoaded = true;
}
@@ -176,19 +173,200 @@ void dWMStarCoin_c::setRightArrowVisible(bool value) {
bool dWMStarCoin_c::canScrollLeft() const {
- return (currentSection > 0);
+ return (currentSectionIndex > 1);
}
bool dWMStarCoin_c::canScrollRight() const {
- // TODO
- return false;
+ return (currentSectionIndex < (availableSectionCount - 1));
}
void dWMStarCoin_c::loadInfo() {
- // TODO
+ WriteBMGToTextBox(BtnBackText, GetBMG(), 3, 1, 0);
+ WriteBMGToTextBox(BtnWorldSelText, GetBMG(), 4, 11, 0);
+
+ int unspentCoins = getUnspentStarCoinCount();
+ int coins = getStarCoinCount();
+
+ WriteNumberToTextBox(&unspentCoins, UnspentCoinCount, false);
+ WriteNumberToTextBox(&coins, TotalCoinCount, false);
+
+ currentSection = -1;
+ currentSectionIndex = -1;
+ availableSectionCount = 0;
+
+ SaveBlock *save = GetSaveFile()->GetBlock(-1);
+ int wantedSection = save->newerWorldID;
+
+ // figure out which sections should be available
+ for (int i = 0; i < dLevelInfo_c::s_info.sectionCount(); i++) {
+ dLevelInfo_c::section_s *section = dLevelInfo_c::s_info.getSectionByIndex(i);
+ OSReport("Checking section %d\n", i);
+
+ bool haveLevels;
+ for (int j = 0; j < section->levelCount; j++) {
+ dLevelInfo_c::entry_s *l = &section->levels[j];
+ if (l->flags & 2) {
+ if (save->GetLevelCondition(l->worldSlot, l->levelSlot) & COND_UNLOCKED) {
+ haveLevels = true;
+ break;
+ }
+ }
+ }
+
+ if (haveLevels) {
+ OSReport("section %d has levels\n", i);
+ if (i == wantedSection) {
+ OSReport("It was the wanted section\n");
+ currentSection = wantedSection;
+ currentSectionIndex = availableSectionCount;
+ }
+ OSReport("Assigned to ID %d\n", availableSectionCount);
+ sectionIndices[availableSectionCount++] = i;
+ OSReport("{%d, %d, %d, %d, %d, %d, %d, %d, ...}\n",
+ sectionIndices[0],
+ sectionIndices[1],
+ sectionIndices[2],
+ sectionIndices[3],
+ sectionIndices[4],
+ sectionIndices[5],
+ sectionIndices[6],
+ sectionIndices[7]
+ );
+ }
+ }
+
+ // if we didn't find the wanted one, use the first one available
+ if (currentSectionIndex == -1) {
+ currentSectionIndex = 0;
+ currentSection = sectionIndices[0];
+ }
+ OSReport("{%d, %d, %d, %d, %d, %d, %d, %d, ...}\n",
+ sectionIndices[0],
+ sectionIndices[1],
+ sectionIndices[2],
+ sectionIndices[3],
+ sectionIndices[4],
+ sectionIndices[5],
+ sectionIndices[6],
+ sectionIndices[7]
+ );
}
void dWMStarCoin_c::loadSectionInfo() {
- // TODO
+ dLevelInfo_c::entry_s *visibleLevels[COLUMN_COUNT][ROW_COUNT];
+
+ // reset everything... everything
+ for (int i = 0; i < COLUMN_COUNT; i++) {
+ for (int j = 0; j < SHINE_COUNT; j++)
+ Shine[i][j]->SetVisible(false);
+
+ for (int j = 0; j < ROW_COUNT; j++) {
+ visibleLevels[i][j] = 0;
+
+ LevelName[i][j]->SetVisible(false);
+
+ for (int k = 0; k < 3; k++) {
+ CoinOutline[i][j][k]->SetVisible(false);
+ Coin[i][j][k]->SetVisible(false);
+ }
+ }
+ }
+
+ // get everything we'll need
+ SaveBlock *save = GetSaveFile()->GetBlock(-1);
+ dLevelInfo_c *linfo = &dLevelInfo_c::s_info;
+
+ dLevelInfo_c::entry_s *names[COLUMN_COUNT];
+ for (int i = 0; i < COLUMN_COUNT; i++)
+ names[i] = linfo->searchByDisplayNum(currentSection, 100+i);
+
+ bool useSubworlds = (COLUMN_COUNT > 1) && names[1];
+
+ int currentPosition[COLUMN_COUNT];
+ int currentColumn = 0; // only incremented in single-subworld mode
+
+ for (int i = 0; i < COLUMN_COUNT; i++)
+ currentPosition[i] = 0;
+
+ dLevelInfo_c::section_s *section = linfo->getSectionByIndex(currentSection);
+
+ int earnedCoins = 0, earnableCoins = 0;
+ // earnedCoins is calculated later
+
+ for (int i = 0; i < section->levelCount; i++) {
+ dLevelInfo_c::entry_s *level = &section->levels[i];
+
+ // only pay attention to real levels
+ if (!(level->flags & 2))
+ continue;
+
+ earnableCoins += 3;
+
+ // is this level unlocked?
+ u32 conds = save->GetLevelCondition(level->worldSlot, level->levelSlot);
+
+ if (!(conds & COND_UNLOCKED))
+ continue;
+
+ // well, let's give it a slot
+ if (useSubworlds) {
+ currentColumn = (level->flags & 0x400) ? 1 : 0;
+ } else {
+ if (currentPosition[currentColumn] >= ROW_COUNT)
+ currentColumn++;
+ }
+
+ visibleLevels[currentColumn][currentPosition[currentColumn]++] = level;
+ }
+
+ // if the first column is empty, then move the second one over
+ if (currentPosition[0] == 0 && useSubworlds) {
+ for (int i = 0; i < currentPosition[1]; i++) {
+ visibleLevels[0][i] = visibleLevels[1][i];
+ visibleLevels[1][i] = 0;
+ }
+
+ names[0] = names[1];
+ names[1] = 0;
+ }
+
+ // work out the names
+ WriteAsciiToTextBox(LeftTitle, linfo->getNameForLevel(names[0]));
+ if (names[1])
+ WriteAsciiToTextBox(RightTitle, linfo->getNameForLevel(names[1]));
+ RightTitle->SetVisible(names[1] != 0);
+
+ // load all level info
+ for (int col = 0; col < COLUMN_COUNT; col++) {
+ for (int row = 0; row < ROW_COUNT; row++) {
+ dLevelInfo_c::entry_s *level = visibleLevels[col][row];
+ if (!level)
+ continue;
+
+ u32 conds = save->GetLevelCondition(level->worldSlot, level->levelSlot);
+
+ if (!(row & 1)) {
+ int shineID = row / 2;
+ if (shineID < SHINE_COUNT)
+ Shine[col][shineID]->SetVisible(true);
+ }
+
+ for (int coin = 0; coin < 3; coin++) {
+ CoinOutline[col][row][coin]->SetVisible(true);
+
+ if (conds & (COND_COIN1 << coin)) {
+ Coin[col][row][coin]->SetVisible(true);
+ earnedCoins++;
+ }
+ }
+
+ LevelName[col][row]->SetVisible(true);
+ WriteAsciiToTextBox(LevelName[col][row], linfo->getNameForLevel(level));
+ }
+ }
+
+ // set up coin things
+ WriteNumberToTextBox(&earnedCoins, EarnedCoinCount, false);
+ WriteNumberToTextBox(&earnableCoins, EarnedCoinMax, false);
}
@@ -231,11 +409,33 @@ void dWMStarCoin_c::executeState_Wait() {
willExit = true;
state.setState(&StateID_HideSectionWait);
} else if ((nowPressed & WPAD_LEFT) && canScrollLeft()) {
- currentSection--;
+ currentSection = sectionIndices[--currentSectionIndex];
+ OSReport("Set section to %d from index %d\n", currentSection, currentSectionIndex);
+ OSReport("{%d, %d, %d, %d, %d, %d, %d, %d, ...}\n",
+ sectionIndices[0],
+ sectionIndices[1],
+ sectionIndices[2],
+ sectionIndices[3],
+ sectionIndices[4],
+ sectionIndices[5],
+ sectionIndices[6],
+ sectionIndices[7]
+ );
willExit = false;
state.setState(&StateID_HideSectionWait);
} else if ((nowPressed & WPAD_RIGHT) && canScrollRight()) {
- currentSection++;
+ currentSection = sectionIndices[++currentSectionIndex];
+ OSReport("Set section to %d from index %d\n", currentSection, currentSectionIndex);
+ OSReport("{%d, %d, %d, %d, %d, %d, %d, %d, ...}\n",
+ sectionIndices[0],
+ sectionIndices[1],
+ sectionIndices[2],
+ sectionIndices[3],
+ sectionIndices[4],
+ sectionIndices[5],
+ sectionIndices[6],
+ sectionIndices[7]
+ );
willExit = false;
state.setState(&StateID_HideSectionWait);
}
@@ -263,12 +463,12 @@ void dWMStarCoin_c::executeState_HideSectionWait() {
void dWMStarCoin_c::endState_HideSectionWait() { }
void dWMStarCoin_c::beginState_HideWait() {
- layout.enableNonLoopAnim(SHOW_ALL);
+ layout.enableNonLoopAnim(SHOW_ALL, true);
layout.grpHandlers[SHOW_ALL].frameCtrl.flags = 3; // NO_LOOP | REVERSE
}
void dWMStarCoin_c::executeState_HideWait() {
if (!layout.isAnimOn(SHOW_ALL))
- state.setState(&StateID_Wait);
+ state.setState(&StateID_Hidden);
}
void dWMStarCoin_c::endState_HideWait() {
visible = false;
diff --git a/src/koopatlas/starcoin.h b/src/koopatlas/starcoin.h
index 3d931e8..5e88343 100644
--- a/src/koopatlas/starcoin.h
+++ b/src/koopatlas/starcoin.h
@@ -35,9 +35,13 @@ class dWMStarCoin_c : public dActor_c {
ROW_COUNT = 9,
COLUMN_COUNT = 2,
SHINE_COUNT = 5,
+ MAX_SECTION_COUNT = 16,
};
int currentSection;
+ int currentSectionIndex;
+ bool sectionIndices[MAX_SECTION_COUNT];
+ int availableSectionCount;
bool isLeftArrowVisible, isRightArrowVisible;
bool willExit;
diff --git a/src/newer.cpp b/src/newer.cpp
index d1894ba..dd0d99c 100644
--- a/src/newer.cpp
+++ b/src/newer.cpp
@@ -1,6 +1,19 @@
#include <newer.h>
#include <game.h>
+void WriteAsciiToTextBox(nw4r::lyt::TextBox *tb, const char *source) {
+ int i = 0;
+ wchar_t buffer[1024];
+ while (i < 1023 && source[i]) {
+ buffer[i] = source[i];
+ i++;
+ }
+ buffer[i] = 0;
+
+ tb->SetString(buffer);
+}
+
+
void getNewerLevelNumberString(int world, int level, wchar_t *dest) {
static const wchar_t *numberKinds[] = {
// 0-19 are handled by code
@@ -46,9 +59,8 @@ void getNewerLevelNumberString(int world, int level, wchar_t *dest) {
}
}
-int getStarCoinCount() {
+int getUnspentStarCoinCount() {
SaveBlock *save = GetSaveFile()->GetBlock(-1);
- int coinsSpent = save->credits_hiscore;
int coinsEarned = 0;
for (int w = 0; w < 10; w++) {
@@ -61,6 +73,11 @@ int getStarCoinCount() {
}
}
- int coinsLeft = coinsEarned - coinsSpent;
- return coinsLeft;
+ return coinsEarned;
+}
+
+int getStarCoinCount() {
+ SaveBlock *save = GetSaveFile()->GetBlock(-1);
+ int coinsSpent = save->credits_hiscore;
+ return getUnspentStarCoinCount() - coinsSpent;
}