From c10922832433aac641ca4f14a06dd4ff46977f84 Mon Sep 17 00:00:00 2001 From: Adrian Tracz Date: Wed, 19 Oct 2022 10:59:54 +0200 Subject: [PATCH 1/8] Implement loading Help.tbl from v1264 client. --- src/game/GameBase.cpp | 6 ++++++ src/game/GameBase.h | 3 ++- src/game/GameDef.h | 9 +++++++++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/game/GameBase.cpp b/src/game/GameBase.cpp index cf3e80a4..178b042b 100644 --- a/src/game/GameBase.cpp +++ b/src/game/GameBase.cpp @@ -28,6 +28,7 @@ CN3TableBase<__TABLE_PLAYER_LOOKS> * CGameBase::s_pTbl_NPC_Looks = CN3TableBase<__TABLE_QUEST_MENU> * CGameBase::s_pTbl_QuestMenu = NULL; // Äù½ºÆ® ¼±Åà ¸Þ´º CN3TableBase<__TABLE_QUEST_TALK> * CGameBase::s_pTbl_QuestTalk = NULL; // Äù½ºÆ® Áö¹® CN3TableBase<__TABLE_TEXTS> * CGameBase::s_pTbl_Texts = NULL; +CN3TableBase<__TABLE_HELP> * CGameBase::s_pTbl_Help = NULL; CN3WorldManager * CGameBase::s_pWorldMgr = NULL; // ¿ùµå ¸Å´ÏÁ®.. CPlayerOtherMgr * CGameBase::s_pOPMgr = NULL; // Other Player Manager - ´Ù¸¥ À¯Àú °ü¸® Ŭ·¡½º.. @@ -73,6 +74,7 @@ void CGameBase::StaticMemberInit() { s_pTbl_QuestMenu = new CN3TableBase<__TABLE_QUEST_MENU>; s_pTbl_QuestTalk = new CN3TableBase<__TABLE_QUEST_TALK>; s_pTbl_Texts = new CN3TableBase<__TABLE_TEXTS>; + s_pTbl_Help = new CN3TableBase<__TABLE_HELP>; std::string szLangTail = ".tbl"; int iLangID = ::GetUserDefaultLangID(); @@ -96,6 +98,8 @@ void CGameBase::StaticMemberInit() { s_pTbl_QuestTalk->LoadFromFile(szFN.c_str()); // Äù½ºÆ® °ü·Ã Áö¹® szFN = "Data\\Texts" + szLangTail; s_pTbl_Texts->LoadFromFile(szFN.c_str()); + szFN = "Data\\Help" + szLangTail; + s_pTbl_Help->LoadFromFile(szFN.c_str()); for (int i = 0; i < MAX_ITEM_EXTENSION; i++) { char szFNTmp[256] = ""; @@ -146,6 +150,8 @@ void CGameBase::StaticMemberRelease() { s_pTbl_QuestTalk = NULL; // Äù½ºÆ® °ü·Ã Áö¹® delete s_pTbl_Texts; s_pTbl_Texts = NULL; + delete s_pTbl_Help; + s_pTbl_Help = NULL; delete s_pPlayer; s_pPlayer = NULL; // Player Character diff --git a/src/game/GameBase.h b/src/game/GameBase.h index 1dda1bca..9beae60a 100644 --- a/src/game/GameBase.h +++ b/src/game/GameBase.h @@ -27,7 +27,8 @@ class CGameBase : public CN3Base { static CN3TableBase * s_pTbl_FXSource; // FX¼Ò½º Á¤º¸ Å×À̺í.. static CN3TableBase * s_pTbl_QuestMenu; // Äù½ºÆ® ¼±Åà ¸Þ´º static CN3TableBase * s_pTbl_QuestTalk; // Äù½ºÆ® Áö¹® - static CN3TableBase * s_pTbl_Texts; + static CN3TableBase * s_pTbl_Texts; // Localized strings + static CN3TableBase * s_pTbl_Help; // Leveling Guide static class CN3WorldManager * s_pWorldMgr; // ¿ùµå ¸Å´ÏÁ® Ŭ·¡½º.. static class CPlayerOtherMgr * s_pOPMgr; // Other Player Manager - ´Ù¸¥ À¯Àú °ü¸® Ŭ·¡½º.. diff --git a/src/game/GameDef.h b/src/game/GameDef.h index c1060c3f..d030f25a 100644 --- a/src/game/GameDef.h +++ b/src/game/GameDef.h @@ -1275,6 +1275,15 @@ typedef struct __TABLE_QUEST_TALK { std::string szTalk; // Äù½ºÆ® Áö¹® } TABLE_QUEST_TALK; +typedef struct __TABLE_HELP { + DWORD dwID; + int pLevelMin; + int pLevelMax; + int pClass; + std::string qTitle; + std::string qDesc; +} TABLE_HELP; + typedef struct __TABLE_TEXTS { DWORD dwID; std::string szText; From 21641cce5694c721bfb9d4a701644e1e56c3182c Mon Sep 17 00:00:00 2001 From: Adrian Tracz Date: Wed, 19 Oct 2022 11:24:43 +0200 Subject: [PATCH 2/8] Add funcionality of leveling guide uif. + Fix setting uif position. + Implement loading quest info data. --- src/game/GameProcMain.cpp | 49 +++++++++++- src/game/GameProcMain.h | 1 + src/game/UILevelGuide.cpp | 156 +++++++++++++++++++++++++++++++++----- src/game/UILevelGuide.h | 32 ++++---- src/game/UIStateBar.cpp | 2 +- src/game/res/Resource.h | 1 + 6 files changed, 205 insertions(+), 36 deletions(-) diff --git a/src/game/GameProcMain.cpp b/src/game/GameProcMain.cpp index ea5f2188..5c202919 100644 --- a/src/game/GameProcMain.cpp +++ b/src/game/GameProcMain.cpp @@ -3884,11 +3884,9 @@ void CGameProcMain::InitUI() { m_pUILevelGuide->Init(s_pUIMgr); m_pUILevelGuide->LoadFromFile(pTbl->szLevelGuide); m_pUILevelGuide->SetVisibleWithNoSound(false); - m_pUILevelGuide->SetStyle(UISTYLE_USER_MOVE_HIDE); + m_pUILevelGuide->SetStyle(UISTYLE_HIDE_UNABLE | UISTYLE_POS_RIGHT); rc = m_pUILevelGuide->GetRegion(); - iX = (iW - (rc.right - rc.left)) / 2; - iY = (iH - (rc.bottom - rc.top)) / 2; - m_pUILevelGuide->SetPos(iX, iY); + m_pUILevelGuide->SetPos(iW - (rc.right - rc.left), 10); // dead ui m_pUIDead->Init(s_pUIMgr); @@ -4484,6 +4482,10 @@ bool CGameProcMain::CommandToggleUIInventory() { m_pUINotice->Close(); } + if (m_pUILevelGuide->IsVisible()) { + m_pUILevelGuide->SetVisible(false); + } + if (m_pUIInventory->IsVisible()) { m_pUIInventory->Close(true); return bNeedOpen; @@ -4521,6 +4523,9 @@ bool CGameProcMain::CommandToggleUISkillTree() { if (m_pUINotice->IsVisible()) { m_pUINotice->Close(); } + if (m_pUILevelGuide->IsVisible()) { + m_pUILevelGuide->SetVisible(false); + } s_pUIMgr->SetFocusedUI(m_pUISkillTreeDlg); m_pUISkillTreeDlg->Open(); @@ -4551,6 +4556,9 @@ bool CGameProcMain::CommandToggleUINotice() { if (m_pUISkillTreeDlg->IsVisible()) { m_pUISkillTreeDlg->Close(); } + if (m_pUILevelGuide->IsVisible()) { + m_pUILevelGuide->SetVisible(false); + } s_pUIMgr->SetFocusedUI(m_pUINotice); m_pUINotice->Open(); @@ -4561,6 +4569,39 @@ bool CGameProcMain::CommandToggleUINotice() { return bNeedOpen; } +bool CGameProcMain::CommandToggleUILevelGuide() { + bool bNeedOpen = !(m_pUILevelGuide->IsVisible()); + + if (m_pSubProcPerTrade->m_ePerTradeState != PER_TRADE_STATE_NONE) { + return bNeedOpen; + } + + if (bNeedOpen) { + if (m_pUIInventory->IsVisible()) { + m_pUIInventory->Close(); + } + if (m_pUITransactionDlg->IsVisible()) { + m_pUITransactionDlg->LeaveTransactionState(); + } + if (m_pUIWareHouseDlg->IsVisible()) { + m_pUIWareHouseDlg->LeaveWareHouseState(); + } + if (m_pUISkillTreeDlg->IsVisible()) { + m_pUISkillTreeDlg->Close(); + } + if (m_pUINotice->IsVisible()) { + m_pUINotice->SetVisible(false); + } + + s_pUIMgr->SetFocusedUI(m_pUILevelGuide); + m_pUILevelGuide->Open(); + } else { + m_pUILevelGuide->SetVisible(false); + } + + return bNeedOpen; +} + bool CGameProcMain::CommandToggleUIMiniMap() { return m_pUIStateBarAndMiniMap->ToggleMiniMap(); } diff --git a/src/game/GameProcMain.h b/src/game/GameProcMain.h index def3e613..0865923a 100644 --- a/src/game/GameProcMain.h +++ b/src/game/GameProcMain.h @@ -224,6 +224,7 @@ class CGameProcMain : public CGameProcedure { bool CommandToggleUISkillTree(); bool CommandToggleUIMiniMap(); bool CommandToggleUINotice(); + bool CommandToggleUILevelGuide(); void CommandMove(e_MoveDirection eMD, bool bStartOrEnd); // ¿òÁ÷ÀÌ´Â ¹æÇâ(ÀüÈÄÁø, ¸ØÃã), ¿òÁ÷À̱⠽ÃÀÛÇϴ°¡? void CommandEnableAttackContinous(bool bEnable, CPlayerBase * pTarget); diff --git a/src/game/UILevelGuide.cpp b/src/game/UILevelGuide.cpp index bb7392e1..6b651972 100644 --- a/src/game/UILevelGuide.cpp +++ b/src/game/UILevelGuide.cpp @@ -3,6 +3,10 @@ #include "UILevelGuide.h" #include "N3Base/N3UIString.h" #include "N3Base/N3UIScrollBar.h" +#include "N3Base/N3UIEdit.h" +#include "PlayerMySelf.h" +#include "Resource.h" +#include "GameProcMain.h" CUILevelGuide::CUILevelGuide() { for (size_t i = 0; i < MAX_GUIDE_PAGE; ++i) { @@ -18,8 +22,105 @@ CUILevelGuide::CUILevelGuide() { m_iCurrPage = 0; } -CUILevelGuide::~CUILevelGuide() { - m_QuestList.clear(); +CUILevelGuide::~CUILevelGuide() {} + +void CUILevelGuide::LoadQuestData(int sLevel) { + m_iCurrPage = 1; + + int lvlMin = 0; + int pLevel = CGameBase::s_pPlayer->m_InfoBase.iLevel; + + m_pText_Level->SetStringAsInt(pLevel); + m_pText_Page->SetStringAsInt(1); + + if (sLevel - pLevel > MAX_SEARCH_ABOVE_PLAYER_LEVEL) { + m_pText_Level->SetStringAsInt(pLevel + MAX_SEARCH_ABOVE_PLAYER_LEVEL); + + char searchText[70]; + + std::string szMsg; + ::_LoadStringFromResource(IDS_QUEST_MENU_SEARCH_LEVEL_MAX_INFO, szMsg); + sprintf(searchText, szMsg.c_str(), MAX_SEARCH_ABOVE_PLAYER_LEVEL); + + CGameProcedure::MessageBoxPost(searchText, "", MB_OK, BEHAVIOR_NOTHING); + } + + int page = 1; + int questIndex = 0; + + for (int i = 1; i < CGameProcedure::s_pProcMain->s_pTbl_Help->GetSize(); i++) { + __TABLE_HELP * selectedQuest = CGameProcedure::s_pProcMain->s_pTbl_Help->Find(i); + + if (sLevel >= selectedQuest->pLevelMin && isQuestIsAvailableForPlayer(selectedQuest->pClass)) { + + m_Quests[page][questIndex] = i; + + if (i % 3 == 0) { + page++; + questIndex = 0; + } else { + questIndex++; + } + } + } + + m_iMaxPage = page; + + for (int i = 0; i < 3; i++) { + __TABLE_HELP * questObj = CGameProcedure::s_pProcMain->s_pTbl_Help->Find(m_Quests[1][i]); + + m_pText_Titles[i]->SetString(questObj->qTitle); + m_pText_Guides[i]->SetString(questObj->qDesc); + + int maxLineCount = m_pText_Guides[i]->GetLineCount(); + + m_pScroll_Guides[i]->SetRange(0, maxLineCount); + m_pScroll_Guides[i]->SetCurrentPos(0); + } +} + +bool CUILevelGuide::isQuestIsAvailableForPlayer(int questRequiredClass) { + + int pClass = CGameBase::s_pPlayer->m_InfoBase.eClass; + + if (questRequiredClass == 100) { // for all + return true; + } + + if (questRequiredClass == 0 && + (pClass == CLASS_KA_WARRIOR || pClass == CLASS_KA_BERSERKER || pClass == CLASS_KA_GUARDIAN || + pClass == CLASS_EL_WARRIOR || pClass == CLASS_EL_BLADE || pClass == CLASS_EL_PROTECTOR)) { // warrior + return true; + } + + if (questRequiredClass == 1 && + (pClass == CLASS_KA_ROGUE || pClass == CLASS_KA_HUNTER || pClass == CLASS_KA_PENETRATOR || + pClass == CLASS_EL_ROGUE || pClass == CLASS_EL_RANGER || pClass == CLASS_EL_ASSASIN)) { // rouge + return true; + } + + if (questRequiredClass == 2 && + (pClass == CLASS_KA_WIZARD || pClass == CLASS_KA_SORCERER || pClass == CLASS_KA_NECROMANCER || + pClass == CLASS_EL_WIZARD || pClass == CLASS_EL_MAGE || pClass == CLASS_EL_ENCHANTER)) { // mage + return true; + } + + if (questRequiredClass == 3 && + (pClass == CLASS_KA_PRIEST || pClass == CLASS_KA_SHAMAN || pClass == CLASS_KA_DARKPRIEST || + pClass == CLASS_EL_PRIEST || pClass == CLASS_EL_CLERIC || pClass == CLASS_EL_DRUID)) { // priest + return true; + } + + return false; +} + +void CUILevelGuide::Open() { + m_iCurrPage = 1; + SetVisible(true); + + LoadQuestData(CGameBase::s_pPlayer->m_InfoBase.iLevel); + + return; } bool CUILevelGuide::Load(HANDLE hFile) { @@ -65,9 +166,7 @@ bool CUILevelGuide::Load(HANDLE hFile) { m_pScroll_Guides[i] = (CN3UIScrollBar *)(this->GetChildByID("scroll_guide" + indexStr)); __ASSERT(m_pScroll_Guides[i], "NULL UI Component!!"); - if (m_pScroll_Guides[i]) { - m_pScroll_Guides[i]->SetVisible(false); - } + m_pScroll_Guides[i]->SetRange(0, 0); } if (m_pText_Page) { @@ -77,6 +176,23 @@ bool CUILevelGuide::Load(HANDLE hFile) { return true; } +void CUILevelGuide::ChangePage(int iIndex) { + __TABLE_HELP * questObj = NULL; + + m_pText_Page->SetStringAsInt(iIndex); + + for (int i = 0; i < 3; i++) { + questObj = CGameProcedure::s_pProcMain->s_pTbl_Help->Find(m_Quests[iIndex][i]); + m_pText_Titles[i]->SetString(questObj->qTitle); + m_pText_Guides[i]->SetString(questObj->qDesc); + + int maxLineCount = m_pText_Guides[i]->GetLineCount(); + + m_pScroll_Guides[i]->SetRange(0, maxLineCount); + m_pScroll_Guides[i]->SetCurrentPos(0); + } +} + bool CUILevelGuide::ReceiveMessage(CN3UIBase * pSender, DWORD dwMsg) { if (!pSender) { return false; @@ -84,18 +200,30 @@ bool CUILevelGuide::ReceiveMessage(CN3UIBase * pSender, DWORD dwMsg) { if (dwMsg == UIMSG_BUTTON_CLICK) { if (pSender == (CN3UIBase *)m_pBtn_Check) { - Check(); + int checkLevel = std::stoi(m_pEdit_Level->GetString()); + LoadQuestData(checkLevel); return true; } else if (pSender == (CN3UIBase *)m_pBtn_Cancel) { SetVisible(false); return true; } else if (pSender == (CN3UIBase *)m_pBtn_Up) { - MovePage(m_iCurrPage + 1); + + if (m_iCurrPage >= m_iMaxPage) { + return true; + } + ChangePage(++m_iCurrPage); + return true; } else if (pSender == (CN3UIBase *)m_pBtn_Down) { - MovePage(m_iCurrPage - 1); + + if (m_iCurrPage <= 1) { + return true; + } + ChangePage(--m_iCurrPage); + return true; } + } else if (dwMsg == UIMSG_SCROLLBAR_POS) { int iIndex = -1; for (size_t i = 0; i < MAX_GUIDE_PAGE; ++i) { @@ -108,16 +236,10 @@ bool CUILevelGuide::ReceiveMessage(CN3UIBase * pSender, DWORD dwMsg) { return true; } - m_pText_Guides[iIndex]->SetStartLine(m_pScroll_Guides[iIndex]->GetCurrentPos()); + if (m_pText_Guides[iIndex]->GetString().length() > 0) { + m_pText_Guides[iIndex]->SetStartLine(m_pScroll_Guides[iIndex]->GetCurrentPos()); + } } return true; } - -void CUILevelGuide::Check() { - N3_WARN("[CUILevelGuide::Check] TODO: needs implementing."); -} - -void CUILevelGuide::MovePage(int iIndex) { - N3_WARN("[CUILevelGuide::MovePage] TODO: needs implementing."); -} diff --git a/src/game/UILevelGuide.h b/src/game/UILevelGuide.h index 5bd75679..126d4a77 100644 --- a/src/game/UILevelGuide.h +++ b/src/game/UILevelGuide.h @@ -4,6 +4,7 @@ #include const int MAX_GUIDE_PAGE = 3; +const int MAX_SEARCH_ABOVE_PLAYER_LEVEL = 5; class CUILevelGuide : public CN3UIBase { public: @@ -12,21 +13,24 @@ class CUILevelGuide : public CN3UIBase { bool Load(HANDLE hFile); bool ReceiveMessage(CN3UIBase * pSender, DWORD dwMsg); + bool isQuestIsAvailableForPlayer(int questRequiredClass); - void Check(); - void MovePage(int iIndex); + void Open(); + void ChangePage(int iIndex); + void LoadQuestData(int sLevel = 0); public: - CN3UIEdit * m_pEdit_Level; - CN3UIButton * m_pBtn_Check; - CN3UIButton * m_pBtn_Cancel; - CN3UIButton * m_pBtn_Up; - CN3UIButton * m_pBtn_Down; - CN3UIString * m_pText_Titles[MAX_GUIDE_PAGE]; - CN3UIString * m_pText_Guides[MAX_GUIDE_PAGE]; - CN3UIString * m_pText_Page; - CN3UIString * m_pText_Level; - CN3UIScrollBar * m_pScroll_Guides[MAX_GUIDE_PAGE]; - std::list m_QuestList; - int m_iCurrPage; + CN3UIEdit * m_pEdit_Level; + CN3UIButton * m_pBtn_Check; + CN3UIButton * m_pBtn_Cancel; + CN3UIButton * m_pBtn_Up; + CN3UIButton * m_pBtn_Down; + CN3UIString * m_pText_Titles[MAX_GUIDE_PAGE]; + CN3UIString * m_pText_Guides[MAX_GUIDE_PAGE]; + CN3UIString * m_pText_Page; + CN3UIString * m_pText_Level; + CN3UIScrollBar * m_pScroll_Guides[MAX_GUIDE_PAGE]; + int m_iCurrPage; + int m_iMaxPage; + int m_Quests[30][MAX_GUIDE_PAGE]; }; diff --git a/src/game/UIStateBar.cpp b/src/game/UIStateBar.cpp index e8ad226b..5df9798d 100644 --- a/src/game/UIStateBar.cpp +++ b/src/game/UIStateBar.cpp @@ -648,7 +648,7 @@ bool CUIStateBar::ReceiveMessage(CN3UIBase * pSender, DWORD dwMsg) { } else if (dwMsg == UIMSG_BUTTON_CLICK) { if (pSender == (CN3UIBase *)m_pBtn_Quest) { if (CGameProcedure::s_pProcMain->m_pUILevelGuide) { - CGameProcedure::s_pProcMain->m_pUILevelGuide->SetVisible(true); + CGameProcedure::s_pProcMain->CommandToggleUILevelGuide(); } m_bQuestButtonClicked = true; return true; diff --git a/src/game/res/Resource.h b/src/game/res/Resource.h index d751cdd2..2e514f51 100644 --- a/src/game/res/Resource.h +++ b/src/game/res/Resource.h @@ -514,6 +514,7 @@ #define IDS_DEAD_REVIVAL_MESSAGE 6603 #define IDS_DEAD_LOW_LEVEL 6604 #define IDS_INVEN_WEIGHT 6605 +#define IDS_QUEST_MENU_SEARCH_LEVEL_MAX_INFO 10100 #define IDS_NATIONSELECT_MSGBOX_SELECTION 10420 #define IDS_NATIONSELECT_DESCRIPTION_KA 10421 #define IDS_NATIONSELECT_DESCRIPTION_EL 10422 From 2654840b0a3bc2fba832e877cc36273753388a5d Mon Sep 17 00:00:00 2001 From: Steve Williams <90905675+stevewgr@users.noreply.github.com> Date: Sun, 23 Oct 2022 07:53:56 -0700 Subject: [PATCH 3/8] Add comment explaining the custom behavior. --- src/game/UIStateBar.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/game/UIStateBar.cpp b/src/game/UIStateBar.cpp index 5df9798d..8610e675 100644 --- a/src/game/UIStateBar.cpp +++ b/src/game/UIStateBar.cpp @@ -648,6 +648,9 @@ bool CUIStateBar::ReceiveMessage(CN3UIBase * pSender, DWORD dwMsg) { } else if (dwMsg == UIMSG_BUTTON_CLICK) { if (pSender == (CN3UIBase *)m_pBtn_Quest) { if (CGameProcedure::s_pProcMain->m_pUILevelGuide) { + // Note that officialy they call SetVisible, however @xGuTeK's implementation + // here is much friendlier, making the Quest button toggling the leveling guide. + //CGameProcedure::s_pProcMain->m_pUILevelGuide->SetVisible(true); CGameProcedure::s_pProcMain->CommandToggleUILevelGuide(); } m_bQuestButtonClicked = true; From 77df9b93cd98272f7f6e35bea3a2e3c447c312af Mon Sep 17 00:00:00 2001 From: Steve Williams <90905675+stevewgr@users.noreply.github.com> Date: Sun, 23 Oct 2022 07:54:45 -0700 Subject: [PATCH 4/8] Set leveling guide position as per official. --- src/game/GameProcMain.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/game/GameProcMain.cpp b/src/game/GameProcMain.cpp index 5c202919..e3236873 100644 --- a/src/game/GameProcMain.cpp +++ b/src/game/GameProcMain.cpp @@ -3884,9 +3884,10 @@ void CGameProcMain::InitUI() { m_pUILevelGuide->Init(s_pUIMgr); m_pUILevelGuide->LoadFromFile(pTbl->szLevelGuide); m_pUILevelGuide->SetVisibleWithNoSound(false); - m_pUILevelGuide->SetStyle(UISTYLE_HIDE_UNABLE | UISTYLE_POS_RIGHT); + m_pUILevelGuide->SetStyle(m_pUILevelGuide->GetStyle() | UISTYLE_POS_RIGHT); rc = m_pUILevelGuide->GetRegion(); m_pUILevelGuide->SetPos(iW - (rc.right - rc.left), 10); + m_pUILevelGuide->SetState(UI_STATE_COMMON_NONE); // dead ui m_pUIDead->Init(s_pUIMgr); From 65cf03346f4f367af977b5e2c4a9d8675e59427d Mon Sep 17 00:00:00 2001 From: Steve Williams <90905675+stevewgr@users.noreply.github.com> Date: Sun, 23 Oct 2022 07:55:35 -0700 Subject: [PATCH 5/8] Implement getting real string width based on rect. Note that this may be useful, when calculating the width of the string based on the ui's region without having to provide the size. --- src/engine/N3Base/N3UIString.cpp | 10 +++++++++- src/engine/N3Base/N3UIString.h | 1 + 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/engine/N3Base/N3UIString.cpp b/src/engine/N3Base/N3UIString.cpp index 25d212d7..92f5e561 100644 --- a/src/engine/N3Base/N3UIString.cpp +++ b/src/engine/N3Base/N3UIString.cpp @@ -472,7 +472,7 @@ void CN3UIString::ChangeFont(const std::string & szFont) { #endif int CN3UIString::GetStringRealWidth(int iNum) { - SIZE size; + SIZE size{}; BOOL bFlag = m_pDFont->GetTextExtent("°¡", lstrlen("°¡"), &size); __ASSERT(bFlag, "cannot get size of dfont"); int iLength = iNum / 2; @@ -482,6 +482,14 @@ int CN3UIString::GetStringRealWidth(int iNum) { return (size.cx * iLength); } +int CN3UIString::GetStringRealWidthRect() { + SIZE size{}; + BOOL bFlag = m_pDFont->GetTextExtent("°¡", lstrlen("°¡"), &size); + __ASSERT(bFlag, "cannot get size of dfont"); + + return (size.cy > 0) ? (m_rcRegion.bottom - m_rcRegion.top) / size.cy : 0; +} + void CN3UIString::SetStyle(DWORD dwType, DWORD dwStyleEx) { if (dwType == UI_STR_TYPE_LINE) { DWORD dwStyle = m_dwStyle; diff --git a/src/engine/N3Base/N3UIString.h b/src/engine/N3Base/N3UIString.h index 7c6fec6b..762638b3 100644 --- a/src/engine/N3Base/N3UIString.h +++ b/src/engine/N3Base/N3UIString.h @@ -37,6 +37,7 @@ class CN3UIString : public CN3UIBase { int GetLineCount() const { return m_iLineCount; } int GetStartLine() const { return m_iStartLine; } int GetStringRealWidth(int iNum); + int GetStringRealWidthRect(); virtual DWORD MouseProc(DWORD dwFlags, const POINT & ptCur, const POINT & ptOld); virtual void Render(); From f99d66fa437afd537686caf4ca0416272fc02955 Mon Sep 17 00:00:00 2001 From: Steve Williams <90905675+stevewgr@users.noreply.github.com> Date: Sun, 23 Oct 2022 07:58:20 -0700 Subject: [PATCH 6/8] Add represent class generic to default to 100. Note that this is official behavior and in some cases we want to represent certain actions for all classes. for example quests in leveling guide. --- src/game/GameBase.cpp | 5 +++-- src/game/GameDef.h | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/game/GameBase.cpp b/src/game/GameBase.cpp index 178b042b..b56bfb73 100644 --- a/src/game/GameBase.cpp +++ b/src/game/GameBase.cpp @@ -471,9 +471,10 @@ e_Class_Represent CGameBase::GetRepresentClass(e_Class eClass) { case CLASS_EL_CLERIC: case CLASS_EL_DRUID: return CLASS_REPRESENT_PRIEST; - } - return CLASS_REPRESENT_UNKNOWN; + default: + return CLASS_REPRESENT_GENERIC; + } } bool CGameBase::GetTextByNation(e_Nation eNation, std::string & szText) { diff --git a/src/game/GameDef.h b/src/game/GameDef.h index d030f25a..34a80e2b 100644 --- a/src/game/GameDef.h +++ b/src/game/GameDef.h @@ -115,6 +115,7 @@ enum e_Class_Represent { CLASS_REPRESENT_ROGUE, CLASS_REPRESENT_WIZARD, CLASS_REPRESENT_PRIEST, + CLASS_REPRESENT_GENERIC = 100, CLASS_REPRESENT_UNKNOWN = 0xffffffff }; From 3257667b00875a06cac4928801253d75fd949835 Mon Sep 17 00:00:00 2001 From: Steve Williams <90905675+stevewgr@users.noreply.github.com> Date: Sun, 23 Oct 2022 08:00:38 -0700 Subject: [PATCH 7/8] Change Help tbl to lower to match with the assets. Just to make sure we stick to the official assets, since in some platforms case sensitive can cause issues loading files. --- src/game/GameBase.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/GameBase.cpp b/src/game/GameBase.cpp index b56bfb73..c9a8c47f 100644 --- a/src/game/GameBase.cpp +++ b/src/game/GameBase.cpp @@ -98,7 +98,7 @@ void CGameBase::StaticMemberInit() { s_pTbl_QuestTalk->LoadFromFile(szFN.c_str()); // Äù½ºÆ® °ü·Ã Áö¹® szFN = "Data\\Texts" + szLangTail; s_pTbl_Texts->LoadFromFile(szFN.c_str()); - szFN = "Data\\Help" + szLangTail; + szFN = "Data\\help" + szLangTail; s_pTbl_Help->LoadFromFile(szFN.c_str()); for (int i = 0; i < MAX_ITEM_EXTENSION; i++) { From 1436ee9cfb153b9f230cf06f6cfc06122b60c675 Mon Sep 17 00:00:00 2001 From: Steve Williams <90905675+stevewgr@users.noreply.github.com> Date: Sun, 23 Oct 2022 08:02:27 -0700 Subject: [PATCH 8/8] Rewrite re version of v1264 leveling guide. Note that the previous implementation was missing a lot of details, as well as not using the correct data structures to make the resource allocation more dynamic. Now that everything is reversed engineered with this uif, we can gurantee that it works exactly the same as per official v1264 client. --- src/game/GameDef.h | 12 +- src/game/GameProcMain.cpp | 2 +- src/game/UILevelGuide.cpp | 326 ++++++++++++++++++++------------------ src/game/UILevelGuide.h | 45 +++--- src/game/res/Resource.h | 2 +- 5 files changed, 202 insertions(+), 185 deletions(-) diff --git a/src/game/GameDef.h b/src/game/GameDef.h index 34a80e2b..7b65f0f4 100644 --- a/src/game/GameDef.h +++ b/src/game/GameDef.h @@ -1277,12 +1277,12 @@ typedef struct __TABLE_QUEST_TALK { } TABLE_QUEST_TALK; typedef struct __TABLE_HELP { - DWORD dwID; - int pLevelMin; - int pLevelMax; - int pClass; - std::string qTitle; - std::string qDesc; + int iID; + int iLevelMin; + int iLevelMax; + e_Class_Represent eRepresentClass; + std::string szTitle; + std::string szDescription; } TABLE_HELP; typedef struct __TABLE_TEXTS { diff --git a/src/game/GameProcMain.cpp b/src/game/GameProcMain.cpp index e3236873..12f38015 100644 --- a/src/game/GameProcMain.cpp +++ b/src/game/GameProcMain.cpp @@ -4595,7 +4595,7 @@ bool CGameProcMain::CommandToggleUILevelGuide() { } s_pUIMgr->SetFocusedUI(m_pUILevelGuide); - m_pUILevelGuide->Open(); + m_pUILevelGuide->SetVisible(true); } else { m_pUILevelGuide->SetVisible(false); } diff --git a/src/game/UILevelGuide.cpp b/src/game/UILevelGuide.cpp index 6b651972..37dd88bb 100644 --- a/src/game/UILevelGuide.cpp +++ b/src/game/UILevelGuide.cpp @@ -1,172 +1,85 @@ #include "StdAfx.h" - #include "UILevelGuide.h" + +#include "Resource.h" +#include "GameProcMain.h" +#include "PlayerMySelf.h" +#include "UIManager.h" + #include "N3Base/N3UIString.h" #include "N3Base/N3UIScrollBar.h" #include "N3Base/N3UIEdit.h" -#include "PlayerMySelf.h" -#include "Resource.h" -#include "GameProcMain.h" + +const int MAX_SEARCH_ABOVE_LEVEL = 5; CUILevelGuide::CUILevelGuide() { - for (size_t i = 0; i < MAX_GUIDE_PAGE; ++i) { - m_pText_Titles[i] = NULL; - m_pText_Guides[i] = NULL; - m_pScroll_Guides[i] = NULL; - } - m_pBtn_Check = NULL; m_pEdit_Level = NULL; + + m_pBtn_Check = NULL; + m_pBtn_Cancel = NULL; + m_pBtn_Up = NULL; + m_pBtn_Down = NULL; + m_pText_Page = NULL; m_pText_Level = NULL; m_iCurrPage = 0; -} - -CUILevelGuide::~CUILevelGuide() {} - -void CUILevelGuide::LoadQuestData(int sLevel) { - m_iCurrPage = 1; - - int lvlMin = 0; - int pLevel = CGameBase::s_pPlayer->m_InfoBase.iLevel; - - m_pText_Level->SetStringAsInt(pLevel); - m_pText_Page->SetStringAsInt(1); - - if (sLevel - pLevel > MAX_SEARCH_ABOVE_PLAYER_LEVEL) { - m_pText_Level->SetStringAsInt(pLevel + MAX_SEARCH_ABOVE_PLAYER_LEVEL); - - char searchText[70]; - - std::string szMsg; - ::_LoadStringFromResource(IDS_QUEST_MENU_SEARCH_LEVEL_MAX_INFO, szMsg); - sprintf(searchText, szMsg.c_str(), MAX_SEARCH_ABOVE_PLAYER_LEVEL); - - CGameProcedure::MessageBoxPost(searchText, "", MB_OK, BEHAVIOR_NOTHING); - } - - int page = 1; - int questIndex = 0; - - for (int i = 1; i < CGameProcedure::s_pProcMain->s_pTbl_Help->GetSize(); i++) { - __TABLE_HELP * selectedQuest = CGameProcedure::s_pProcMain->s_pTbl_Help->Find(i); - if (sLevel >= selectedQuest->pLevelMin && isQuestIsAvailableForPlayer(selectedQuest->pClass)) { - - m_Quests[page][questIndex] = i; - - if (i % 3 == 0) { - page++; - questIndex = 0; - } else { - questIndex++; - } - } - } - - m_iMaxPage = page; - - for (int i = 0; i < 3; i++) { - __TABLE_HELP * questObj = CGameProcedure::s_pProcMain->s_pTbl_Help->Find(m_Quests[1][i]); - - m_pText_Titles[i]->SetString(questObj->qTitle); - m_pText_Guides[i]->SetString(questObj->qDesc); - - int maxLineCount = m_pText_Guides[i]->GetLineCount(); - - m_pScroll_Guides[i]->SetRange(0, maxLineCount); - m_pScroll_Guides[i]->SetCurrentPos(0); - } -} - -bool CUILevelGuide::isQuestIsAvailableForPlayer(int questRequiredClass) { - - int pClass = CGameBase::s_pPlayer->m_InfoBase.eClass; - - if (questRequiredClass == 100) { // for all - return true; - } - - if (questRequiredClass == 0 && - (pClass == CLASS_KA_WARRIOR || pClass == CLASS_KA_BERSERKER || pClass == CLASS_KA_GUARDIAN || - pClass == CLASS_EL_WARRIOR || pClass == CLASS_EL_BLADE || pClass == CLASS_EL_PROTECTOR)) { // warrior - return true; - } - - if (questRequiredClass == 1 && - (pClass == CLASS_KA_ROGUE || pClass == CLASS_KA_HUNTER || pClass == CLASS_KA_PENETRATOR || - pClass == CLASS_EL_ROGUE || pClass == CLASS_EL_RANGER || pClass == CLASS_EL_ASSASIN)) { // rouge - return true; - } - - if (questRequiredClass == 2 && - (pClass == CLASS_KA_WIZARD || pClass == CLASS_KA_SORCERER || pClass == CLASS_KA_NECROMANCER || - pClass == CLASS_EL_WIZARD || pClass == CLASS_EL_MAGE || pClass == CLASS_EL_ENCHANTER)) { // mage - return true; - } - - if (questRequiredClass == 3 && - (pClass == CLASS_KA_PRIEST || pClass == CLASS_KA_SHAMAN || pClass == CLASS_KA_DARKPRIEST || - pClass == CLASS_EL_PRIEST || pClass == CLASS_EL_CLERIC || pClass == CLASS_EL_DRUID)) { // priest - return true; + for (size_t i = 0; i < MAX_QUESTS_PER_PAGE; ++i) { + m_pText_Titles[i] = NULL; + m_pText_Guides[i] = NULL; + m_pScroll_Guides[i] = NULL; } - - return false; } -void CUILevelGuide::Open() { - m_iCurrPage = 1; - SetVisible(true); - - LoadQuestData(CGameBase::s_pPlayer->m_InfoBase.iLevel); - - return; -} +CUILevelGuide::~CUILevelGuide() = default; bool CUILevelGuide::Load(HANDLE hFile) { if (!CN3UIBase::Load(hFile)) { return false; } - m_pBtn_Check = (CN3UIButton *)(this->GetChildByID("btn_check")); + m_pBtn_Check = (CN3UIButton *)GetChildByID("btn_check"); __ASSERT(m_pBtn_Check, "NULL UI Component!!"); - m_pBtn_Cancel = (CN3UIButton *)(this->GetChildByID("btn_cancel")); + m_pBtn_Cancel = (CN3UIButton *)GetChildByID("btn_cancel"); __ASSERT(m_pBtn_Cancel, "NULL UI Component!!"); - m_pBtn_Up = (CN3UIButton *)(this->GetChildByID("btn_up")); + m_pBtn_Up = (CN3UIButton *)GetChildByID("btn_up"); __ASSERT(m_pBtn_Up, "NULL UI Component!!"); - m_pBtn_Down = (CN3UIButton *)(this->GetChildByID("btn_down")); + m_pBtn_Down = (CN3UIButton *)GetChildByID("btn_down"); __ASSERT(m_pBtn_Down, "NULL UI Component!!"); - m_pEdit_Level = (CN3UIEdit *)(this->GetChildByID("edit_level")); + m_pEdit_Level = (CN3UIEdit *)GetChildByID("edit_level"); __ASSERT(m_pEdit_Level, "NULL UI Component!!"); - m_pText_Page = (CN3UIString *)(this->GetChildByID("text_page")); + m_pText_Page = (CN3UIString *)GetChildByID("text_page"); __ASSERT(m_pText_Page, "NULL UI Component!!"); - m_pText_Level = (CN3UIString *)(this->GetChildByID("text_level")); + m_pText_Level = (CN3UIString *)GetChildByID("text_level"); __ASSERT(m_pText_Level, "NULL UI Component!!"); - for (size_t i = 0; i < MAX_GUIDE_PAGE; ++i) { + for (size_t i = 0; i < MAX_QUESTS_PER_PAGE; ++i) { std::string indexStr = std::to_string(i); - m_pText_Titles[i] = (CN3UIString *)(this->GetChildByID("text_title" + indexStr)); + m_pText_Titles[i] = (CN3UIString *)GetChildByID("text_title" + indexStr); __ASSERT(m_pText_Titles[i], "NULL UI Component!!"); if (m_pText_Titles[i]) { m_pText_Titles[i]->SetString(""); } - m_pText_Guides[i] = (CN3UIString *)(this->GetChildByID("text_guide" + indexStr)); + m_pText_Guides[i] = (CN3UIString *)GetChildByID("text_guide" + indexStr); __ASSERT(m_pText_Guides[i], "NULL UI Component!!"); if (m_pText_Guides[i]) { m_pText_Guides[i]->SetString(""); } - m_pScroll_Guides[i] = (CN3UIScrollBar *)(this->GetChildByID("scroll_guide" + indexStr)); + m_pScroll_Guides[i] = (CN3UIScrollBar *)GetChildByID("scroll_guide" + indexStr); __ASSERT(m_pScroll_Guides[i], "NULL UI Component!!"); - m_pScroll_Guides[i]->SetRange(0, 0); + if (m_pScroll_Guides[i]) { + m_pScroll_Guides[i]->SetVisible(false); + } } if (m_pText_Page) { @@ -176,23 +89,6 @@ bool CUILevelGuide::Load(HANDLE hFile) { return true; } -void CUILevelGuide::ChangePage(int iIndex) { - __TABLE_HELP * questObj = NULL; - - m_pText_Page->SetStringAsInt(iIndex); - - for (int i = 0; i < 3; i++) { - questObj = CGameProcedure::s_pProcMain->s_pTbl_Help->Find(m_Quests[iIndex][i]); - m_pText_Titles[i]->SetString(questObj->qTitle); - m_pText_Guides[i]->SetString(questObj->qDesc); - - int maxLineCount = m_pText_Guides[i]->GetLineCount(); - - m_pScroll_Guides[i]->SetRange(0, maxLineCount); - m_pScroll_Guides[i]->SetCurrentPos(0); - } -} - bool CUILevelGuide::ReceiveMessage(CN3UIBase * pSender, DWORD dwMsg) { if (!pSender) { return false; @@ -200,33 +96,21 @@ bool CUILevelGuide::ReceiveMessage(CN3UIBase * pSender, DWORD dwMsg) { if (dwMsg == UIMSG_BUTTON_CLICK) { if (pSender == (CN3UIBase *)m_pBtn_Check) { - int checkLevel = std::stoi(m_pEdit_Level->GetString()); - LoadQuestData(checkLevel); + CheckAvailableQuests(); return true; } else if (pSender == (CN3UIBase *)m_pBtn_Cancel) { SetVisible(false); return true; } else if (pSender == (CN3UIBase *)m_pBtn_Up) { - - if (m_iCurrPage >= m_iMaxPage) { - return true; - } - ChangePage(++m_iCurrPage); - + ChangePage(m_iCurrPage + 1); return true; } else if (pSender == (CN3UIBase *)m_pBtn_Down) { - - if (m_iCurrPage <= 1) { - return true; - } - ChangePage(--m_iCurrPage); - + ChangePage(m_iCurrPage - 1); return true; } - } else if (dwMsg == UIMSG_SCROLLBAR_POS) { int iIndex = -1; - for (size_t i = 0; i < MAX_GUIDE_PAGE; ++i) { + for (size_t i = 0; i < MAX_QUESTS_PER_PAGE; ++i) { if (pSender == (CN3UIBase *)m_pScroll_Guides[i]) { iIndex = i; break; @@ -236,10 +120,140 @@ bool CUILevelGuide::ReceiveMessage(CN3UIBase * pSender, DWORD dwMsg) { return true; } - if (m_pText_Guides[iIndex]->GetString().length() > 0) { - m_pText_Guides[iIndex]->SetStartLine(m_pScroll_Guides[iIndex]->GetCurrentPos()); - } + m_pText_Guides[iIndex]->SetStartLine(m_pScroll_Guides[iIndex]->GetCurrentPos()); } return true; } + +void CUILevelGuide::SetVisible(bool bVisible) { + if (m_bVisible == bVisible) { + return; + } + + if (bVisible) { + UpdateQuestsByLevel(CGameBase::s_pPlayer->m_InfoBase.iLevel); + if (m_pEdit_Level) { + m_pEdit_Level->SetString(""); + m_pEdit_Level->SetFocus(); + } + } else { + if (m_pEdit_Level) { + m_pEdit_Level->SetString(""); + m_pEdit_Level->KillFocus(); + } + } + + CN3UIBase::SetVisible(bVisible); + if (bVisible) { + CGameProcedure::s_pUIMgr->SetVisible(this); + } else { + CGameProcedure::s_pUIMgr->ReFocusUI(); + } +} + +void CUILevelGuide::UpdateQuestsByLevel(int iLevel) { + if (iLevel >= 0 && CGameBase::s_pPlayer->m_InfoBase.iLevel + MAX_SEARCH_ABOVE_LEVEL >= iLevel) { + m_QuestList.clear(); + e_Class_Represent eRepClass = CGameBase::GetRepresentClass(CGameBase::s_pPlayer->m_InfoBase.eClass); + + size_t iQuestsCount = CGameBase::s_pTbl_Help->GetSize(); + if (iQuestsCount > 0) { + for (size_t i = 0; i < iQuestsCount; ++i) { + __TABLE_HELP * pQuest = CGameBase::s_pTbl_Help->Find(i); + if (!pQuest) { + continue; + } + + if (pQuest->eRepresentClass == CLASS_REPRESENT_GENERIC || pQuest->eRepresentClass == eRepClass) { + if (pQuest->iLevelMin == iLevel && pQuest->iLevelMax == iLevel) { + m_QuestList.push_front(pQuest); + } else if (pQuest->iLevelMin <= iLevel && pQuest->iLevelMax >= iLevel) { + m_QuestList.push_back(pQuest); + } + } + } + } + } + + if (m_pText_Level) { + m_pText_Level->SetStringAsInt(iLevel); + } + ChangePage(0); +} + +void CUILevelGuide::ChangePage(int iIndex) { + if (iIndex < 0) { + return; + } + + if (m_QuestList.size() <= 0 || iIndex * MAX_QUESTS_PER_PAGE < m_QuestList.size()) { + for (size_t i = 0; i < MAX_QUESTS_PER_PAGE; ++i) { + if (m_pText_Titles[i]) { + m_pText_Titles[i]->SetString(""); + } + if (m_pText_Guides[i]) { + m_pText_Guides[i]->SetString(""); + } + if (m_pScroll_Guides[i]) { + m_pScroll_Guides[i]->SetVisible(false); + } + } + } + + if (m_QuestList.size() > 0 && iIndex * MAX_QUESTS_PER_PAGE < m_QuestList.size()) { + auto itr = std::next(m_QuestList.begin(), iIndex * MAX_QUESTS_PER_PAGE); + for (size_t i = 0; i < MAX_QUESTS_PER_PAGE && itr != m_QuestList.end(); ++i, ++itr) { + __TABLE_HELP * pQuest = (*itr); + if (!pQuest) { + continue; + } + + if (m_pText_Titles[i]) { + m_pText_Titles[i]->SetString(pQuest->szTitle); + } + if (m_pText_Guides[i]) { + m_pText_Guides[i]->SetString(pQuest->szDescription); + if (m_pText_Guides[i]->GetLineCount() > m_pText_Guides[i]->GetStringRealWidthRect()) { + if (m_pScroll_Guides[i]) { + m_pScroll_Guides[i]->SetVisible(true); + int iScroll = m_pText_Guides[i]->GetLineCount() - m_pText_Guides[i]->GetStringRealWidthRect(); + if (iScroll < 0) { + iScroll = 0; + } + m_pScroll_Guides[i]->SetRange(0, iScroll); + m_pScroll_Guides[i]->SetCurrentPos(0); + } + } else if (m_pScroll_Guides[i]) { + m_pScroll_Guides[i]->SetVisible(false); + } + } + } + m_iCurrPage = iIndex; + if (m_pText_Page) { + m_pText_Page->SetStringAsInt(iIndex + 1); + } + } +} + +void CUILevelGuide::CheckAvailableQuests() { + int iLevelFilter = std::atol(m_pEdit_Level->GetString().c_str()); + if (iLevelFilter <= 0) { + return; + } + + if (CGameBase::s_pPlayer->m_InfoBase.iLevel + MAX_SEARCH_ABOVE_LEVEL < iLevelFilter) { + std::string szMsgFormat; + ::_LoadStringFromResource(IDS_LEVELGUIDE_SEARCH_WARNING, szMsgFormat); + + char szMsg[70]{}; + sprintf(szMsg, szMsgFormat.c_str(), MAX_SEARCH_ABOVE_LEVEL); + CGameProcedure::MessageBoxPost(szMsg, "", MB_OK, BEHAVIOR_NOTHING); + + iLevelFilter = CGameBase::s_pPlayer->m_InfoBase.iLevel + MAX_SEARCH_ABOVE_LEVEL; + } + + UpdateQuestsByLevel(iLevelFilter); + m_pEdit_Level->SetString(""); + m_pEdit_Level->SetFocus(); +} diff --git a/src/game/UILevelGuide.h b/src/game/UILevelGuide.h index 126d4a77..e730e94e 100644 --- a/src/game/UILevelGuide.h +++ b/src/game/UILevelGuide.h @@ -3,34 +3,37 @@ #include "N3Base/N3UIBase.h" #include -const int MAX_GUIDE_PAGE = 3; -const int MAX_SEARCH_ABOVE_PLAYER_LEVEL = 5; +const int MAX_QUESTS_PER_PAGE = 3; class CUILevelGuide : public CN3UIBase { public: CUILevelGuide(); - virtual ~CUILevelGuide(); + ~CUILevelGuide() override; - bool Load(HANDLE hFile); - bool ReceiveMessage(CN3UIBase * pSender, DWORD dwMsg); - bool isQuestIsAvailableForPlayer(int questRequiredClass); + bool Load(HANDLE hFile) override; + bool ReceiveMessage(CN3UIBase * pSender, DWORD dwMsg) override; + void SetVisible(bool bVisible) override; - void Open(); + void UpdateQuestsByLevel(int iLevel); void ChangePage(int iIndex); - void LoadQuestData(int sLevel = 0); + void CheckAvailableQuests(); public: - CN3UIEdit * m_pEdit_Level; - CN3UIButton * m_pBtn_Check; - CN3UIButton * m_pBtn_Cancel; - CN3UIButton * m_pBtn_Up; - CN3UIButton * m_pBtn_Down; - CN3UIString * m_pText_Titles[MAX_GUIDE_PAGE]; - CN3UIString * m_pText_Guides[MAX_GUIDE_PAGE]; - CN3UIString * m_pText_Page; - CN3UIString * m_pText_Level; - CN3UIScrollBar * m_pScroll_Guides[MAX_GUIDE_PAGE]; - int m_iCurrPage; - int m_iMaxPage; - int m_Quests[30][MAX_GUIDE_PAGE]; + CN3UIEdit * m_pEdit_Level; + + CN3UIButton * m_pBtn_Check; + CN3UIButton * m_pBtn_Cancel; + CN3UIButton * m_pBtn_Up; + CN3UIButton * m_pBtn_Down; + + CN3UIString * m_pText_Titles[MAX_QUESTS_PER_PAGE]; + CN3UIString * m_pText_Guides[MAX_QUESTS_PER_PAGE]; + CN3UIString * m_pText_Page; + CN3UIString * m_pText_Level; + + CN3UIScrollBar * m_pScroll_Guides[MAX_QUESTS_PER_PAGE]; + + std::list m_QuestList; + + int m_iCurrPage; }; diff --git a/src/game/res/Resource.h b/src/game/res/Resource.h index 2e514f51..6385c509 100644 --- a/src/game/res/Resource.h +++ b/src/game/res/Resource.h @@ -514,7 +514,7 @@ #define IDS_DEAD_REVIVAL_MESSAGE 6603 #define IDS_DEAD_LOW_LEVEL 6604 #define IDS_INVEN_WEIGHT 6605 -#define IDS_QUEST_MENU_SEARCH_LEVEL_MAX_INFO 10100 +#define IDS_LEVELGUIDE_SEARCH_WARNING 10100 #define IDS_NATIONSELECT_MSGBOX_SELECTION 10420 #define IDS_NATIONSELECT_DESCRIPTION_KA 10421 #define IDS_NATIONSELECT_DESCRIPTION_EL 10422