summaryrefslogtreecommitdiff
path: root/src/koopatlas/pathmanager.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/koopatlas/pathmanager.cpp255
1 files changed, 252 insertions, 3 deletions
diff --git a/src/koopatlas/pathmanager.cpp b/src/koopatlas/pathmanager.cpp
index cf3e0eb..8c31d96 100644
--- a/src/koopatlas/pathmanager.cpp
+++ b/src/koopatlas/pathmanager.cpp
@@ -8,6 +8,25 @@
extern "C" void PlaySoundWithFunctionB4(void *spc, nw4r::snd::SoundHandle *handle, int id, int unk);
u8 MaybeFinishingLevel[2] = {0xFF,0xFF};
+u8 LastLevelPlayed[2] = {0xFF,0xFF};
+bool CanFinishCoins = false;
+bool CanFinishExits = false;
+bool CanFinishWorld = false;
+bool CanFinishAlmostAllCoins = false;
+bool CanFinishAllCoins = false;
+bool CanFinishAllExits = false;
+bool CanFinishEverything = false;
+void ResetAllCompletionCandidates() {
+ MaybeFinishingLevel[0] = 0xFF;
+ LastLevelPlayed[0] = 0xFF;
+ CanFinishCoins = false;
+ CanFinishExits = false;
+ CanFinishWorld = false;
+ CanFinishAlmostAllCoins = false;
+ CanFinishAllCoins = false;
+ CanFinishAllExits = false;
+ CanFinishEverything = false;
+}
void dWMPathManager_c::setup() {
dScKoopatlas_c *wm = dScKoopatlas_c::instance;
@@ -147,13 +166,74 @@ void dWMPathManager_c::setup() {
// did we just beat a level?
if (MaybeFinishingLevel[0] != 0xFF) {
- SaveBlock *save = GetSaveFile()->GetBlock(-1);
if (save->CheckLevelCondition(MaybeFinishingLevel[0], MaybeFinishingLevel[1], COND_NORMAL)) {
shouldRequestSave = true;
}
+ }
- MaybeFinishingLevel[0] = 0xFF;
+ // have we got any completions?
+ u32 conds = save->GetLevelCondition(LastLevelPlayed[0], LastLevelPlayed[1]);
+ dLevelInfo_c::entry_s *whatEntry =
+ dLevelInfo_c::s_info.searchBySlot(LastLevelPlayed[0], LastLevelPlayed[1]);
+
+ // how many exits?
+ int exits = 0, maxExits = 0;
+ if (whatEntry->flags & 0x10) {
+ maxExits++;
+ if (conds & COND_NORMAL)
+ exits++;
+ }
+ if (whatEntry->flags & 0x20) {
+ maxExits++;
+ if (conds & COND_SECRET)
+ exits++;
+ }
+
+ completionMessageWorldNum = whatEntry->displayWorld;
+
+ // now do all the message checks
+ int flag = 0, totalFlag = 0;
+ if (CanFinishCoins) {
+ totalFlag |= 1;
+ if ((conds & COND_COIN_ALL) == COND_COIN_ALL) {
+ flag |= 1;
+ completionMessageType = CMP_MSG_COINS;
+ }
+ }
+ if (CanFinishExits) {
+ totalFlag |= 2;
+ if (exits == maxExits) {
+ flag |= 2;
+ completionMessageType = CMP_MSG_EXITS;
+ }
+ }
+ if (CanFinishWorld && flag == totalFlag)
+ completionMessageType = CMP_MSG_WORLD;
+
+ if (CanFinishAlmostAllCoins) {
+ if ((conds & COND_COIN_ALL) == COND_COIN_ALL)
+ completionMessageType = CMP_MSG_GLOBAL_COINS_EXC_W9;
+ }
+
+ int gFlag = 0, gTotalFlag = 0;
+ if (CanFinishAllCoins) {
+ gTotalFlag |= 1;
+ if ((conds & COND_COIN_ALL) == COND_COIN_ALL) {
+ gFlag |= 1;
+ completionMessageType = CMP_MSG_GLOBAL_COINS;
+ }
+ }
+ if (CanFinishAllExits) {
+ gTotalFlag |= 2;
+ if (exits == maxExits) {
+ gFlag |= 2;
+ completionMessageType = CMP_MSG_GLOBAL_EXITS;
+ }
}
+ if (CanFinishEverything && gFlag == gTotalFlag)
+ completionMessageType = CMP_MSG_EVERYTHING;
+
+ ResetAllCompletionCandidates();
if (wm->isAfterKamekCutscene)
copyWorldDefToSave(wm->mapData.findWorldDef(1));
@@ -180,6 +260,135 @@ dWMPathManager_c::~dWMPathManager_c() {
MaybeFinishingLevel[1] = enteredLevel->levelSlot;
}
}
+
+ // Now, a fuckton of checks for the various possible things we can finish!
+ dLevelInfo_c *li = &dLevelInfo_c::s_info;
+ u32 theseConds = save->GetLevelCondition(enteredLevel->worldSlot, enteredLevel->levelSlot);
+
+ int coinCount = 0, exitCount = 0;
+ int globalCoinCount = 0, globalCoinCountExcW9 = 0, globalExitCount = 0;
+
+ int totalCoinCount = 0, totalExitCount = 0;
+ int totalGlobalCoinCount = 0, totalGlobalCoinCountExcW9 = 0, totalGlobalExitCount = 0;
+
+ for (int sIdx = 0; sIdx < li->sectionCount(); sIdx++) {
+ dLevelInfo_c::section_s *sect = li->getSectionByIndex(sIdx);
+
+ for (int lIdx = 0; lIdx < sect->levelCount; lIdx++) {
+ dLevelInfo_c::entry_s *entry = &sect->levels[lIdx];
+ u32 entryConds = save->GetLevelCondition(entry->worldSlot, entry->levelSlot);
+
+ // Only track actual levels
+ if (!(entry->flags & 2))
+ continue;
+
+ // Counts for this world
+ if (entry->displayWorld == enteredLevel->displayWorld) {
+ totalCoinCount++;
+ if ((entryConds & COND_COIN_ALL) == COND_COIN_ALL)
+ coinCount++;
+
+ // Normal exit
+ if (entry->flags & 0x10) {
+ totalExitCount++;
+ if (entryConds & COND_NORMAL)
+ exitCount++;
+ }
+
+ // Secret exit
+ if (entry->flags & 0x20) {
+ totalExitCount++;
+ if (entryConds & COND_SECRET)
+ exitCount++;
+ }
+ }
+
+ // Counts for everywhere
+ totalGlobalCoinCount++;
+ if ((entryConds & COND_COIN_ALL) == COND_COIN_ALL)
+ globalCoinCount++;
+
+ if (entry->displayWorld != 9) {
+ totalGlobalCoinCountExcW9++;
+ if (entryConds & COND_COIN_ALL)
+ globalCoinCountExcW9++;
+ }
+
+ // Normal exit
+ if (entry->flags & 0x10) {
+ totalGlobalExitCount++;
+ if (entryConds & COND_NORMAL)
+ globalExitCount++;
+ }
+
+ // Secret exit
+ if (entry->flags & 0x20) {
+ totalGlobalExitCount++;
+ if (entryConds & COND_SECRET)
+ globalExitCount++;
+ }
+ }
+ }
+
+ // So.. are we candidates for any of these?
+ ResetAllCompletionCandidates();
+
+ LastLevelPlayed[0] = enteredLevel->worldSlot;
+ LastLevelPlayed[1] = enteredLevel->levelSlot;
+
+ int everythingFlag = 0, gEverythingFlag = 0;
+ if (coinCount == totalCoinCount)
+ everythingFlag |= 1;
+ if (exitCount == globalExitCount)
+ everythingFlag |= 2;
+ if (globalCoinCount == totalGlobalCoinCount)
+ gEverythingFlag |= 1;
+ if (globalExitCount == totalGlobalExitCount)
+ gEverythingFlag |= 2;
+
+ // Check if we could obtain every star coin
+ if ((theseConds & COND_COIN_ALL) != COND_COIN_ALL) {
+ if ((coinCount + 1) == totalCoinCount) {
+ CanFinishCoins = true;
+ everythingFlag |= 1;
+ }
+ if ((globalCoinCount + 1) == totalGlobalCoinCount) {
+ CanFinishAllCoins = true;
+ gEverythingFlag |= 1;
+ }
+ if ((globalCoinCountExcW9 + 1) == totalGlobalCoinCountExcW9)
+ CanFinishAlmostAllCoins = true;
+ }
+
+ // Check if we could obtain every exit
+ int elExits = 0, elTotalExits = 0;
+ if (enteredLevel->flags & 0x10) {
+ elTotalExits++;
+ if (theseConds & COND_NORMAL)
+ elExits++;
+ }
+ if (enteredLevel->flags & 0x20) {
+ elTotalExits++;
+ if (theseConds & COND_SECRET)
+ elExits++;
+ }
+
+ if ((elExits + 1) == elTotalExits) {
+ if ((exitCount + 1) == totalExitCount) {
+ CanFinishExits = true;
+ everythingFlag |= 2;
+ }
+ if ((globalExitCount + 1) == totalGlobalExitCount) {
+ CanFinishAllExits = true;
+ gEverythingFlag |= 2;
+ }
+ }
+
+ // And could we obtain EVERYTHING?
+ if ((CanFinishCoins || CanFinishExits) && everythingFlag == 3)
+ CanFinishWorld = true;
+ if ((CanFinishAllCoins || CanFinishAllExits) && gEverythingFlag == 3)
+ CanFinishEverything = true;
}
if (penguinSlideSound.Exists())
@@ -382,7 +591,7 @@ bool dWMPathManager_c::evaluateUnlockCondition(u8 *&in, SaveBlock *save, int sta
bool dWMPathManager_c::doingThings() {
- if (isEnteringLevel || (waitAfterUnlock > 0) ||
+ if (isEnteringLevel || (waitAfterUnlock > 0) || (completionAnimDelay > 0) ||
(waitAtStart > 0) || (waitForAfterDeathAnim > 0) ||
(countdownToFadeIn > 0) || (unlockingAlpha != -1))
return true;
@@ -461,6 +670,46 @@ void dWMPathManager_c::execute() {
return;
}
+ if (completionAnimDelay > 0) {
+ completionAnimDelay--;
+ if (dmGladDuration > 0) {
+ dmGladDuration--;
+ if (dmGladDuration == 0)
+ daWMPlayer_c::instance->startAnimation(wait_select, 1.0f, 0.0f, 0.0f);
+ }
+ if (completionAnimDelay == 0)
+ completionMessagePending = true;
+ return;
+ }
+
+ // just in case
+ if (completionMessagePending)
+ return;
+
+ if (completionMessageType > 0) {
+ OSReport("We have a completion message type: %d\n", completionMessageType);
+
+ int whichSound;
+ if (completionMessageType == CMP_MSG_GLOBAL_COINS) {
+ whichSound = STRM_BGM_STAR_COIN_CMPLT_ALL;
+ completionAnimDelay = 240;
+ } else if (completionMessageType == CMP_MSG_EVERYTHING) {
+ whichSound = STRM_BGM_ALL_CMPLT_5STARS;
+ completionAnimDelay = 216;
+ } else {
+ whichSound = STRM_BGM_STAR_COIN_CMPLT_WORLD;
+ completionAnimDelay = 138;
+ }
+
+ nw4r::snd::SoundHandle something;
+ PlaySoundWithFunctionB4(SoundRelatedClass, &something, whichSound, 1);
+
+ daWMPlayer_c::instance->startAnimation(coin_comp, 1.0f, 0.0f, 0.0f);
+ dmGladDuration = 154;
+
+ return;
+ }
+
if (waitAtStart > 0) {
waitAtStart--;
if (waitAtStart == 0) {