diff options
| author | Treeki <treeki@gmail.com> | 2013-02-25 22:03:47 +0100 | 
|---|---|---|
| committer | Treeki <treeki@gmail.com> | 2013-02-25 22:03:47 +0100 | 
| commit | 027164e4b4baa4ac02ad8647b9977798c540297a (patch) | |
| tree | 04b54ca80bcb98ac928ea02eafe0dd69fdded148 | |
| parent | 6cfe2dd3ddce416e8884dd61218751bc5c77e54c (diff) | |
| download | kamek-027164e4b4baa4ac02ad8647b9977798c540297a.tar.gz kamek-027164e4b4baa4ac02ad8647b9977798c540297a.zip  | |
implement completion congratulations messages
Diffstat (limited to '')
| -rw-r--r-- | koopatlas.yaml | 6 | ||||
| -rw-r--r-- | src/koopatlas/core.cpp | 81 | ||||
| -rw-r--r-- | src/koopatlas/core.h | 4 | ||||
| -rw-r--r-- | src/koopatlas/pathmanager.cpp | 255 | ||||
| -rw-r--r-- | src/koopatlas/pathmanager.h | 16 | 
5 files changed, 359 insertions, 3 deletions
diff --git a/koopatlas.yaml b/koopatlas.yaml index 5c9c081..377e9eb 100644 --- a/koopatlas.yaml +++ b/koopatlas.yaml @@ -98,3 +98,9 @@ hooks:      addr_pal: 0x800D52F0      data: '41820010' +  - name: ResetAllCompletionCandidates +    type: branch_insn +    branch_type: b +    src_addr_pal: 0x800B2FF0 +    target_func: 'ResetAllCompletionCandidates(void)' + diff --git a/src/koopatlas/core.cpp b/src/koopatlas/core.cpp index 1772724..9666e53 100644 --- a/src/koopatlas/core.cpp +++ b/src/koopatlas/core.cpp @@ -10,6 +10,8 @@ dScKoopatlas_c *dScKoopatlas_c::instance = 0;  CREATE_STATE_E(dScKoopatlas_c, Limbo);  CREATE_STATE(dScKoopatlas_c, ContinueWait);  CREATE_STATE_E(dScKoopatlas_c, Normal); +CREATE_STATE(dScKoopatlas_c, CompletionMsg); +CREATE_STATE_E(dScKoopatlas_c, CompletionMsgHideWait);  CREATE_STATE_E(dScKoopatlas_c, CSMenu);  CREATE_STATE_E(dScKoopatlas_c, TitleConfirmOpenWait);  CREATE_STATE_E(dScKoopatlas_c, TitleConfirmSelect); @@ -499,6 +501,12 @@ void dScKoopatlas_c::endState_ContinueWait() {  void dScKoopatlas_c::executeState_Normal() { +	if (pathManager.completionMessagePending) { +		OSReport("Going to set CompletionMsg\n"); +		state.setState(&StateID_CompletionMsg); +		return; +	} +  	if (pathManager.doingThings())  		return; @@ -1050,6 +1058,79 @@ void dScKoopatlas_c::showSaveWindow() {  } +void dScKoopatlas_c::beginState_CompletionMsg() { +	OSReport("CompletionMsg beginning with type %d\n", pathManager.completionMessageType); +	static const int ynTypes[8] = { +		/*NULL*/ -1, +		/*COINS*/ 14, +		/*EXITS*/ 7, +		/*WORLD*/ 8, +		/*COINS EXC W9*/ 9, +		/*GLOBAL COINS*/ 11, +		/*GLOBAL EXITS*/ 27, +		/*EVERYTHING*/ 21 +	}; +	yesNoWindow->type = ynTypes[pathManager.completionMessageType]; +	yesNoWindow->visible = true; +	mustFixYesNoText = 10; // hacky shit +} + +void dScKoopatlas_c::endState_CompletionMsg() { +	pathManager.completionMessagePending = false; +	pathManager.completionMessageType = 0; +} + +void dScKoopatlas_c::executeState_CompletionMsg() { +	// hacky shit +	if (mustFixYesNoText > 0) { +		mustFixYesNoText--; + +		int type = pathManager.completionMessageType; + +		if (type >= CMP_MSG_COINS && type <= CMP_MSG_WORLD) { +			// get the stuff we need: base BMG string +			static const int bmgs[4] = {-1, 65, 58, 59}; +			const wchar_t *baseText = GetBMG()->findStringForMessageID(0, bmgs[type]); + +			// title +			int w = pathManager.completionMessageWorldNum; +			int l = ((w == 5) || (w == 7)) ? 101 : 100; +			dLevelInfo_c::entry_s *titleEntry = dLevelInfo_c::s_info.searchByDisplayNum(w, l); +			const char *title = dLevelInfo_c::s_info.getNameForLevel(titleEntry); + +			// assemble the string +			wchar_t text[512]; + +			wcscpy(text, baseText); +			int pos = wcslen(text); + +			text[pos++] = ' '; + +			while (*title) +				text[pos++] = *(title++); + +			text[pos++] = '!'; +			text[pos++] = 0; + +			yesNoWindow->T_question_00->SetString(text); +			yesNoWindow->T_questionS_00->SetString(text); +		} +	} + +	if (!yesNoWindow->animationActive) { +		if (Wiimote_TestButtons(GetActiveWiimote(), WPAD_A | WPAD_TWO)) { +			yesNoWindow->close = true; +			state.setState(&StateID_CompletionMsgHideWait); +		} +	} +} + +void dScKoopatlas_c::executeState_CompletionMsgHideWait() { +	if (!yesNoWindow->visible) +		state.setState(&StateID_Normal); +} + +  void NewerMapDrawFunc() {  	Reset3DState();  	SetCurrentCameraID(0); diff --git a/src/koopatlas/core.h b/src/koopatlas/core.h index 58030b7..f314b82 100644 --- a/src/koopatlas/core.h +++ b/src/koopatlas/core.h @@ -58,6 +58,8 @@ class dScKoopatlas_c : public dScene_c {  		DECLARE_STATE(Limbo);  		DECLARE_STATE(ContinueWait);  		DECLARE_STATE(Normal); +		DECLARE_STATE(CompletionMsg); +		DECLARE_STATE(CompletionMsgHideWait);  		DECLARE_STATE(CSMenu);  		DECLARE_STATE(TitleConfirmOpenWait);  		DECLARE_STATE(TitleConfirmSelect); @@ -118,6 +120,8 @@ class dScKoopatlas_c : public dScene_c {  		bool warpZoneHacks; +		int mustFixYesNoText; +  		u32 iterateMapList(u32(*callback)(u32,const char *,int,int), u32 userData, int *ptrIndex = 0);  		const char *getMapNameForIndex(int index);  		int getIndexForMapName(const char *name); 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 = §->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) { diff --git a/src/koopatlas/pathmanager.h b/src/koopatlas/pathmanager.h index 156ed7b..522db7f 100644 --- a/src/koopatlas/pathmanager.h +++ b/src/koopatlas/pathmanager.h @@ -15,6 +15,17 @@ extern "C" void *SoundRelatedClass;  extern "C" void *MapSoundPlayer(void *SoundClass, int soundID, int unk);  extern "C" bool SpawnEffect(const char*, int, Vec*, S16Vec*, Vec*); +enum CompletionMessageType { +	CMP_MSG_NULL = 0, +	CMP_MSG_COINS = 1, +	CMP_MSG_EXITS = 2, +	CMP_MSG_WORLD = 3, +	CMP_MSG_GLOBAL_COINS_EXC_W9 = 4, +	CMP_MSG_GLOBAL_COINS = 5, +	CMP_MSG_GLOBAL_EXITS = 6, +	CMP_MSG_EVERYTHING = 7 +}; +  class dWMPathManager_c {  	public:  		void setup(); @@ -76,6 +87,11 @@ class dWMPathManager_c {  	public:  		bool shouldRequestSave;  		bool isEnteringLevel; +		bool completionMessagePending; +		int dmGladDuration; +		int completionAnimDelay; +		int completionMessageType; +		int completionMessageWorldNum;  		bool calledEnteredNode;  		int levelStartWait;  | 
