#include "koopatlas/hud.h" #include dWMHud_c *dWMHud_c::instance = 0; dWMHud_c *dWMHud_c::build() { void *buffer = AllocFromGameHeap1(sizeof(dWMHud_c)); dWMHud_c *c = new(buffer) dWMHud_c; instance = c; return c; } dWMHud_c::dWMHud_c() { layoutLoaded = false; displayedControllerType = -1; isFooterVisible = false; } enum WMHudAnimation { SHOW_LIVES = 0, SHOW_HEADER, SHOW_FOOTER }; int dWMHud_c::onCreate() { if (!layoutLoaded) { bool gotFile = layout.loadArc("MapHUD.arc", false); if (!gotFile) return false; bool output = layout.build("maphud.brlyt"); if (!IsWideScreen()) { layout.clippingEnabled = true; layout.clipX = 0; layout.clipY = 52; layout.clipWidth = 640; layout.clipHeight = 352; layout.layout.rootPane->scale.x = 0.7711f; layout.layout.rootPane->scale.y = 0.7711f; } static const char *brlanNames[2] = {"MapHUD_ShowMain.brlan", "MapHUD_ShowHeader.brlan"}; static const char *groupNames[3] = {"G_Lives", "G_Header", "G_Footer"}; layout.loadAnimations(brlanNames, 2); layout.loadGroups(groupNames, (int[3]){0, 1, 0}, 3); layout.disableAllAnimations(); layout.enableNonLoopAnim(SHOW_LIVES); layout.resetAnim(SHOW_FOOTER); layout.resetAnim(SHOW_HEADER); static const char *tbNames[2] = {"MenuButtonInfo", "ItemsButtonInfo"}; layout.setLangStrings(tbNames, (int[2]){12, 15}, 4, 2); static const char *paneNames[] = { "N_IconPos1P_00", "N_IconPos2P_00", "N_IconPos3P_00", "N_IconPos4P_00" }; layout.getPanes(paneNames, &N_IconPosXP_00[0], 4); static const char *pictureNames[] = { "Header_Centre", "Header_Right", "Footer", "NormalExitFlag", "SecretExitFlag", "StarCoinOff0", "StarCoinOff1", "StarCoinOff2", "StarCoinOn0", "StarCoinOn1", "StarCoinOn2", "P_marioFace_00", "P_luigiFace_00", "P_BkinoFace_00", "P_YkinoFace_00", "Star0", "Star1", "Star2" }; layout.getPictures(pictureNames, &Header_Centre, 18); static const char *textBoxNames[] = { "LevelName", "LevelNameS", "LevelNumber", "LevelNumberS", "WorldName", "WorldNameS", "StarCoinCounter", "T_lifeNumber_00", "T_lifeNumber_01", "T_lifeNumber_02", "T_lifeNumber_03" }; layout.getTextBoxes(textBoxNames, &LevelName, 11); headerCol.setTexMap(Header_Right->material->texMaps); headerCol.applyAlso(Header_Centre->material->texMaps); footerCol.setTexMap(Footer->material->texMaps); layoutLoaded = true; layout.drawOrder = 0; willShowHeader = false; willShowFooter = false; loadFooterInfo(); SaveBlock *save = GetSaveFile()->GetBlock(-1); willShowFooter = (save->newerWorldName[0] != 0); if (!dScKoopatlas_c::instance->pathManager.isMoving) enteredNode(); setupLives(); } return true; } int dWMHud_c::onDelete() { dWMHud_c::instance = 0; if (!layoutLoaded) return true; return layout.free(); } int dWMHud_c::onExecute() { if (!layoutLoaded) return true; if (willShowHeader && (!(layout.isAnimOn(SHOW_HEADER)))) { willShowHeader = false; loadHeaderInfo(); playShowAnim(SHOW_HEADER); } if (willShowFooter && (!(layout.isAnimOn(SHOW_FOOTER)))) { willShowFooter = false; isFooterVisible = true; loadFooterInfo(); playShowAnim(SHOW_FOOTER); } setupLives(); // FUCK IT updatePressableButtonThingies(); int scCount = getUnspentStarCoinCount(); WriteNumberToTextBox(&scCount, StarCoinCounter, false); layout.execAnimations(); layout.update(); return true; } int dWMHud_c::onDraw() { if (!layoutLoaded) return true; layout.scheduleForDrawing(); return true; } void dWMHud_c::playShowAnim(int id) { if (!this || !this->layoutLoaded) return; layout.enableNonLoopAnim(id); } void dWMHud_c::playHideAnim(int id) { if (!this || !this->layoutLoaded) return; if (!layout.isAnimOn(id)) { layout.enableNonLoopAnim(id, true); } layout.grpHandlers[id].frameCtrl.flags = 3; // NO_LOOP | REVERSE if (id == SHOW_FOOTER) isFooterVisible = false; } void dWMHud_c::loadHeaderInfo() { dLevelInfo_c *levelInfo = &dLevelInfo_c::s_info; dLevelInfo_c::entry_s *infEntry = levelInfo->searchBySlot( nodeForHeader->levelNumber[0]-1, nodeForHeader->levelNumber[1]-1); if (infEntry == 0) { LevelName->SetString(L"Unknown Level Name!"); LevelNameS->SetString(L"Unknown Level Name!"); return; } // LEVEL NAME wchar_t convertedLevelName[100]; const char *sourceLevelName = levelInfo->getNameForLevel(infEntry); int charCount = 0; while (*sourceLevelName != 0 && charCount < 99) { convertedLevelName[charCount] = *sourceLevelName; sourceLevelName++; charCount++; } convertedLevelName[charCount] = 0; LevelName->SetString(convertedLevelName); LevelNameS->SetString(convertedLevelName); // a hack because I don't feel like editing the rlyt LevelName->size.x = LevelNameS->size.x = 400.0f; // LEVEL NUMBER wchar_t levelNumber[16]; getNewerLevelNumberString(infEntry->displayWorld, infEntry->displayLevel, levelNumber); LevelNumber->SetString(levelNumber); // make the picture shadowy int sidx = 0; while (levelNumber[sidx]) { if (levelNumber[sidx] == 11) { levelNumber[sidx+1] = 0x200 | (levelNumber[sidx+1]&0xFF); sidx += 2; } sidx++; } LevelNumberS->SetString(levelNumber); nw4r::ut::TextWriter tw2; tw2.font = LevelNumber->font; tw2.SetFontSize(LevelNumber->fontSizeX, LevelNumber->fontSizeY); tw2.lineSpace = LevelNumber->lineSpace; tw2.charSpace = LevelNumber->charSpace; if (LevelNumber->tagProc != 0) tw2.tagProcessor = LevelNumber->tagProc; float currentPos = tw2.CalcStringWidth(levelNumber, wcslen(levelNumber)); currentPos += LevelNumber->trans.x + 12.0f; // INFO int w = nodeForHeader->levelNumber[0] - 1; int l = nodeForHeader->levelNumber[1] - 1; u32 conds = GetSaveFile()->GetBlock(-1)->GetLevelCondition(w, l); NormalExitFlag->trans.x = currentPos; NormalExitFlag->SetVisible(conds & COND_NORMAL); if (conds & COND_NORMAL) currentPos += NormalExitFlag->size.x; SecretExitFlag->trans.x = currentPos; SecretExitFlag->SetVisible(conds & COND_SECRET); if (conds & COND_SECRET) currentPos += SecretExitFlag->size.x; // are star coins enabled or not? bool haveSC = (infEntry->flags & 2); for (int i = 0; i < 3; i++) { bool flag = (conds & (COND_COIN1 << i)); StarCoinOn[i]->SetVisible(flag); StarCoinOff[i]->SetVisible(haveSC); if (haveSC) { StarCoinOff[i]->trans.x = currentPos; currentPos += StarCoinOff[i]->size.x + 4.0f; } } // SIZE THING nw4r::ut::TextWriter tw; tw.font = LevelName->font; tw.SetFontSize(LevelName->fontSizeX, LevelName->fontSizeY); tw.lineSpace = LevelName->lineSpace; tw.charSpace = LevelName->charSpace; if (LevelName->tagProc != 0) tw.tagProcessor = LevelName->tagProc; float width = tw.CalcStringWidth(convertedLevelName, charCount); float totalWidth = width + LevelName->trans.x - 20.0f; if (totalWidth < currentPos) totalWidth = currentPos; Header_Centre->size.x = totalWidth; Header_Right->trans.x = totalWidth; SaveBlock *save = GetSaveFile()->GetBlock(-1); headerCol.colourise(save->hudHintH, save->hudHintS, save->hudHintL); } void dWMHud_c::loadFooterInfo() { SaveBlock *save = GetSaveFile()->GetBlock(-1); wchar_t convertedWorldName[32]; int i; for (i = 0; i < 32; i++) { convertedWorldName[i] = save->newerWorldName[i]; if (convertedWorldName[i] == 0) break; } convertedWorldName[31] = 0; WorldName->SetString(convertedWorldName); WorldNameS->SetString(convertedWorldName); WorldName->colour1 = save->hudTextColours[0]; WorldName->colour2 = save->hudTextColours[1]; footerCol.colourise(save->hudHintH, save->hudHintS, save->hudHintL); // figure out if stars are needed // Star 0: world is complete // Star 1: all exits complete // Star 2: all star coins obtained static int lastLevelIDs[] = { -1, /*no world*/ 27, 27, 27, 27, 27, 27, 27, 25, -1, /*no end level in W9*/ 24, 24, 24, 3, 5 }; bool starVisibility[3]; starVisibility[0] = false; dLevelInfo_c *linfo = &dLevelInfo_c::s_info; dLevelInfo_c::entry_s *lastLevel = linfo->searchByDisplayNum(save->newerWorldID, lastLevelIDs[save->newerWorldID]); if (lastLevel) { starVisibility[0] = (save->GetLevelCondition(lastLevel->worldSlot,lastLevel->levelSlot) & COND_NORMAL); } // now calculate the other two starVisibility[1] = true; starVisibility[2] = true; dLevelInfo_c::section_s *sect = linfo->getSectionByIndex(save->newerWorldID); for (int i = 0; i < sect->levelCount; i++) { dLevelInfo_c::entry_s *entry = §->levels[i]; u32 conds = save->GetLevelCondition(entry->worldSlot, entry->levelSlot); if (((entry->flags & 0x10) && !(conds & COND_NORMAL)) || ((entry->flags & 0x20) && !(conds & COND_SECRET))) starVisibility[1] = false; if (entry->flags & 2) { if ((conds & COND_COIN_ALL) != COND_COIN_ALL) starVisibility[2] = false; } } float startX = Star[0]->trans.x; for (int i = 0; i < 3; i++) { Star[i]->SetVisible(starVisibility[i]); Star[i]->trans.x = startX; if (starVisibility[i]) { startX += Star[i]->size.x + 4.0f; } } WorldName->trans.x = startX + 4.0f; WorldNameS->trans.x = startX + 6.0f; } void dWMHud_c::enteredNode(dKPNode_s *node) { if (node == 0) node = dScKoopatlas_c::instance->pathManager.currentNode; if (node->type == dKPNode_s::LEVEL) { willShowHeader = true; nodeForHeader = node; } } void dWMHud_c::leftNode() { if (layout.grpHandlers[SHOW_HEADER].frameCtrl.currentFrame > 0.1f) { // not hidden if ((layout.isAnimOn(SHOW_HEADER) && !(layout.grpHandlers[SHOW_HEADER].frameCtrl.flags & 2)) || (!layout.isAnimOn(SHOW_HEADER))) { // currently being shown, OR fully shown already playHideAnim(SHOW_HEADER); } } } void dWMHud_c::hideFooter() { if (isFooterVisible) playHideAnim(SHOW_FOOTER); } void dWMHud_c::showFooter() { willShowFooter = true; if (isFooterVisible) playHideAnim(SHOW_FOOTER); } void dWMHud_c::setupLives() { static const int LogicalPlayerIDs[] = {0,1,3,2}; P_marioFace_00->SetVisible(false); P_luigiFace_00->SetVisible(false); P_BkinoFace_00->SetVisible(false); P_YkinoFace_00->SetVisible(false); int playerCount = 0; for (int i = 0; i < 4; i++) { // The part in setupLives() int playerID = LogicalPlayerIDs[i]; int slotID = SearchForIndexOfPlayerID(playerID); int lives = Player_Lives[slotID]; int length = 2; WriteNumberToTextBox(&lives, &length, T_lifeNumber[slotID], true); // The part in setupIconThings() if (QueryPlayerAvailability(slotID)) { playerCount++; nw4r::lyt::Pane *facePane = (&P_marioFace_00)[playerID]; facePane->trans = N_IconPosXP_00[playerCount - 1]->trans; facePane->SetVisible(true); } } for (int i = 0; i < 4; i++) N_IconPosXP_00[i]->SetVisible(false); N_IconPosXP_00[playerCount - 1]->SetVisible(true); } void dWMHud_c::updatePressableButtonThingies() { int cntType = RemoconMng->controllers[0]->controllerType; if (cntType != displayedControllerType) { displayedControllerType = cntType; int beef = (cntType == 0) ? 0 : 1; GameMgrP->currentControllerType = beef; WriteBMGToTextBox( layout.findTextBoxByName("ItemsButtonInfo"), GetBMG(), 4, 15, 0); } }