#include "koopatlas/hud.h" void CharToWChar(const char *input, wchar_t *output, int length) { for (int i = 0; i < length; i++) output[i] = input[i]; } int getStarCoinCount() { SaveBlock *save = GetSaveFile()->GetBlock(-1); int coinsSpent = save->credits_hiscore; int coinsEarned = 0; for (int w = 0; w < 10; w++) { for (int l = 0; l < 10; l++) { u32 conds = save->GetLevelCondition(w, l); if (conds & COND_COIN1) { coinsEarned++; } if (conds & COND_COIN2) { coinsEarned++; } if (conds & COND_COIN3) { coinsEarned++; } } } int coinsLeft = coinsEarned - coinsSpent; return coinsLeft; } 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; } // TODO: Need to define these in a better way, somehow #define ANIM_BUTTON_1 0 #define ANIM_BUTTON_2 1 #define ANIM_BOTTOM_SHOW 2 #define ANIM_BOTTOM_HIDE 3 #define ANIM_TOP_SHOW 4 #define ANIM_TOP_HIDE 5 int dWMHud_c::onCreate() { if (!layoutLoaded) { bool gotFile = layout.loadArc("maphud.arc", false); if (!gotFile) return false; //static const char *brlanNames[3] = {"maphud_hitbutton.brlan", "maphud_in.brlan", "maphud_out.brlan"}; static const char *brlanNames[5] = {"maphud_hitbutton.brlan", "bottom_in.brlan", "bottom_out.brlan", "top_in.brlan", "top_out.brlan"}; static const char *groupNames[6] = {"B01_Button", "B02_Button", "A00_Window", "A00_Window", "A01_Window", "A01_Window"}; 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; } layout.loadAnimations(brlanNames, 5); layout.loadGroups(groupNames, (int[6]){0, 0, 1, 2, 3, 4}, 6); layout.disableAllAnimations(); layout.enableNonLoopAnim(ANIM_BOTTOM_SHOW); hidePointBar(); setWorldText(" "); setWorldName(); if (dScKoopatlas_c::instance->pathManager.mustComplainToMapCreator) dWMHud_c::instance->setLevelText("Please Fix Your Missing Entrance. Thanks"); layoutLoaded = true; } return true; } int dWMHud_c::onDelete() { return layout.free(); } int dWMHud_c::onExecute() { updateLives(); setWorldName(); checkPointStatus(); setPointName(); layout.execAnimations(); layout.update(); return true; } int dWMHud_c::onDraw() { layout.scheduleForDrawing(); return true; } void dWMHud_c::updateLives() { static const char *textID[4] = {"M", "L", "B", "Y"}; static const char *picID[4] = {"P_mariopic", "P_luigipic", "P_toadBlue", "P_toadyellow"}; for (int i = 0; i < 4; i++) { char boxName [13]; sprintf(boxName, "T_%slifes_01", textID[i]); nw4r::lyt::TextBox *box = layout.findTextBoxByName(boxName); nw4r::lyt::Pane *pic = layout.findPictureByName(picID[i]); if (Player_Active[i] != 0) { box->alpha = 0xFF; pic->alpha = 0xFF; char lives [3]; sprintf(lives, "%02d", Player_Lives[Player_ID[i]]); const char *loaves = lives; wchar_t life; CharToWChar(loaves, &life, 3); box->SetString(&life); } else { box->alpha = 0; pic->alpha = 0; } } nw4r::lyt::TextBox *coinbox = layout.findTextBoxByName("T_coin_count_01"); char stars [4]; int starCoinCount = getStarCoinCount(); sprintf(stars, "%03d", starCoinCount); const char *scoins = stars; wchar_t wcoins; CharToWChar(scoins, &wcoins, 4); coinbox->SetString(&wcoins); } void dWMHud_c::setLevelText(const char *str, int length) { if (str == 0) { setLevelText("--NULL STRING--"); return; } if (length == -1) { length = strlen(str); } wchar_t newString[128]; int i; for (i = 0; i < length && i < 128; i++) { newString[i] = str[i]; } newString[i] = 0; setLevelText(newString, i); } void dWMHud_c::setLevelText(const wchar_t *str, int length) { if (str == 0) { setLevelText("--NULL STRING--"); return; } if (length == -1) { length = wcslen(str); } nw4r::lyt::TextBox *box = layout.findTextBoxByName("T_levelname_01"); nw4r::ut::TextWriter tw; tw.font = box->font; tw.SetFontSize(box->fontSizeX, box->fontSizeY); tw.somethingRelatedToLineHeight = box->lineSpace; tw.charSpace = box->charSpace; if (box->tagProc != 0) tw.tagProcessorMaybe = box->tagProc; float width = tw.CalcStringWidth(str, length); SpammyReport("Text width: %f\n", width); layout.findWindowByName("W_levelname")->size.x = width + 22; layout.findPictureByName("P_topleftboxbg")->size.x = width; layout.findPictureByName("P_topthinboxbg")->size.x = 597 - width; box->SetString(str); } void dWMHud_c::setPointName() { // figure this out... dKPNode_s *node = dScKoopatlas_c::instance->pathManager.currentNode; if (node->type == dKPNode_s::LEVEL) { dLevelInfo_c *li = &dScKoopatlas_c::instance->levelInfo; dLevelInfo_c::entry_s *entry = li->search(node->levelNumber[0] - 1, node->levelNumber[1] - 1); setLevelText(li->getNameForLevel(entry)); } else { setLevelText(" "); hidePointBar(); } } void dWMHud_c::checkPointStatus() { dKPNode_s *node = dScKoopatlas_c::instance->pathManager.currentNode; if ((node->type == dKPNode_s::LEVEL) && ((node->levelNumber[1] < 30) || (node->levelNumber[1] > 37))) { SaveBlock *save = GetSaveFile()->GetBlock(-1); int world = node->levelNumber[0]; int level = node->levelNumber[1]; u32 conds = save->GetLevelCondition(world-1, level-1); nw4r::lyt::Pane *pic; if (conds & COND_COIN1) { pic = layout.findPictureByName("P_coin_on_01"); pic->alpha = 0xFF; pic = layout.findPictureByName("P_coin_off_01"); pic->alpha = 0; } else { pic = layout.findPictureByName("P_coin_on_01"); pic->alpha = 0; pic = layout.findPictureByName("P_coin_off_01"); pic->alpha = 0xFF; } if (conds & COND_COIN2) { pic = layout.findPictureByName("P_coin_on_02"); pic->alpha = 0xFF; pic = layout.findPictureByName("P_coin_off_02"); pic->alpha = 0; } else { pic = layout.findPictureByName("P_coin_on_02"); pic->alpha = 0; pic = layout.findPictureByName("P_coin_off_02"); pic->alpha = 0xFF; } if (conds & COND_COIN3) { pic = layout.findPictureByName("P_coin_on_03"); pic->alpha = 0xFF; pic = layout.findPictureByName("P_coin_off_03"); pic->alpha = 0; } else { pic = layout.findPictureByName("P_coin_on_03"); pic->alpha = 0; pic = layout.findPictureByName("P_coin_off_03"); pic->alpha = 0xFF; } if (conds & COND_NORMAL) { pic = layout.findPictureByName("P_normalexitflag"); pic->alpha = 0xFF; } else { pic = layout.findPictureByName("P_normalexitflag"); pic->alpha = 0; } if (conds & COND_SECRET) { pic = layout.findPictureByName("P_secretexitflag"); pic->alpha = 0xFF; } else { pic = layout.findPictureByName("P_secretexitflag"); pic->alpha = 0; } u8 deaths = save->death_counts[world-1][level-1]; nw4r::lyt::TextBox *deathbox = layout.findTextBoxByName("T_death_01"); char die [4]; sprintf(die, "%03d", deaths); const char *dies = die; wchar_t wdie; CharToWChar(dies, &wdie, 4); deathbox->SetString(&wdie); } else { nw4r::lyt::Pane *pic; static const char *picNames[8] = {"P_coin_on_01", "P_coin_off_01", "P_coin_on_02", "P_coin_off_02", "P_coin_on_03", "P_coin_off_03", "P_normalexitflag", "P_secretexitflag"}; for (int i = 0; i < 8; i++) { pic = layout.findPictureByName(picNames[i]); pic->alpha = 0; } nw4r::lyt::TextBox *deathbox = layout.findTextBoxByName("T_death_01"); wchar_t noDie; CharToWChar("---", &noDie, 4); deathbox->SetString(&noDie); } } void dWMHud_c::setWorldText(const char *str, int length) { if (str == 0) { setWorldText("--NULL STRING--"); return; } if (length == -1) { length = strlen(str); } wchar_t newString[128]; int i; for (i = 0; i < length && i < 128; i++) { newString[i] = str[i]; } newString[i] = 0; setWorldText(newString, i); } void dWMHud_c::setWorldText(const wchar_t *str, int length) { if (str == 0) { setWorldText("--NULL STRING--"); return; } if (length == -1) { length = wcslen(str); } nw4r::lyt::TextBox *box = layout.findTextBoxByName("T_area_01"); nw4r::ut::TextWriter tw; tw.font = box->font; tw.SetFontSize(box->fontSizeX, box->fontSizeY); tw.somethingRelatedToLineHeight = box->lineSpace; tw.charSpace = box->charSpace; if (box->tagProc != 0) tw.tagProcessorMaybe = box->tagProc; float width = tw.CalcStringWidth(str, length); SpammyReport("Text width: %f\n", width); box->SetString(str); } void dWMHud_c::setWorldName() { // figure this out... dKPNode_s *node = dScKoopatlas_c::instance->pathManager.currentNode; if (node->type == dKPNode_s::LEVEL) { int world = node->levelNumber[0]; int level = node->levelNumber[1]; setWorldText(NewerWorldName(NewerWorldForLevelID(world, level))); } } void dWMHud_c::showPointBar() { dKPNode_s *node = dScKoopatlas_c::instance->pathManager.currentNode; if (node->type == dKPNode_s::LEVEL) { isPointBarShown = true; layout.enableNonLoopAnim(ANIM_TOP_SHOW); } } void dWMHud_c::hidePointBar() { if (isPointBarShown) { isPointBarShown = false; layout.enableNonLoopAnim(ANIM_TOP_HIDE); } }