From 2be723aa9bc3dd533026bb2af8068c0642fb2904 Mon Sep 17 00:00:00 2001 From: Adrian Tracz Date: Fri, 17 May 2024 16:21:42 +0200 Subject: [PATCH 1/4] Implement in game command list --- src/engine/N3Base/N3UIList.cpp | 11 + src/engine/N3Base/N3UIList.h | 1 + src/game/GameDef.h | 1 + src/game/GameProcMain.cpp | 161 +++++++++++++-- src/game/GameProcMain.h | 6 +- src/game/KnightOnLine.vcxproj | 4 + src/game/KnightOnLine.vcxproj.filters | 12 ++ src/game/UICmdEdit.cpp | 76 +++++++ src/game/UICmdEdit.h | 26 +++ src/game/UICmdList.cpp | 283 ++++++++++++++++++++++++++ src/game/UICmdList.h | 60 ++++++ src/game/res/Resource.h | 179 +++++++++++----- src/game/res/Resource.rc | Bin 111684 -> 111820 bytes 13 files changed, 751 insertions(+), 69 deletions(-) create mode 100644 src/game/UICmdEdit.cpp create mode 100644 src/game/UICmdEdit.h create mode 100644 src/game/UICmdList.cpp create mode 100644 src/game/UICmdList.h diff --git a/src/engine/N3Base/N3UIList.cpp b/src/engine/N3Base/N3UIList.cpp index bc3f3005..11f3435e 100644 --- a/src/engine/N3Base/N3UIList.cpp +++ b/src/engine/N3Base/N3UIList.cpp @@ -195,6 +195,17 @@ bool CN3UIList::SetString(int iIndex, const std::string & szString) { return false; } +CN3UIString * CN3UIList::GetChildStrFromList(std::string str) { + for (std::list::iterator it = m_ListString.begin(); it != m_ListString.end(); ++it) { + CN3UIString * pUIString = (*it); + if (pUIString->GetString() == str) { + return pUIString; + } + } + + return NULL; +} + void CN3UIList::UpdateChildRegions() { RECT rc = this->GetRegion(); RECT rcThis = rc; diff --git a/src/engine/N3Base/N3UIList.h b/src/engine/N3Base/N3UIList.h index 6a9100b4..35918f8a 100644 --- a/src/engine/N3Base/N3UIList.h +++ b/src/engine/N3Base/N3UIList.h @@ -28,6 +28,7 @@ class CN3UIList : public CN3UIBase { D3DCOLOR FontColor() { return m_crFont; } BOOL FontIsBold() { return m_bFontBold; } BOOL FontIsItalic() { return m_bFontItalic; } + CN3UIString * GetChildStrFromList(std::string str); void SetFont(const std::string & szFontName, DWORD dwHeight, BOOL bBold, BOOL bItalic); void SetFontColor(D3DCOLOR color); diff --git a/src/game/GameDef.h b/src/game/GameDef.h index 92988c61..5976e907 100644 --- a/src/game/GameDef.h +++ b/src/game/GameDef.h @@ -26,6 +26,7 @@ enum eKeyMap { KM_TOGGLE_SKILL = DIK_K, KM_TOGGLE_STATE = DIK_U, KM_TOGGLE_MINIMAP = DIK_M, + KM_TOGGLE_COMMAND_LIST = DIK_H, KM_TOGGLE_HELP = DIK_F1, KM_CAMERA_CHANGE = DIK_F9, KM_DROPPED_ITEM_OPEN = DIK_F, diff --git a/src/game/GameProcMain.cpp b/src/game/GameProcMain.cpp index db35bc1d..67f4ce4c 100644 --- a/src/game/GameProcMain.cpp +++ b/src/game/GameProcMain.cpp @@ -24,6 +24,8 @@ #include "UIChat.h" #include "UIInventory.h" #include "UICmd.h" +#include "UICmdList.h" +#include "UICmdEdit.h" #include "UIVarious.h" #include "UIStateBar.h" #include "UITargetBar.h" @@ -80,17 +82,48 @@ enum e_ChatCmd { CMD_WHISPER, CMD_TOWN, - CMD_TRADE, CMD_EXIT, + CMD_GREETING, + CMD_GREETING2, + CMD_GREETING3, + CMD_PROVOKE, + CMD_PROVOKE2, + CMD_PROVOKE3, + CMD_GAME_SAVE, + CMD_RECOMMEND, + CMD_INDIVIDUAL_BATTLE, + CMDSIT_STAND, + CMD_WALK_RUN, + CMD_LOCATION, + + CMD_TRADE, + CMD_FORBIDTRADE, + CMD_PERMITTRADE, + CMD_MERCHANT, + CMD_PARTY, CMD_LEAVEPARTY, CMD_RECRUITPARTY, + CMD_SEEKING_PARTY, + CMD_FORBIDPARTY, + CMD_PERMITPARTY, + CMD_JOINCLAN, CMD_WITHDRAWCLAN, CMD_FIRECLAN, + CMD_COMMAND, + CMD_CLAN_WAR, + CMD_SURRENDER, CMD_APPOINTVICECHIEF, - CMD_GREETING, - CMD_EXCITE, + CMD_CLAN_CHAT, + CMD_CLAN_BATTLE, + + CMD_CONFEDERACY, + CMD_BAN_KNIGHTS, + CMD_QUIT_KNIGHTS, + CMD_BASE, + CMD_DECLARATION, + CMD_VISIBLE, CMD_INVISIBLE, CMD_CLEAN, @@ -103,7 +136,16 @@ enum e_ChatCmd { CMD_FORBIDCONNECT, CMD_FORBIDCHAT, CMD_PERMITCHAT, - CMD_GAME_SAVE, + CMD_NOTICEALL, + CMD_CUTOFF, + CMD_VIEW, + CMD_UNVIEW, + CMD_FORBIDUSER, + CMD_SUMMONUSER, + CMD_ATTACKDISABLE, + CMD_ATTACKENABLE, + CMD_PLC, + CMD_COUNT, CMD_UNKNOWN = 0xffffffff }; @@ -139,6 +181,8 @@ CGameProcMain::CGameProcMain() // r기본 생성자.. 각 변수의 역활은 m_pUIStateBarAndMiniMap = new CUIStateBar(); m_pUIVar = new CUIVarious(); m_pUICmd = new CUICmd(); + m_pUICmdList = new CUICmdListDlg(); + m_pUICmdEditDlg = new CUICmdEditDlg(); m_pUITargetBar = new CUITargetBar(); m_pUIHelp = new CUIHelp(); m_pUINotice = new CUINotice(); @@ -187,6 +231,8 @@ CGameProcMain::~CGameProcMain() { delete m_pUIStateBarAndMiniMap; delete m_pUIVar; delete m_pUICmd; + delete m_pUICmdList; + delete m_pUICmdEditDlg; delete m_pUITargetBar; delete m_pUIHelp; delete m_pUINotice; @@ -243,6 +289,8 @@ void CGameProcMain::ReleaseUIs() { m_pUIChatDlg->Release(); m_pUIMsgDlg->Release(); m_pUICmd->Release(); + m_pUICmdList->Release(); + m_pUICmdEditDlg->Release(); m_pUIVar->Release(); m_pUIStateBarAndMiniMap->Release(); m_pUITargetBar->Release(); @@ -277,9 +325,29 @@ void CGameProcMain::Init() { m_pLightMgr->Release(); s_pEng->SetDefaultLight(m_pLightMgr->Light(0), m_pLightMgr->Light(1), m_pLightMgr->Light(2)); - for (int i = IDS_CMD_WHISPER; i <= IDS_CMD_GAME_SAVE; i++) //명령어 로딩... - { - ::_LoadStringFromResource(i, s_szCmdMsg[i - IDS_CMD_WHISPER]); + int i = 0; + for (uint32_t resource = IDS_CMD_WHISPER; resource <= IDS_CMD_LOCATION; resource++) { + ::_LoadStringFromResource(resource, s_szCmdMsg[i++]); + } + + for (uint32_t resource = IDS_CMD_TRADE; resource <= IDS_CMD_MERCHANT; resource++) { + ::_LoadStringFromResource(resource, s_szCmdMsg[i++]); + } + + for (uint32_t resource = IDS_CMD_PARTY; resource <= IDS_CMD_PERMITPARTY; resource++) { + ::_LoadStringFromResource(resource, s_szCmdMsg[i++]); + } + + for (uint32_t resource = IDS_CMD_JOINCLAN; resource <= IDS_CMD_CLAN_BATTLE; resource++) { + ::_LoadStringFromResource(resource, s_szCmdMsg[i++]); + } + + for (uint32_t resource = IDS_CMD_CONFEDERACY; resource <= IDS_CMD_DECLARATION; resource++) { + ::_LoadStringFromResource(resource, s_szCmdMsg[i++]); + } + + for (uint32_t resource = IDS_CMD_VISIBLE; resource <= IDS_CMD_PLC; resource++) { + ::_LoadStringFromResource(resource, s_szCmdMsg[i++]); } s_SndMgr.ReleaseStreamObj(&(CGameProcedure::s_pSnd_BGM)); @@ -1307,6 +1375,10 @@ void CGameProcMain::ProcessLocalInput(DWORD dwMouseFlags) { } } + if (s_pLocalInput->IsKeyPress(KM_TOGGLE_COMMAND_LIST)) { + this->CommandToggleCmdList(); + } + if (s_pLocalInput->IsKeyPress(KM_TOGGLE_MINIMAP)) { this->CommandToggleUIMiniMap(); } @@ -3723,6 +3795,21 @@ void CGameProcMain::InitUI() { m_pUICmd->SetPos((iW - (rc.right - rc.left)) / 2, iH - (rc.bottom - rc.top)); m_pUICmd->SetStyle(UISTYLE_FOCUS_UNABLE | UISTYLE_HIDE_UNABLE); + m_pUICmdList->Init(s_pUIMgr); + m_pUICmdList->LoadFromFile(pTbl->szKaCmdList); + rc = m_pUICmdList->GetRegion(); + m_pUICmdList->SetPos(iW - (rc.right - rc.left), 10); + m_pUICmdList->SetVisible(false); + + m_pUICmdEditDlg->Init(s_pUIMgr); + m_pUICmdEditDlg->LoadFromFile(pTbl->szCmdEdit); + m_pUICmdEditDlg->SetVisibleWithNoSound(false); + rc = m_pUICmdEditDlg->GetRegion(); + iX = (iW - (rc.right - rc.left)) / 2; + iY = (iH - (rc.bottom - rc.top)) / 2; + m_pUICmdEditDlg->SetPos(iX, iY); + m_pUICmdEditDlg->SetStyle(UISTYLE_USER_MOVE_HIDE); + m_pUIChatDlg->Init(s_pUIMgr); //Manager 자식으로 리스트에 추가 m_pUIChatDlg->LoadFromFile(pTbl->szChat); rc = m_pUIChatDlg->GetRegion(); @@ -4640,6 +4727,42 @@ bool CGameProcMain::CommandToggleUIInventory() { return bNeedOpen; } +bool CGameProcMain::OpenCmdEdit(std::string msg) { + bool bNeedOpen = !(m_pUICmdEditDlg->IsVisible()); + + if (bNeedOpen) { + s_pUIMgr->SetFocusedUI(m_pUICmdEditDlg); + m_pUICmdEditDlg->Open(msg); + } + + return bNeedOpen; +} + +bool CGameProcMain::CommandToggleCmdList() { + bool bNeedOpen = !(m_pUICmdList->IsVisible()); + 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(); + } + + s_pUIMgr->SetFocusedUI(m_pUICmdList); + m_pUICmdList->Open(); + } else { + m_pUICmdList->Close(); + } + + return bNeedOpen; +} + bool CGameProcMain::CommandToggleUISkillTree() { bool bNeedOpen = !(m_pUISkillTreeDlg->IsVisible()); @@ -4906,9 +5029,17 @@ void CGameProcMain::MsgRecv_UserState(DataPack * pDataPack, int & iOffset) { } else if (N3_SP_STATE_CHANGE_ACTION == eSP) // 크기 변함 { if (1 == iState) { - pBPC->AnimationAdd(ANI_GREETING0, true); // 인사 + pBPC->AnimationAdd(ANI_GREETING0, true); + } else if (2 == iState) { + pBPC->AnimationAdd(ANI_GREETING1, true); + } else if (3 == iState) { + pBPC->AnimationAdd(ANI_GREETING2, true); } else if (11 == iState) { - pBPC->AnimationAdd(ANI_WAR_CRY1, true); // 도발 + pBPC->AnimationAdd(ANI_WAR_CRY0, true); + } else if (12 == iState) { + pBPC->AnimationAdd(ANI_WAR_CRY1, true); + } else if (13 == iState) { + pBPC->AnimationAdd(ANI_WAR_CRY2, true); } } } @@ -5649,15 +5780,19 @@ void CGameProcMain::ParseChattingCommand(const std::string & szCmd) { } } break; - case CMD_GREETING: { + case CMD_GREETING: + case CMD_GREETING2: + case CMD_GREETING3: { if (s_pPlayer->State() == PSA_BASIC && s_pPlayer->StateMove() == PSM_STOP) { - this->MsgSend_StateChange(N3_SP_STATE_CHANGE_ACTION, 1); + this->MsgSend_StateChange(N3_SP_STATE_CHANGE_ACTION, 1 + (eCmd - CMD_GREETING)); } } break; - case CMD_EXCITE: { + case CMD_PROVOKE: + case CMD_PROVOKE2: + case CMD_PROVOKE3: { if (s_pPlayer->State() == PSA_BASIC && s_pPlayer->StateMove() == PSM_STOP) { - this->MsgSend_StateChange(N3_SP_STATE_CHANGE_ACTION, 11); + this->MsgSend_StateChange(N3_SP_STATE_CHANGE_ACTION, 11 + (eCmd - CMD_PROVOKE)); } } break; diff --git a/src/game/GameProcMain.h b/src/game/GameProcMain.h index 1ca2d090..0b164909 100644 --- a/src/game/GameProcMain.h +++ b/src/game/GameProcMain.h @@ -27,7 +27,9 @@ class CGameProcMain : public CGameProcedure { class CUIMessageWnd * m_pUIMsgDlg; // 게임 메시지 출력 상자. class CUIStateBar * m_pUIStateBarAndMiniMap; // mp,hp,exp, minimap.... class CUICmd * m_pUICmd; // 왼쪽 하단의 명령버튼 창.. - class CUITargetBar * m_pUITargetBar; // 타겟 상태창.. + class CUICmdListDlg * m_pUICmdList; + class CUICmdEditDlg * m_pUICmdEditDlg; + class CUITargetBar * m_pUITargetBar; // 타겟 상태창.. class CUITransactionDlg * m_pUITransactionDlg; class CUIDroppedItemDlg * m_pUIDroppedItemDlg; class CSubProcPerTrade * m_pSubProcPerTrade; @@ -231,6 +233,8 @@ class CGameProcMain : public CGameProcedure { bool CommandToggleMoveContinous(); bool CommandToggleWalkRun(); bool CommandToggleUISkillTree(); + bool CommandToggleCmdList(); + bool OpenCmdEdit(std::string msg); bool CommandToggleUIMiniMap(); bool CommandToggleUINotice(); bool CommandToggleUILevelGuide(); diff --git a/src/game/KnightOnLine.vcxproj b/src/game/KnightOnLine.vcxproj index c981d51c..44ff4187 100644 --- a/src/game/KnightOnLine.vcxproj +++ b/src/game/KnightOnLine.vcxproj @@ -273,6 +273,8 @@ + + @@ -461,6 +463,8 @@ + + diff --git a/src/game/KnightOnLine.vcxproj.filters b/src/game/KnightOnLine.vcxproj.filters index cba47d86..af99826c 100644 --- a/src/game/KnightOnLine.vcxproj.filters +++ b/src/game/KnightOnLine.vcxproj.filters @@ -646,6 +646,12 @@ N3Base\Core + + Procedure - Main\UI + + + Procedure - Main\UI + @@ -1163,6 +1169,12 @@ Procedure - Main\UI + + Procedure - Main\UI + + + Procedure - Main\UI + diff --git a/src/game/UICmdEdit.cpp b/src/game/UICmdEdit.cpp new file mode 100644 index 00000000..338fe0b5 --- /dev/null +++ b/src/game/UICmdEdit.cpp @@ -0,0 +1,76 @@ +// UICmdEditDlg.cpp: implementation of the CUICmdEditDlg class. +// +////////////////////////////////////////////////////////////////////// +#include "StdAfx.h"; +#include "resource.h" +#include "UICmdEdit.h" + +#include "GameProcMain.h" +#include "GameProcedure.h" +#include "PacketDef.h" +#include "APISocket.h" + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +CUICmdEditDlg::CUICmdEditDlg() {} + +CUICmdEditDlg::~CUICmdEditDlg() {} + +bool CUICmdEditDlg::Load(HANDLE hFile) { + if (CN3UIBase::Load(hFile) == false) { + return false; + } + + m_pText_Title = (CN3UIString *)GetChildByID("Text_cmd"); + __ASSERT(m_pText_Title, "NULL UI Component!!"); + m_pBtn_Ok = (CN3UIButton *)GetChildByID("btn_ok"); + __ASSERT(m_pBtn_Ok, "NULL UI Component!!"); + m_pBtn_Cancel = (CN3UIButton *)GetChildByID("btn_cancel"); + __ASSERT(m_pBtn_Cancel, "NULL UI Component!!"); + m_pEdit_Box = (CN3UIEdit *)GetChildByID("edit_cmd"); + __ASSERT(m_pEdit_Box, "NULL UI Component!!"); + return true; +} + +bool CUICmdEditDlg::ReceiveMessage(CN3UIBase * pSender, DWORD dwMsg) { + if (dwMsg == UIMSG_BUTTON_CLICK) { + if (pSender->m_szID == "btn_ok") { + m_szArg1 = m_pEdit_Box->GetString(); + std::string tempCmdStr = "/" + m_pText_Title->GetString() + " " + m_szArg1; + CGameProcedure::s_pProcMain->ParseChattingCommand(tempCmdStr); + + SetVisible(false); + return true; + } + + if (pSender->m_szID == "btn_cancel") { + SetVisible(false); + return true; + } + } + return true; +} + +void CUICmdEditDlg::Open(std::string msg) { + if (!msg.empty()) { + //m_pText_Title->SetString(msg); + m_pEdit_Box->SetString(""); + } + + m_pEdit_Box->SetFocus(); + SetVisible(true); +} + +void CUICmdEditDlg::SetVisible(bool bVisible) { + if (bVisible == this->IsVisible()) { + return; + } + + if (!bVisible) { + m_pEdit_Box->KillFocus(); + } + + CN3UIBase::SetVisible(bVisible); +} diff --git a/src/game/UICmdEdit.h b/src/game/UICmdEdit.h new file mode 100644 index 00000000..a57feb45 --- /dev/null +++ b/src/game/UICmdEdit.h @@ -0,0 +1,26 @@ +#pragma once +#include "GameDef.h" +#include "N3Base/N3UIBase.h" +#include "N3Base/N3UIString.h" +#include "N3Base/N3UIEdit.h" + +////////////////////////////////////////////////////////////////////// + +class CUICmdEditDlg : public CN3UIBase { + public: + CN3UIString * m_pText_Title; + CN3UIButton * m_pBtn_Ok; + CN3UIButton * m_pBtn_Cancel; + CN3UIEdit * m_pEdit_Box; + std::string m_szArg1; + + public: + void SetVisible(bool bVisible); + void Open(std::string msg); + + bool Load(HANDLE hFile); + bool ReceiveMessage(CN3UIBase * pSender, DWORD dwMsg); + + CUICmdEditDlg(); + virtual ~CUICmdEditDlg(); +}; diff --git a/src/game/UICmdList.cpp b/src/game/UICmdList.cpp new file mode 100644 index 00000000..77e7f849 --- /dev/null +++ b/src/game/UICmdList.cpp @@ -0,0 +1,283 @@ +// UICmdListDlg.cpp: implementation of the CUICmdListDlg class. +// +////////////////////////////////////////////////////////////////////// + +#include "StdAfx.h" + +#include "LocalInput.h" +#include "Resource.h" +#include "UICmdList.h" + +#include "GameProcedure.h" +#include "GameProcMain.h" +#include "UIHotKeyDlg.h" +#include "UIManager.h" + +#include "N3Base/N3UIArea.h" +#include "N3Base/N3UIString.h" +#include "N3Base/N3UIScrollBar.h" +#include "N3Base/N3SndObj.h" + +#include "APISocket.h" +#include "PacketDef.h" +#include "PlayerMySelf.h" +#include "UIManager.h" + +#include "N3UIDBCLButton.h" + +#include "GameDef.h" + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +CUICmdListDlg::CUICmdListDlg() { + m_bOpenningNow = false; + m_bClosingNow = false; + m_fMoveDelta = 0.0f; + + m_pBtn_cancel = NULL; + m_pList_CmdCat = NULL; + m_pList_Cmds = NULL; + m_pUICmdEdit = NULL; + m_pScroll_Categories = NULL; + m_pScroll_Commands = NULL; +} + +CUICmdListDlg::~CUICmdListDlg() { + Release(); +} + +bool CUICmdListDlg::Load(HANDLE hFile) { + if (CN3UIBase::Load(hFile) == false) { + return false; + } + + m_pBtn_cancel = (CN3UIButton *)this->GetChildByID("btn_cancel"); + __ASSERT(m_pBtn_cancel, "NULL UI Component!!!"); + m_pList_CmdCat = (CN3UIList *)this->GetChildByID("list_curtailment"); + __ASSERT(m_pList_CmdCat, "NULL UI Component!!!"); + m_pList_Cmds = (CN3UIList *)this->GetChildByID("list_content"); + __ASSERT(m_pList_Cmds, "NULL UI Component!!!"); + + //CN3UIArea + // CN3UIBase * pChild = m_pArea_Destroy->GetChildByIndex(i); + /* + m_pScroll_Categories = (CN3UIList *)m_pList_CmdCat->GetChildByIndex(0); + __ASSERT(m_pScroll_Categories, "NULL UI Component!!"); + m_pScroll_Categories->SetVisible(true); + + m_pScroll_Commands = (CN3UIScrollBar *)m_pList_Cmds->GetChildByIndex(0); + __ASSERT(m_pScroll_Categories, "NULL UI Component!!"); + m_pScroll_Commands->SetVisible(true); + + */ + + CreateCategoryList(); + + return true; +} + +void CUICmdListDlg::Release() { + CN3UIBase::Release(); +} + +void CUICmdListDlg::Open() { + SetVisible(true); + this->SetPos(CN3Base::s_CameraData.vp.Width, 10); + m_fMoveDelta = 0; + m_bOpenningNow = true; + m_bClosingNow = false; + + m_iRBtnDownOffs = -1; +} +void CUICmdListDlg::Close(bool bByKey) { + SetVisible(false); + m_fMoveDelta = 0; + m_bOpenningNow = false; + m_bClosingNow = true; +} + +void CUICmdListDlg::Tick() { + if (m_bOpenningNow) { + POINT ptCur = this->GetPos(); + RECT rc = this->GetRegion(); + float fWidth = (float)(rc.right - rc.left); + + float fDelta = 5000.0f * CN3Base::s_fSecPerFrm; + fDelta *= (fWidth - m_fMoveDelta) / fWidth; + if (fDelta < 2.0f) { + fDelta = 2.0f; + } + m_fMoveDelta += fDelta; + + int iXLimit = CN3Base::s_CameraData.vp.Width - (int)fWidth; + ptCur.x = CN3Base::s_CameraData.vp.Width - (int)m_fMoveDelta; + if (ptCur.x <= iXLimit) { + ptCur.x = iXLimit; + m_bOpenningNow = false; + } + + this->SetPos(ptCur.x, ptCur.y); + } else if (m_bClosingNow) { + POINT ptCur = this->GetPos(); + RECT rc = this->GetRegion(); + float fWidth = (float)(rc.right - rc.left); + + float fDelta = 5000.0f * CN3Base::s_fSecPerFrm; + fDelta *= (fWidth - m_fMoveDelta) / fWidth; + if (fDelta < 2.0f) { + fDelta = 2.0f; + } + m_fMoveDelta += fDelta; + + int iXLimit = CN3Base::s_CameraData.vp.Width; + ptCur.x = CN3Base::s_CameraData.vp.Width - (int)(fWidth - m_fMoveDelta); + if (ptCur.x >= iXLimit) { + ptCur.x = iXLimit; + m_bClosingNow = false; + + this->SetVisibleWithNoSound(false, false, true); + } + + this->SetPos(ptCur.x, ptCur.y); + } + + CN3UIBase::Tick(); +} + +bool CUICmdListDlg::CreateCategoryList() { + if (m_pList_CmdCat == NULL || m_pList_Cmds == NULL) { + return false; + } + + std::string szCategory; + int idStart = IDS_PRIVATE_CMD_CAT; + + for (int i = 0; i < 8; i++) { + ::_LoadStringFromResource(i + 7800, szCategory); //load command categories + + if (CGameBase::s_pPlayer->m_InfoBase.iAuthority == 0 && szCategory == "GM") { // if not gm hide this category + continue; + } + + m_pList_CmdCat->AddString(szCategory); + idStart++; + } + + m_pList_CmdCat->SetFontColor(0xffffff00); //green + + int idCur = 8000; //Command list strings start at this index + int idEnd = 9600; //Command list strings end at this index + + std::string szCommand; + //create map of commands + for (int i = idCur; idCur < idEnd; idCur++, i++) { + if (idCur == 9000) { + i += 400; // offset and put gm cmds at end of map + } else if (idCur == 9100) { + i -= 500; + idCur = 9200; + } + szCommand.clear(); + ::_LoadStringFromResource(idCur, szCommand); + if (!szCommand.empty() && (i / 100) % 2 == 0) { + m_mapCmds[i] = szCommand; + } + } + + UpdateCommandList(CMD_LIST_PRIVATE); //initialize a cmd list for viewing when opening cmd window + + return true; +} +bool CUICmdListDlg::UpdateCommandList(uint8_t cmdCat) { + if (m_pList_Cmds == NULL) { + return false; + } + + m_pList_Cmds->ResetContent(); + + int indexStart = cmdCat * 200 + 8000; //start index for correct loc in map + int indexEnd = indexStart + 100; //where to stop iterating + int i = 0; + + for (auto itr = m_mapCmds.begin(); itr != m_mapCmds.end(); ++itr) { + if (itr->first >= indexStart && itr->first < indexEnd) { + m_pList_Cmds->AddString(itr->second); + + CN3UIString * pChild = m_pList_Cmds->GetChildStrFromList(itr->second); + std::string cmdTip; + ::_LoadStringFromResource(itr->first + 100, cmdTip); + if (pChild != NULL) { + pChild->SetTooltipText(cmdTip.c_str()); + } + //SavvyNik tooltip is being loaded in but the rectangle + //that it shows on is too small. Need to figure out where + //this is being set. + } + } + + return true; +} +bool CUICmdListDlg::ReceiveMessage(CN3UIBase * pSender, DWORD dwMsg) { + if (NULL == pSender) { + return false; + } + + if (dwMsg == UIMSG_BUTTON_CLICK) { + if (pSender == m_pBtn_cancel) { + SetVisible(false); + return true; + } + } else if (dwMsg == UIMSG_LIST_SELCHANGE) { + if (pSender == m_pList_CmdCat) { + uint8_t iSel = m_pList_CmdCat->GetCurSel(); + UpdateCommandList(iSel); + return true; + } + } else if (dwMsg == UIMSG_LIST_DBLCLK) { + if (pSender == m_pList_Cmds) { + uint8_t iSel = m_pList_Cmds->GetCurSel(); + ExecuteCommand(iSel); + return true; + } + } + + return false; +} + +void CUICmdListDlg::Render() { + if (!m_bVisible) { + return; + } + + CN3UIBase::Render(); +} + +//this_ui_add_start +bool CUICmdListDlg::OnKeyPress(int iKey) { + return CN3UIBase::OnKeyPress(iKey); +} + +void CUICmdListDlg::SetVisible(bool bVisible) { + CN3UIBase::SetVisible(bVisible); + if (bVisible) { + CGameProcedure::s_pUIMgr->SetVisibleFocusedUI(this); + } else { + CGameProcedure::s_pUIMgr->ReFocusUI(); //this_ui + } +} + +bool CUICmdListDlg::ExecuteCommand(uint8_t cmdSel) { + std::string command; + m_pList_Cmds->GetString(cmdSel, command); + + if (command == "PM") { + CGameProcedure::s_pProcMain->OpenCmdEdit(command); + } + + command = '/' + command; + CGameProcedure::s_pProcMain->ParseChattingCommand(command); + + return true; +} \ No newline at end of file diff --git a/src/game/UICmdList.h b/src/game/UICmdList.h new file mode 100644 index 00000000..627378ab --- /dev/null +++ b/src/game/UICmdList.h @@ -0,0 +1,60 @@ +// UICmdListDlg.h: interface for the CUICmdListDlg class. +// +////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "N3Base/N3UIBase.h" +#include "N3Base/N3UIButton.h" +#include "N3Base/N3UIList.h" +#include "N3Base/N3UIEdit.h" + +////////////////////////////////////////////////////////////////////// + +class CUICmdListDlg : public CN3UIBase { + bool m_bDestoyDlgAlive; + class CUICmdEdit * m_pUICmdEdit; + CN3UIButton * m_pBtn_cancel; + CN3UIList * m_pList_CmdCat; + CN3UIList * m_pList_Cmds; + CN3UIScrollBar * m_pScroll_Categories; + CN3UIScrollBar * m_pScroll_Commands; + + protected: + bool m_bOpenningNow; + bool m_bClosingNow; + float m_fMoveDelta; + int m_iRBtnDownOffs; + bool m_bRBtnProcessing; + + enum iCmd { + CMD_LIST_PRIVATE, + CMD_LIST_TRADE, + CMD_LIST_PARTY, + CMD_LIST_CLAN, + CMD_LIST_KNIGHTS, + CMD_LIST_GUARDIAN, + CMD_LIST_KING, + CMD_LIST_GM + }; + + std::map m_mapCmds; + + public: + void SetVisible(bool bVisible); + + bool OnKeyPress(int iKey); + virtual void Release(); + virtual void Tick(); + virtual bool ReceiveMessage(CN3UIBase * pSender, DWORD dwMsg); + void Render(); + void Open(); + void Close(bool bByKey = false); + bool Load(HANDLE hFile); + bool CreateCategoryList(); + bool UpdateCommandList(uint8_t cmd); + bool ExecuteCommand(uint8_t cmdSel); + + CUICmdListDlg(); + virtual ~CUICmdListDlg(); +}; diff --git a/src/game/res/Resource.h b/src/game/res/Resource.h index 3706c35a..b71172fd 100644 --- a/src/game/res/Resource.h +++ b/src/game/res/Resource.h @@ -442,6 +442,7 @@ #define IDS_WANT_PARTY_MEMBER 6123 #define IDS_SETTING_KARUS_SCREEN 6124 #define IDS_SETTING_ELMORAD_SCREEN 6125 +/* #define IDS_CMD_WHISPER 6200 #define IDS_CMD_TOWN 6201 #define IDS_CMD_TRADE 6202 @@ -468,61 +469,129 @@ #define IDS_CMD_FORBIDCHAT 6223 #define IDS_CMD_PERMITCHAT 6224 #define IDS_CMD_GAME_SAVE 6225 -#define IDS_PARTY_BBS_REGISTER 6300 -#define IDS_PARTY_BBS_REGISTER_CANCEL 6301 -#define IDS_TRADE_BBS_SELL_REGISTER 6302 -#define IDS_TRADE_BBS_PER_TRADE 6303 -#define IDS_TRADE_BBS_BUY_REGISTER 6304 -#define IDS_TRADE_BBS_FAIL1 6305 -#define IDS_TRADE_BBS_FAIL2 6306 -#define IDS_TRADE_BBS_FAIL3 6307 -#define IDS_TRADE_BBS_FAIL4 6308 -#define IDS_TRADE_BBS_FAIL5 6309 -#define IDS_TRADE_BBS_FAIL6 6310 -#define IDS_OTHER_PER_TRADE_ID_NO 6311 -#define IDS_CLAN_DENY_LOWLEVEL 6500 -#define IDS_CLAN_DENY_LOWGOLD 6501 -#define IDS_CLAN_DENY_INVALIDDAY 6502 -#define IDS_CLAN_DENY_ALREADYJOINED 6503 -#define IDS_CLAN_DENY_UNKNOWN 6504 -#define IDS_CLAN_MAKE_SUCCESS 6505 -#define IDS_CLAN_WARNING_COST 6506 -#define IDS_CLAN_INPUT_NAME 6507 -#define IDS_CLAN_REINPUT_NAME 6508 -#define IDS_CLAN_WITHDRAW_SUCCESS 6509 -#define IDS_CLAN_WITHDRAW_FAIL 6510 -#define IDS_CLAN_JOIN_SUCCESS 6511 -#define IDS_CLAN_JOIN_FAIL_CLAN_FULL 6512 -#define IDS_CLAN_JOIN_FAIL_NONE_CLAN 6513 -#define IDS_CLAN_JOIN_FAIL_INVALIDRIGHT 6514 -#define IDS_CLAN_JOIN_FAIL_OTHER_CLAN_USER 6515 -#define IDS_CLAN_JOIN_FAIL_ENEMY_USER 6516 -#define IDS_CLAN_JOIN_FAIL_DEAD_USER 6517 -#define IDS_CLAN_JOIN_FAIL_NONE_USER 6518 -#define IDS_CLAN_COMMON_FAIL_ME 6519 -#define IDS_CLAN_COMMON_FAIL_NOTJOINED 6520 -#define IDS_CLAN_JOIN_REQ 6521 -#define IDS_CLAN_JOIN_REJECT 6522 -#define IDS_CLAN_COMMON_FAIL_BATTLEZONE 6523 -#define IDS_CONFIRM_EXECUTE_OPTION 6524 -#define IDS_REQUEST_GAME_SAVE 6525 -#define IDS_DELAY_GAME_SAVE 6526 -#define IDS_CLAN_DENY_INVALID_SERVER 6527 -#define IDS_DEAD_RETURN_TOWN 6600 -#define IDS_DEAD_REVIVAL 6601 -#define IDS_DEAD_LACK_LIFE_STONE 6602 -#define IDS_DEAD_REVIVAL_MESSAGE 6603 -#define IDS_DEAD_LOW_LEVEL 6604 -#define IDS_INVEN_WEIGHT 6605 -#define IDS_WARP_ARRIVED 6606 -#define IDS_WARP_REQUIRED_COINS 7612 -#define IDS_EXIT_GAME_IN 7632 -#define IDS_EXIT_GAME_CANCELED 7633 -#define IDS_EXIT_GAME_DURING_BATTLE_WARNING 7634 -#define IDS_LEVELGUIDE_SEARCH_WARNING 10100 -#define IDS_NATIONSELECT_MSGBOX_SELECTION 10420 -#define IDS_NATIONSELECT_DESCRIPTION_KA 10421 -#define IDS_NATIONSELECT_DESCRIPTION_EL 10422 +*/ +#define IDS_CMD_WHISPER 8000 +#define IDS_CMD_TOWN 8001 +#define IDS_CMD_EXIT 8002 +#define IDS_CMD_GREETING 8003 +#define IDS_CMD_GREETING2 8004 +#define IDS_CMD_GREETING3 8005 +#define IDS_CMD_PROVOKE 8006 +#define IDS_CMD_PROVOKE2 8007 +#define IDS_CMD_PROVOKE3 8008 +#define IDS_CMD_GAME_SAVE 8009 +#define IDS_CMD_RECOMMEND 8010 +#define IDS_CMD_INDIVIDUAL_BATTLE 8011 +#define IDS_CMD_SIT_STAND 8012 +#define IDS_CMD_WALK_RUN 8013 +#define IDS_CMD_LOCATION 8014 + +#define IDS_CMD_TRADE 8200 +#define IDS_CMD_FORBIDTRADE 8201 +#define IDS_CMD_PERMITTRADE 8202 +#define IDS_CMD_MERCHANT 8203 + +#define IDS_CMD_PARTY 8400 +#define IDS_CMD_LEAVEPARTY 8401 +#define IDS_CMD_RECRUITPARTY 8402 +#define IDS_CMD_SEEKING_PARTY 8402 +#define IDS_CMD_FORBIDPARTY 8403 +#define IDS_CMD_PERMITPARTY 8404 + +#define IDS_CMD_JOINCLAN 8600 +#define IDS_CMD_WITHDRAWCLAN 8601 +#define IDS_CMD_FIRECLAN 8602 +#define IDS_CMD_COMMAND 8603 +#define IDS_CMD_CLAN_WAR 8604 +#define IDS_CMD_SURRENDER 8605 +#define IDS_CMD_APPOINTVICECHIEF 8606 +#define IDS_CMD_CLAN_CHAT 8607 +#define IDS_CMD_CLAN_BATTLE 8608 + +#define IDS_CMD_CONFEDERACY 8800 +#define IDS_CMD_BAN_KNIGHTS 8801 +#define IDS_CMD_QUIT_KNIGHTS 8802 +#define IDS_CMD_BASE 8803 +#define IDS_CMD_DECLARATION 8804 + +#define IDS_CMD_VISIBLE 9000 +#define IDS_CMD_INVISIBLE 9001 +#define IDS_CMD_CLEAN 9002 +#define IDS_CMD_RAINING 9003 +#define IDS_CMD_SNOWING 9004 +#define IDS_CMD_TIME 9005 +#define IDS_CMD_CU_COUNT 9006 +#define IDS_CMD_NOTICE 9007 +#define IDS_CMD_ARREST 9008 +#define IDS_CMD_FORBIDCONNECT 9009 +#define IDS_CMD_FORBIDCHAT 9010 +#define IDS_CMD_PERMITCHAT 9011 +#define IDS_CMD_NOTICEALL 9012 +#define IDS_CMD_CUTOFF 9013 +#define IDS_CMD_VIEW 9014 +#define IDS_CMD_UNVIEW 9015 +#define IDS_CMD_FORBIDUSER 9016 +#define IDS_CMD_SUMMONUSER 9017 +#define IDS_CMD_ATTACKDISABLE 9018 +#define IDS_CMD_ATTACKENABLE 9019 +#define IDS_CMD_PLC 9020 + +#define IDS_PARTY_BBS_REGISTER 6300 +#define IDS_PARTY_BBS_REGISTER_CANCEL 6301 +#define IDS_TRADE_BBS_SELL_REGISTER 6302 +#define IDS_TRADE_BBS_PER_TRADE 6303 +#define IDS_TRADE_BBS_BUY_REGISTER 6304 +#define IDS_TRADE_BBS_FAIL1 6305 +#define IDS_TRADE_BBS_FAIL2 6306 +#define IDS_TRADE_BBS_FAIL3 6307 +#define IDS_TRADE_BBS_FAIL4 6308 +#define IDS_TRADE_BBS_FAIL5 6309 +#define IDS_TRADE_BBS_FAIL6 6310 +#define IDS_OTHER_PER_TRADE_ID_NO 6311 +#define IDS_CLAN_DENY_LOWLEVEL 6500 +#define IDS_CLAN_DENY_LOWGOLD 6501 +#define IDS_CLAN_DENY_INVALIDDAY 6502 +#define IDS_CLAN_DENY_ALREADYJOINED 6503 +#define IDS_CLAN_DENY_UNKNOWN 6504 +#define IDS_CLAN_MAKE_SUCCESS 6505 +#define IDS_CLAN_WARNING_COST 6506 +#define IDS_CLAN_INPUT_NAME 6507 +#define IDS_CLAN_REINPUT_NAME 6508 +#define IDS_CLAN_WITHDRAW_SUCCESS 6509 +#define IDS_CLAN_WITHDRAW_FAIL 6510 +#define IDS_CLAN_JOIN_SUCCESS 6511 +#define IDS_CLAN_JOIN_FAIL_CLAN_FULL 6512 +#define IDS_CLAN_JOIN_FAIL_NONE_CLAN 6513 +#define IDS_CLAN_JOIN_FAIL_INVALIDRIGHT 6514 +#define IDS_CLAN_JOIN_FAIL_OTHER_CLAN_USER 6515 +#define IDS_CLAN_JOIN_FAIL_ENEMY_USER 6516 +#define IDS_CLAN_JOIN_FAIL_DEAD_USER 6517 +#define IDS_CLAN_JOIN_FAIL_NONE_USER 6518 +#define IDS_CLAN_COMMON_FAIL_ME 6519 +#define IDS_CLAN_COMMON_FAIL_NOTJOINED 6520 +#define IDS_CLAN_JOIN_REQ 6521 +#define IDS_CLAN_JOIN_REJECT 6522 +#define IDS_CLAN_COMMON_FAIL_BATTLEZONE 6523 +#define IDS_CONFIRM_EXECUTE_OPTION 6524 +#define IDS_REQUEST_GAME_SAVE 6525 +#define IDS_DELAY_GAME_SAVE 6526 +#define IDS_CLAN_DENY_INVALID_SERVER 6527 +#define IDS_DEAD_RETURN_TOWN 6600 +#define IDS_DEAD_REVIVAL 6601 +#define IDS_DEAD_LACK_LIFE_STONE 6602 +#define IDS_DEAD_REVIVAL_MESSAGE 6603 +#define IDS_DEAD_LOW_LEVEL 6604 +#define IDS_INVEN_WEIGHT 6605 +#define IDS_WARP_ARRIVED 6606 +#define IDS_WARP_REQUIRED_COINS 7612 +#define IDS_EXIT_GAME_IN 7632 +#define IDS_EXIT_GAME_CANCELED 7633 +#define IDS_EXIT_GAME_DURING_BATTLE_WARNING 7634 +#define IDS_PRIVATE_CMD_CAT 7800 +#define IDS_LEVELGUIDE_SEARCH_WARNING 10100 +#define IDS_NATIONSELECT_MSGBOX_SELECTION 10420 +#define IDS_NATIONSELECT_DESCRIPTION_KA 10421 +#define IDS_NATIONSELECT_DESCRIPTION_EL 10422 // Next default values for new objects // diff --git a/src/game/res/Resource.rc b/src/game/res/Resource.rc index 4aae3d5d205c49cfdb4ed47e0a98fbb2ecd55437..ece4328b1429bbbcd9e2863f5be7095be6d3b663 100644 GIT binary patch delta 62 zcmX@|g6+&pwhdhurpqj66ks%(Jo|znglW8a_Jxzzpu*F2mou6}#lh_D>y|T4;{gCP Cy%*B} delta 67 zcmX@}lI_R~whdhuSX~(+7@Q~n=M Date: Tue, 25 Jun 2024 19:59:30 +0200 Subject: [PATCH 2/4] Update command list with working tooltips, add N3UIList, N3UITooltip missing functions ![Screenshot](https://iili.io/d3T5Xn4.jpg) Thanks to @twostars and @stevewgr for asm code :) --- src/engine/N3Base/N3UIBase.h | 5 +- src/engine/N3Base/N3UIList.cpp | 92 ++++--- src/engine/N3Base/N3UIList.h | 8 +- src/engine/N3Base/N3UITooltip.cpp | 57 ++++ src/engine/N3Base/N3UITooltip.h | 9 +- src/game/GameProcMain.cpp | 432 ++++++++++++++++-------------- src/game/GameProcMain.h | 4 +- src/game/UICmd.cpp | 4 +- src/game/UICmdEdit.cpp | 16 +- src/game/UICmdEdit.h | 8 +- src/game/UICmdList.cpp | 363 +++++++++++++++++-------- src/game/UICmdList.h | 212 ++++++++++++--- src/game/res/Resource.h | 55 ++-- 13 files changed, 839 insertions(+), 426 deletions(-) diff --git a/src/engine/N3Base/N3UIBase.h b/src/engine/N3Base/N3UIBase.h index 31b7afaf..6d31e204 100644 --- a/src/engine/N3Base/N3UIBase.h +++ b/src/engine/N3Base/N3UIBase.h @@ -43,8 +43,9 @@ class CN3UIBase : public CN3BaseFileAccess { #endif public: - std::string m_szID; // UI id - std::string m_szToolTip; // tooltip text + std::string m_szID; // UI id + std::string m_szToolTip; // tooltip text + D3DCOLOR m_crToolTipColor; // tooltip text color void SetID(LPCTSTR pszID) { m_szID = pszID; } const std::string GetID() const { return m_szID; } void SetTooltipText(LPCTSTR pszTT) { m_szToolTip = pszTT; } diff --git a/src/engine/N3Base/N3UIList.cpp b/src/engine/N3Base/N3UIList.cpp index 11f3435e..0985b73a 100644 --- a/src/engine/N3Base/N3UIList.cpp +++ b/src/engine/N3Base/N3UIList.cpp @@ -6,6 +6,7 @@ #include "N3UIList.h" #include "N3UIString.h" #include "N3UIScrollBar.h" +#include "N3UITooltip.h" ////////////////////////////////////////////////////////////////////// // Construction/Destruction @@ -14,7 +15,7 @@ CN3UIList::CN3UIList() { m_eType = UI_TYPE_LIST; - m_iCurSel = 0; // 현재 선택.. + m_iCurSel = 0; // Current selection.. m_pScrollBarRef = NULL; m_szFontName = "굴림체"; @@ -35,7 +36,8 @@ void CN3UIList::Release() { // delete (*it); // } - m_ListString.clear(); // 어차피 자식은 다지우니까... 리스트의 포인터를 Delete 할 필요 없다.. + // Since all the children will be deleted anyway... there is no need to delete the pointer to the list.. + m_ListString.clear(); m_iCurSel = 0; m_pScrollBarRef = NULL; @@ -46,6 +48,13 @@ void CN3UIList::Release() { m_crFont = 0xffffffff; } +void CN3UIList::SetScrollBarRef(CN3UIScrollBar * pScrollBarRef) { + m_pScrollBarRef = pScrollBarRef; + if (m_pScrollBarRef) { + m_pScrollBarRef->SetCurrentPos(0); + } +} + void CN3UIList::SetFont(const std::string & szFontName, DWORD dwHeight, BOOL bBold, BOOL bItalic) { m_szFontName = szFontName; m_dwFontHeight = dwHeight; @@ -96,6 +105,23 @@ int CN3UIList::AddStrings(const std::string * pszStrings, int iStringCount) { return m_ListString.size() - 1; } +int CN3UIList::AddStringTooltip(const std::string & szString, const D3DCOLOR szStringColor, + const std::string & szStringToolTip, const D3DCOLOR szStringToolTipColor) { + CN3UIString * pString = new CN3UIString(); + pString->Init(this); + pString->SetFont(m_szFontName, m_dwFontHeight, m_bFontBold, m_bFontItalic); + pString->SetColor(szStringColor); + pString->SetString(szString); + + pString->SetTooltipText(szStringToolTip.c_str()); + pString->m_crToolTipColor = szStringToolTipColor; + + m_ListString.push_back(pString); + this->UpdateChildRegions(); + + return m_ListString.size() - 1; +} + int CN3UIList::AddString(const std::string & szString) { CN3UIString * pString = new CN3UIString(); pString->Init(this); @@ -137,11 +163,9 @@ bool CN3UIList::DeleteString(int iIndex) { } it_pString it = m_ListString.begin(); - for (int i = 0; i < iIndex; it++) { - ; - } + std::advance(it, iIndex); - delete (*it); + delete *it; m_ListString.erase(it); int iSC = m_ListString.size(); @@ -195,11 +219,10 @@ bool CN3UIList::SetString(int iIndex, const std::string & szString) { return false; } -CN3UIString * CN3UIList::GetChildStrFromList(std::string str) { - for (std::list::iterator it = m_ListString.begin(); it != m_ListString.end(); ++it) { - CN3UIString * pUIString = (*it); - if (pUIString->GetString() == str) { - return pUIString; +CN3UIString * CN3UIList::GetChildStrFromList(const std::string str) { + for (CN3UIString * pString : m_ListString) { + if (pString->GetString() == str) { + return pString; } } @@ -213,7 +236,7 @@ void CN3UIList::UpdateChildRegions() { SIZE size; int iScrollPos = 0; if (m_pScrollBarRef) { - m_pScrollBarRef->GetCurrentPos(); + iScrollPos = m_pScrollBarRef->GetCurrentPos(); RECT rcTmp = m_pScrollBarRef->GetRegion(); rc.right = rcTmp.left; } @@ -241,14 +264,13 @@ void CN3UIList::UpdateChildRegions() { } if (m_pScrollBarRef) { - if (rc.bottom <= rcThis.bottom) { - m_pScrollBarRef->SetCurrentPos(0); - m_pScrollBarRef->SetVisibleWithNoSound(false); + if (rc.top <= rcThis.bottom) { + //m_pScrollBarRef->SetCurrentPos(0); + //m_pScrollBarRef->SetVisibleWithNoSound(false); } else { m_pScrollBarRef->SetVisibleWithNoSound(true); } - - m_pScrollBarRef->SetRange(0, m_ListString.size()); + //m_pScrollBarRef->SetRange(0, m_ListString.size()); } } @@ -273,10 +295,10 @@ bool CN3UIList::SetScrollPos(int iScrollPos) { bool CN3UIList::Load(HANDLE hFile) { bool bSuccess = CN3UIBase::Load(hFile); - // font 정보 + // font information DWORD dwNum; int iStrLen = 0; - ReadFile(hFile, &iStrLen, sizeof(iStrLen), &dwNum, NULL); // font 이름 길이 + ReadFile(hFile, &iStrLen, sizeof(iStrLen), &dwNum, NULL); // font name length __ASSERT(iStrLen > 0, "No font name"); if (iStrLen > 0) { m_szFontName.assign(iStrLen, ' '); @@ -287,7 +309,7 @@ bool CN3UIList::Load(HANDLE hFile) { ReadFile(hFile, &m_bFontItalic, 4, &dwNum, NULL); // font flag (bold, italic) } - // Child 중에 Scroll Bar 가 있는지 찾아본다. + // Check if any of the children have a scroll bar. for (UIListItor itor = m_Children.begin(); m_Children.end() != itor; ++itor) { CN3UIBase * pUI = *itor; if (pUI->UIType() == UI_TYPE_SCROLLBAR) { @@ -299,7 +321,7 @@ bool CN3UIList::Load(HANDLE hFile) { // if( pString->GetFontName != m_szFontName || // pString->GetFontHeight() != m_dwFontHeight || // m_bFontBold != (pString->GetFontFlags() & D3DFONT_BOLD) || - // m_bFontItalic != (pString->GetFontFlags() & D3DFONT_ITALIC) ) // 폰트가 다르면.. 적용 + // m_bFontItalic != (pString->GetFontFlags() & D3DFONT_ITALIC) ) // If the font is different.. apply // { // pString->SetFont(m_szFontName, m_dwFontHeight, m_bFontBold, m_bFontItalic); // } @@ -317,10 +339,10 @@ bool CN3UIList::Save(HANDLE hFile) { DWORD dwNum; - // font 정보 + // font information int iStrLen = m_szFontName.size(); __ASSERT(iStrLen > 0, "No font name"); - WriteFile(hFile, &iStrLen, sizeof(iStrLen), &dwNum, NULL); // font 이름 길이 + WriteFile(hFile, &iStrLen, sizeof(iStrLen), &dwNum, NULL); // font name length if (iStrLen > 0) { WriteFile(hFile, m_szFontName.c_str(), iStrLen, &dwNum, NULL); // string WriteFile(hFile, &m_dwFontHeight, 4, &dwNum, NULL); // font height @@ -352,14 +374,14 @@ DWORD CN3UIList::MouseProc(DWORD dwFlags, const POINT & ptCur, const POINT & ptO } // 특정 이벤트에 대해 메시지 전송.. - if (IsIn(ptCur.x, ptCur.y) && ((dwFlags & UI_MOUSE_LBCLICK) || (dwFlags & UI_MOUSE_LBDBLCLK))) { + if (IsIn(ptCur.x, ptCur.y)) { RECT rc = this->GetRegion(), rcStr; SIZE size; it_pString it = m_ListString.begin(), itEnd = m_ListString.end(); for (int i = 0; it != itEnd; it++, i++) { CN3UIString * pStr = (*it); - if (false == pStr->IsVisible()) { + if (!pStr->IsVisible()) { continue; } @@ -370,20 +392,28 @@ DWORD CN3UIList::MouseProc(DWORD dwFlags, const POINT & ptCur, const POINT & ptO rc.bottom += size.cy; if (::PtInRect(&rcStr, ptCur)) { - m_iCurSel = i; + if (!pStr->m_szToolTip.empty()) { + pStr->GetTooltipCtrl()->SetSingleLineText(pStr->m_szToolTip); + pStr->GetTooltipCtrl()->SetColor(pStr->m_crToolTipColor); + } + if (dwFlags & UI_MOUSE_LBCLICK) { + m_iCurSel = i; if (m_pParent) { m_pParent->ReceiveMessage(this, UIMSG_LIST_SELCHANGE); // 부모에게 버튼 클릭 통지.. } dwRet |= UIMSG_LIST_SELCHANGE; - } else { + dwRet |= UI_MOUSEPROC_DONESOMETHING; + return dwRet; + } else if (dwFlags & UI_MOUSE_LBDBLCLK) { + m_iCurSel = i; if (m_pParent) { m_pParent->ReceiveMessage(this, UIMSG_LIST_DBLCLK); // 부모에게 버튼 클릭 통지.. } dwRet |= UIMSG_LIST_DBLCLK; + dwRet |= UI_MOUSEPROC_DONESOMETHING; + return dwRet; } - dwRet |= UI_MOUSEPROC_DONESOMETHING; - return dwRet; } } } @@ -402,7 +432,7 @@ void CN3UIList::Render() { } CN3UIString * pStr = *it; if (pStr) { - RECT rc = pStr->GetRegion(); // 선택 표시 + RECT rc = pStr->GetRegion(); // Selection indicator __VertexTransformedColor vLines[5]; vLines[0].Set(rc.left, rc.top, UI_DEFAULT_Z, UI_DEFAULT_RHW, 0xff00ff00); @@ -454,7 +484,7 @@ bool CN3UIList::ReceiveMessage(CN3UIBase * pSender, DWORD dwMsg) { if (UIMSG_SCROLLBAR_POS == dwMsg) { if (pSender == m_pScrollBarRef) { this->SetScrollPos(m_pScrollBarRef->GetCurrentPos()); - // return m_pParent->ReceiveMessage(this, UIMSG_SCROLLBAR_POS); + return m_pParent->ReceiveMessage(this, UIMSG_SCROLLBAR_POS); } } diff --git a/src/engine/N3Base/N3UIList.h b/src/engine/N3Base/N3UIList.h index 35918f8a..56f8dfee 100644 --- a/src/engine/N3Base/N3UIList.h +++ b/src/engine/N3Base/N3UIList.h @@ -12,7 +12,7 @@ typedef typename std::list::iterator it_pString; class CN3UIList : public CN3UIBase { protected: - int m_iCurSel; // 현재 선택.. + int m_iCurSel; // Current selection.. std::list m_ListString; // String List class CN3UIScrollBar * m_pScrollBarRef; @@ -28,7 +28,8 @@ class CN3UIList : public CN3UIBase { D3DCOLOR FontColor() { return m_crFont; } BOOL FontIsBold() { return m_bFontBold; } BOOL FontIsItalic() { return m_bFontItalic; } - CN3UIString * GetChildStrFromList(std::string str); + CN3UIString * GetChildStrFromList(const std::string str); + void SetScrollBarRef(CN3UIScrollBar * pScrollBarRef); void SetFont(const std::string & szFontName, DWORD dwHeight, BOOL bBold, BOOL bItalic); void SetFontColor(D3DCOLOR color); @@ -38,6 +39,9 @@ class CN3UIList : public CN3UIBase { void UpdateChildRegions(); int AddStrings(const std::string * pszStrings, int iStringCount); int AddString(const std::string & szString); + int AddStringTooltip(const std::string & szString, const D3DCOLOR szStringColor = 0x00000000, + const std::string & szStringToolTip = nullptr, + const D3DCOLOR szStringToolTipColor = 0x00000000); bool InsertString(int iIndex, const std::string & szString); bool DeleteString(int iIndex); bool GetString(int iIndex, std::string & szString); diff --git a/src/engine/N3Base/N3UITooltip.cpp b/src/engine/N3Base/N3UITooltip.cpp index 44b3a209..906de5d4 100644 --- a/src/engine/N3Base/N3UITooltip.cpp +++ b/src/engine/N3Base/N3UITooltip.cpp @@ -72,6 +72,63 @@ void CN3UITooltip::Render() { CN3UIStatic::Render(); } } +// I've added this function to fix long single line tooltip. I left old function too. +void CN3UITooltip::SetSingleLineText(const std::string & szText) { + if (!m_bVisible || m_bSetText) { + return; + } + + int iStrLen = szText.size(); + if (iStrLen == 0 || m_pBuffOutRef == NULL) { + return; + } + + m_pBuffOutRef->ClearOnlyStringBuffer(); + + SIZE size; + if (m_pBuffOutRef->GetTextExtent(szText, iStrLen, &size)) { + m_pBuffOutRef->SetStyle(UISTYLE_STRING_SINGLELINE | UISTYLE_STRING_ALIGNCENTER | UISTYLE_STRING_ALIGNVCENTER); + + size.cx += 12; + size.cy += 12; + SetSize(size.cx, size.cy); + } + + m_pBuffOutRef->SetString(szText); + m_pBuffOutRef->SetColor(m_crToolTipColor); + + POINT ptNew = m_ptCursor; + ptNew.x -= (m_rcRegion.right - m_rcRegion.left) / 2; + ptNew.y -= (m_rcRegion.bottom - m_rcRegion.top) + 10; + + D3DVIEWPORT9 & vp = s_CameraData.vp; + + int vpWidth = vp.Width; + int vpHeight = vp.Height; + + int tooltipWidth = m_rcRegion.right - m_rcRegion.left; + int tooltipHeight = m_rcRegion.bottom - m_rcRegion.top; + + int horizontalMargin = 15; + int verticalMargin = 10; + + if (ptNew.x + tooltipWidth > vp.X + vpWidth) { + ptNew.x = vp.X + vpWidth - tooltipWidth - horizontalMargin; + } + if (ptNew.x < vp.X) { + ptNew.x = vp.X + horizontalMargin; + } + + if (ptNew.y + tooltipHeight > vp.Y + vpHeight) { + ptNew.y = vp.Y + vpHeight - tooltipHeight - verticalMargin; + } + if (ptNew.y < vp.Y) { + ptNew.y = vp.Y + verticalMargin; + } + SetPos(ptNew.x, ptNew.y); + + m_bSetText = true; +} void CN3UITooltip::SetText(const std::string & szText) { if (!m_bVisible || m_bSetText) { diff --git a/src/engine/N3Base/N3UITooltip.h b/src/engine/N3Base/N3UITooltip.h index 95782353..f9ed52d8 100644 --- a/src/engine/N3Base/N3UITooltip.h +++ b/src/engine/N3Base/N3UITooltip.h @@ -21,13 +21,16 @@ class CN3UITooltip : public CN3UIStatic { // Attributes public: protected: - float m_fHoverTime; // 마우스가 한곳에서 정지하여 있는 시간(누적) - bool m_bSetText; // 이미 text가 설정되었는가? - POINT m_ptCursor; // 커서의 위치 + float m_fHoverTime; // 마우스가 한곳에서 정지하여 있는 시간(누적) + bool m_bSetText; // 이미 text가 설정되었는가? + POINT m_ptCursor; // 커서의 위치 + D3DCOLOR m_crToolTipColor; // Operations public: void SetText(const std::string & szText); + void SetSingleLineText(const std::string & szText); + void SetColor(const D3DCOLOR & crToolTipColor) { m_crToolTipColor = crToolTipColor; }; virtual void Release(); virtual void Tick(); virtual void Render(); diff --git a/src/game/GameProcMain.cpp b/src/game/GameProcMain.cpp index 67f4ce4c..95e92e99 100644 --- a/src/game/GameProcMain.cpp +++ b/src/game/GameProcMain.cpp @@ -79,78 +79,6 @@ #include "N3Base/N3SndMgr.h" #include "N3Base/N3TableBase.h" -enum e_ChatCmd { - CMD_WHISPER, - CMD_TOWN, - CMD_EXIT, - CMD_GREETING, - CMD_GREETING2, - CMD_GREETING3, - CMD_PROVOKE, - CMD_PROVOKE2, - CMD_PROVOKE3, - CMD_GAME_SAVE, - CMD_RECOMMEND, - CMD_INDIVIDUAL_BATTLE, - CMDSIT_STAND, - CMD_WALK_RUN, - CMD_LOCATION, - - CMD_TRADE, - CMD_FORBIDTRADE, - CMD_PERMITTRADE, - CMD_MERCHANT, - - CMD_PARTY, - CMD_LEAVEPARTY, - CMD_RECRUITPARTY, - CMD_SEEKING_PARTY, - CMD_FORBIDPARTY, - CMD_PERMITPARTY, - - CMD_JOINCLAN, - CMD_WITHDRAWCLAN, - CMD_FIRECLAN, - CMD_COMMAND, - CMD_CLAN_WAR, - CMD_SURRENDER, - CMD_APPOINTVICECHIEF, - CMD_CLAN_CHAT, - CMD_CLAN_BATTLE, - - CMD_CONFEDERACY, - CMD_BAN_KNIGHTS, - CMD_QUIT_KNIGHTS, - CMD_BASE, - CMD_DECLARATION, - - CMD_VISIBLE, - CMD_INVISIBLE, - CMD_CLEAN, - CMD_RAINING, - CMD_SNOWING, - CMD_TIME, - CMD_CU_COUNT, - CMD_NOTICE, - CMD_ARREST, - CMD_FORBIDCONNECT, - CMD_FORBIDCHAT, - CMD_PERMITCHAT, - CMD_NOTICEALL, - CMD_CUTOFF, - CMD_VIEW, - CMD_UNVIEW, - CMD_FORBIDUSER, - CMD_SUMMONUSER, - CMD_ATTACKDISABLE, - CMD_ATTACKENABLE, - CMD_PLC, - - CMD_COUNT, - CMD_UNKNOWN = 0xffffffff -}; -static std::string s_szCmdMsg[CMD_COUNT]; // 게임상 명령어 - ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// @@ -181,8 +109,8 @@ CGameProcMain::CGameProcMain() // r기본 생성자.. 각 변수의 역활은 m_pUIStateBarAndMiniMap = new CUIStateBar(); m_pUIVar = new CUIVarious(); m_pUICmd = new CUICmd(); - m_pUICmdList = new CUICmdListDlg(); - m_pUICmdEditDlg = new CUICmdEditDlg(); + m_pUICmdList = new CUICmdList(); + m_pUICmdEditDlg = new CUICmdEdit(); m_pUITargetBar = new CUITargetBar(); m_pUIHelp = new CUIHelp(); m_pUINotice = new CUINotice(); @@ -325,31 +253,6 @@ void CGameProcMain::Init() { m_pLightMgr->Release(); s_pEng->SetDefaultLight(m_pLightMgr->Light(0), m_pLightMgr->Light(1), m_pLightMgr->Light(2)); - int i = 0; - for (uint32_t resource = IDS_CMD_WHISPER; resource <= IDS_CMD_LOCATION; resource++) { - ::_LoadStringFromResource(resource, s_szCmdMsg[i++]); - } - - for (uint32_t resource = IDS_CMD_TRADE; resource <= IDS_CMD_MERCHANT; resource++) { - ::_LoadStringFromResource(resource, s_szCmdMsg[i++]); - } - - for (uint32_t resource = IDS_CMD_PARTY; resource <= IDS_CMD_PERMITPARTY; resource++) { - ::_LoadStringFromResource(resource, s_szCmdMsg[i++]); - } - - for (uint32_t resource = IDS_CMD_JOINCLAN; resource <= IDS_CMD_CLAN_BATTLE; resource++) { - ::_LoadStringFromResource(resource, s_szCmdMsg[i++]); - } - - for (uint32_t resource = IDS_CMD_CONFEDERACY; resource <= IDS_CMD_DECLARATION; resource++) { - ::_LoadStringFromResource(resource, s_szCmdMsg[i++]); - } - - for (uint32_t resource = IDS_CMD_VISIBLE; resource <= IDS_CMD_PLC; resource++) { - ::_LoadStringFromResource(resource, s_szCmdMsg[i++]); - } - s_SndMgr.ReleaseStreamObj(&(CGameProcedure::s_pSnd_BGM)); if (m_pWarMessage) { @@ -5028,18 +4931,25 @@ void CGameProcMain::MsgRecv_UserState(DataPack * pDataPack, int & iOffset) { } } else if (N3_SP_STATE_CHANGE_ACTION == eSP) // 크기 변함 { - if (1 == iState) { + switch (iState) { + case 1u: pBPC->AnimationAdd(ANI_GREETING0, true); - } else if (2 == iState) { + break; + case 2u: pBPC->AnimationAdd(ANI_GREETING1, true); - } else if (3 == iState) { + break; + case 3u: pBPC->AnimationAdd(ANI_GREETING2, true); - } else if (11 == iState) { - pBPC->AnimationAdd(ANI_WAR_CRY0, true); - } else if (12 == iState) { + break; + case 11u: pBPC->AnimationAdd(ANI_WAR_CRY1, true); - } else if (13 == iState) { + break; + case 12u: + pBPC->AnimationAdd(ANI_WAR_CRY0, true); + break; + case 13u: pBPC->AnimationAdd(ANI_WAR_CRY2, true); + break; } } } @@ -5643,7 +5553,11 @@ void CGameProcMain::ParseChattingCommand(const std::string & szCmd) { static BYTE byBuff[1024] = ""; sscanf(szCmd.c_str(), "/%s %s %s %s", szCmds[0], szCmds[1], szCmds[2], szCmds[3]); - if (0 == lstrcmp(szCmds[0], "goto")) { + //upper command + std::transform(szCmds[0], szCmds[0] + std::strlen(szCmds[0]), szCmds[0], + [](unsigned char c) { return std::toupper(c); }); + + if (0 == lstrcmp(szCmds[0], "GOTO")) { float fX = (float)atof(szCmds[1]); float fZ = (float)atof(szCmds[2]); @@ -5653,30 +5567,31 @@ void CGameProcMain::ParseChattingCommand(const std::string & szCmd) { CAPISocket::MP_AddWord(byBuff, iOffset, (fZ * 10)); s_pSocket->Send(byBuff, iOffset); - } else if (0 == lstrcmp(szCmds[0], "systemgametimeon")) { + } else if (0 == lstrcmp(szCmds[0], "SYSTEMGAMETIMEON")) { if (m_pUIStateBarAndMiniMap) { m_pUIStateBarAndMiniMap->SetSystemTimeVisibility(true); } - } else if (0 == lstrcmp(szCmds[0], "systemgametimeoff")) { + } else if (0 == lstrcmp(szCmds[0], "SYSTEMGAMETIMEOFF")) { if (m_pUIStateBarAndMiniMap) { m_pUIStateBarAndMiniMap->SetSystemTimeVisibility(false); } } - e_ChatCmd eCmd = CMD_UNKNOWN; - for (int i = 0; i < CMD_COUNT; i++) { - if (0 == lstrcmpi(szCmds[0], s_szCmdMsg[i].c_str())) { - eCmd = (e_ChatCmd)i; - break; - } + int eCmd = -1; + + if (m_pUICmdList->g_commandMappings.count(szCmds[0]) > 0) { + eCmd = m_pUICmdList->g_commandMappings[szCmds[0]]; } switch (eCmd) { - case CMD_WHISPER: { + //////////////////////////////////////////////////////////////////////////////////////// + //PRIVATE + //////////////////////////////////////////////////////////////////////////////////////// + case iPrivateCommand ::CMD_WHISPER: { this->MsgSend_ChatSelectTarget(szCmds[1]); // 일대일 채팅 상대 정하기. } break; - case CMD_TOWN: { + case iPrivateCommand::CMD_TOWN: { if (s_pPlayer->m_bStun) { return; // 기절해 있음 못함.. } @@ -5693,7 +5608,56 @@ void CGameProcMain::ParseChattingCommand(const std::string & szCmd) { } } break; - case CMD_TRADE: { + case iPrivateCommand::CMD_EXIT: { + PostQuitMessage(0); + } break; + + case iPrivateCommand::CMD_GREETING: + case iPrivateCommand::CMD_GREETING2: + case iPrivateCommand::CMD_GREETING3: { + if (s_pPlayer->State() == PSA_BASIC && s_pPlayer->StateMove() == PSM_STOP) { + this->MsgSend_StateChange(N3_SP_STATE_CHANGE_ACTION, 1 + (eCmd - CMD_GREETING)); + } + } break; + + case iPrivateCommand::CMD_PROVOKE: + case iPrivateCommand::CMD_PROVOKE2: + case iPrivateCommand::CMD_PROVOKE3: { + if (s_pPlayer->State() == PSA_BASIC && s_pPlayer->StateMove() == PSM_STOP) { + this->MsgSend_StateChange(N3_SP_STATE_CHANGE_ACTION, 11 + (eCmd - CMD_PROVOKE)); + } + } break; + + case iPrivateCommand::CMD_GAME_SAVE: { + if (m_fRequestGameSave > 300.0f) { + BYTE byBuff[4]; + int iOffset = 0; + s_pSocket->MP_AddByte(byBuff, iOffset, N3_REQUEST_GAME_SAVE); // Save request command.. + s_pSocket->Send(byBuff, iOffset); + m_fRequestGameSave = 0.0f; + + std::string szMsg; + ::_LoadStringFromResource(IDS_REQUEST_GAME_SAVE, szMsg); + this->MsgOutput(szMsg, 0xffffff00); + } else { + char szBuf[256]; + std::string szMsg; + ::_LoadStringFromResource(IDS_DELAY_GAME_SAVE, szMsg); + sprintf(szBuf, szMsg.c_str(), 5); + this->MsgOutput(szBuf, 0xffffff00); + } + } break; + + case iPrivateCommand::CMD_RECOMMEND: { + //TODO + } break; + case iPrivateCommand::CMD_INDIVIDUAL_BATTLE: { + //TODO + } break; + //////////////////////////////////////////////////////////////////////////////////////// + // TRADE + //////////////////////////////////////////////////////////////////////////////////////// + case iTradeCommand::CMD_TRADE: { CPlayerOther * pOPC = s_pOPMgr->UPCGetByID(s_pPlayer->m_iIDTarget, true); if (pOPC && (pOPC->Position() - s_pPlayer->Position()).Magnitude() < (pOPC->Height() + 5.0f) && !m_pUITransactionDlg @@ -5719,13 +5683,23 @@ void CGameProcMain::ParseChattingCommand(const std::string & szCmd) { m_pSubProcPerTrade->EnterWaitMsgFromServerStatePerTradeReq(); } - } break; - case CMD_EXIT: { - PostQuitMessage(0); } break; + case iTradeCommand::CMD_FORBIDTRADE: + //TODO + break; - case CMD_PARTY: { + case iTradeCommand::CMD_PERMITTRADE: + //TODO + break; + + case iTradeCommand::CMD_MERCHANT: + //TODO + break; + //////////////////////////////////////////////////////////////////////////////////////// + //PARTY + //////////////////////////////////////////////////////////////////////////////////////// + case iPartyCommand::CMD_PARTY: { CPlayerBase * pTarget = s_pOPMgr->UPCGetByID(s_pPlayer->m_iIDTarget, true); if (pTarget) { std::string szMsg; @@ -5738,11 +5712,10 @@ void CGameProcMain::ParseChattingCommand(const std::string & szCmd) { } } break; - case CMD_LEAVEPARTY: { + case iPartyCommand::CMD_LEAVEPARTY: { this->MsgSend_PartyOrForceLeave(0); // 파티 요청.. } break; - - case CMD_RECRUITPARTY: { + case iPartyCommand::CMD_SEEKING_PARTY: { if (m_pUIPartyBBS) { if (s_pPlayer->m_bRecruitParty) { m_pUIPartyBBS->MsgSend_RegisterCancel(); @@ -5754,129 +5727,198 @@ void CGameProcMain::ParseChattingCommand(const std::string & szCmd) { // if(m_pUIPartyBBS && !m_pUIPartyBBS->IsVisible()) // m_pUIPartyBBS->MsgSend_RefreshData(0); } break; - - case CMD_JOINCLAN: { + case iPartyCommand::CMD_FORBIDPARTY: + //TODO + break; + case iPartyCommand::CMD_PERMITPARTY: + //TODO + break; + //////////////////////////////////////////////////////////////////////////////////////// + //CLAN + //////////////////////////////////////////////////////////////////////////////////////// + case iClanCommand::CMD_JOINCLAN: { if (s_pPlayer->m_InfoExt.eKnightsDuty == KNIGHTS_DUTY_CHIEF || s_pPlayer->m_InfoExt.eKnightsDuty == KNIGHTS_DUTY_VICECHIEF) { this->MsgSend_KnightsJoin(s_pPlayer->m_iIDTarget); } } break; - - case CMD_WITHDRAWCLAN: { + case iClanCommand::CMD_WITHDRAWCLAN: { this->MsgSend_KnightsWithdraw(); } break; - - case CMD_FIRECLAN: { + case iClanCommand::CMD_FIRECLAN: { if (s_pPlayer->m_InfoExt.eKnightsDuty == KNIGHTS_DUTY_CHIEF) { std::string szName = szCmds[1]; MsgSend_KnightsLeave(szName); } } break; - - case CMD_APPOINTVICECHIEF: { + case iClanCommand::CMD_COMMAND: { + //TODO + } break; + case iClanCommand::CMD_CLAN_WAR: { + //TODO + } break; + case iClanCommand::CMD_SURRENDER: { + //TODO + } break; + case iClanCommand::CMD_APPOINTVICECHIEF: { if (s_pPlayer->m_InfoExt.eKnightsDuty == KNIGHTS_DUTY_CHIEF) { std::string szName = szCmds[1]; MsgSend_KnightsAppointViceChief(szName); } } break; - - case CMD_GREETING: - case CMD_GREETING2: - case CMD_GREETING3: { - if (s_pPlayer->State() == PSA_BASIC && s_pPlayer->StateMove() == PSM_STOP) { - this->MsgSend_StateChange(N3_SP_STATE_CHANGE_ACTION, 1 + (eCmd - CMD_GREETING)); - } + case iClanCommand::CMD_CLAN_CHAT: { + //TODO } break; - - case CMD_PROVOKE: - case CMD_PROVOKE2: - case CMD_PROVOKE3: { - if (s_pPlayer->State() == PSA_BASIC && s_pPlayer->StateMove() == PSM_STOP) { - this->MsgSend_StateChange(N3_SP_STATE_CHANGE_ACTION, 11 + (eCmd - CMD_PROVOKE)); - } + case iClanCommand::CMD_CLAN_BATTLE: { + //TODO } break; - - case CMD_VISIBLE: { - this->MsgSend_StateChange(N3_SP_STATE_CHANGE_VISIBLE, 0); + //////////////////////////////////////////////////////////////////////////////////////// + //KNIGHTS + //////////////////////////////////////////////////////////////////////////////////////// + case iKnightsCommand::CMD_CONFEDERACY: { + //TODO 1298 } break; - - case CMD_INVISIBLE: { - this->MsgSend_StateChange(N3_SP_STATE_CHANGE_VISIBLE, 255); + case iKnightsCommand::CMD_BAN_KNIGHTS: { + //TODO 1298 } break; - - case CMD_CLEAN: { + case iKnightsCommand::CMD_QUIT_KNIGHTS: { + //TODO 1298 + } break; + case iKnightsCommand::CMD_BASE: { + //TODO 1298 + } break; + case iKnightsCommand::CMD_DECLARATION: { + //TODO 1298 + } break; + //////////////////////////////////////////////////////////////////////////////////////// + //GUARDIAN MONSTER + //////////////////////////////////////////////////////////////////////////////////////// + case iGuardianCommand::CMD_GUARD_HIDE: { + //TODO 1298 + } break; + case iGuardianCommand::CMD_GUARD: { + //TODO 1298 + } break; + case iGuardianCommand::CMD_GUARD_DEFEND: { + //TODO 1298 + } break; + case iGuardianCommand::CMD_GUARD_LOOK_OUT: { + //TODO 1298 + } break; + case iGuardianCommand::CMD_GUARD_FORMATION: { + //TODO 1298 + } break; + case iGuardianCommand::CMD_GUARD_REST: { + //TODO 1298 + } break; + case iGuardianCommand::CMD_GUARD_DESTROY: { + //TODO 1298 + } break; + //////////////////////////////////////////////////////////////////////////////////////// + //KING + //////////////////////////////////////////////////////////////////////////////////////// + case iKingCommand::CMD_KING_ROYALORDER: { + //TODO 1298 + } break; + case iKingCommand::CMD_KING_PRIZE: { + //TODO 1298 + } break; + case iKingCommand::CMD_KING_EXPRATE: { + //TODO 1298 + } break; + case iKingCommand::CMD_KING_DROPRATE: { + //TODO 1298 + } break; + case iKingCommand::CMD_KING_RAIN: { + //TODO 1298 + } break; + case iKingCommand::CMD_KING_SNOW: { + //TODO 1298 + } break; + case iKingCommand::CMD_KING_CLEAR: { + //TODO 1298 + } break; + case iKingCommand::CMD_KING_REWARD: { + //TODO 1298 + } break; + //////////////////////////////////////////////////////////////////////////////////////// + //GM + //////////////////////////////////////////////////////////////////////////////////////// + case iGmCommand::CMD_VISIBLE: { + } break; + case iGmCommand::CMD_INVISIBLE: { + } break; + case iGmCommand::CMD_CLEAN: { int iPercent = atoi(szCmds[1]); this->MsgSend_Weather(1, iPercent); } break; - case CMD_RAINING: { + case iGmCommand::CMD_RAINING: { int iPercent = atoi(szCmds[1]); this->MsgSend_Weather(2, iPercent); } break; - - case CMD_SNOWING: { + case iGmCommand::CMD_SNOWING: { int iPercent = atoi(szCmds[1]); this->MsgSend_Weather(3, iPercent); } break; - - case CMD_TIME: { + case iGmCommand::CMD_TIME: { int iHour = atoi(szCmds[1]); int iMin = atoi(szCmds[2]); this->MsgSend_Time(iHour, iMin); } break; - - case CMD_CU_COUNT: { + case iGmCommand::CMD_CU_COUNT: { int iOffset = 0; CAPISocket::MP_AddByte(byBuff, iOffset, N3_CONCURRENT_USER_COUNT); s_pSocket->Send(byBuff, iOffset); } break; - - case CMD_NOTICE: { + case iGmCommand::CMD_NOTICE: { if (szCmd.size() >= 7) { std::string szChat = szCmd.substr(6); // "/공지 "를 제외한 나머지 문자열 this->MsgSend_Chat(N3_CHAT_PUBLIC, szChat); } + } + case iGmCommand::CMD_ARREST: { + this->MsgSend_Administrator(N3_SP_ADMINISTRATOR_ARREST, szCmds[1]); } break; - - case CMD_ARREST: { - this->MsgSend_Administrator(N3_SP_ADMINISTRATOR_ARREST, szCmds[1]); //추적 - } break; - - case CMD_FORBIDCONNECT: { + case iGmCommand::CMD_FORBIDCONNECT: { this->MsgSend_Administrator(N3_SP_ADMINISTRATOR_FORBID_CONNECT, szCmds[1]); //접속금지 } break; - - case CMD_FORBIDCHAT: { + case iGmCommand::CMD_FORBIDCHAT: { this->MsgSend_Administrator(N3_SP_ADMINISTRATOR_CHAT_FORBID, szCmds[1]); //채팅금지 } break; - - case CMD_PERMITCHAT: { + case iGmCommand::CMD_PERMITCHAT: { this->MsgSend_Administrator(N3_SP_ADMINISTRATOR_CHAT_PERMIT, szCmds[1]); //채팅허가 } break; - - case CMD_GAME_SAVE: { - if (m_fRequestGameSave > 300.0f) { - BYTE byBuff[4]; // 버퍼.. - int iOffset = 0; // 옵셋.. - s_pSocket->MP_AddByte(byBuff, iOffset, N3_REQUEST_GAME_SAVE); // 저장 요청 커멘드.. - s_pSocket->Send(byBuff, iOffset); // 보냄.. - m_fRequestGameSave = 0.0f; - - std::string szMsg; - ::_LoadStringFromResource(IDS_REQUEST_GAME_SAVE, szMsg); - this->MsgOutput(szMsg, 0xffffff00); - } else { - char szBuf[256]; - std::string szMsg; - ::_LoadStringFromResource(IDS_DELAY_GAME_SAVE, szMsg); - sprintf(szBuf, szMsg.c_str(), 5); - this->MsgOutput(szBuf, 0xffffff00); - } + case iGmCommand::CMD_NOTICEALL: { + //TODO + } break; + case iGmCommand::CMD_CUTOFF: { + //TODO + } break; + case iGmCommand::CMD_VIEW: { + //TODO + } break; + case iGmCommand::CMD_UNVIEW: { + //TODO + } break; + case iGmCommand::CMD_FORBIDUSER: { + //TODO + } break; + case iGmCommand::CMD_SUMMONUSER: { + //TODO + } break; + case iGmCommand::CMD_ATTACKDISABLE: { + //TODO + } break; + case iGmCommand::CMD_ATTACKENABLE: { + //TODO + } break; + case iGmCommand::CMD_PLC: { + //TODO } break; - default: break; - } // end of switch(eCmd) + } } void CGameProcMain::UpdateUI_PartyOrForceButtons() { diff --git a/src/game/GameProcMain.h b/src/game/GameProcMain.h index 0b164909..5f1f8d67 100644 --- a/src/game/GameProcMain.h +++ b/src/game/GameProcMain.h @@ -27,8 +27,8 @@ class CGameProcMain : public CGameProcedure { class CUIMessageWnd * m_pUIMsgDlg; // 게임 메시지 출력 상자. class CUIStateBar * m_pUIStateBarAndMiniMap; // mp,hp,exp, minimap.... class CUICmd * m_pUICmd; // 왼쪽 하단의 명령버튼 창.. - class CUICmdListDlg * m_pUICmdList; - class CUICmdEditDlg * m_pUICmdEditDlg; + class CUICmdEdit * m_pUICmdList; + class CUICmdEdit * m_pUICmdEditDlg; class CUITargetBar * m_pUITargetBar; // 타겟 상태창.. class CUITransactionDlg * m_pUITransactionDlg; class CUIDroppedItemDlg * m_pUIDroppedItemDlg; diff --git a/src/game/UICmd.cpp b/src/game/UICmd.cpp index 43ad216b..d50f36b7 100644 --- a/src/game/UICmd.cpp +++ b/src/game/UICmd.cpp @@ -120,7 +120,9 @@ bool CUICmd::ReceiveMessage(CN3UIBase * pSender, DWORD dwMsg) { CGameProcedure::s_pProcMain->CommandToggleUIState(); } - else if (pSender == m_pBtn_Exit) { + else if (pSender == m_pBtn_Option) { + CGameProcedure::s_pProcMain->CommandToggleCmdList(); + } else if (pSender == m_pBtn_Exit) { CGameProcedure::s_pProcMain->CommandExitMenu(); } diff --git a/src/game/UICmdEdit.cpp b/src/game/UICmdEdit.cpp index 338fe0b5..41a357b1 100644 --- a/src/game/UICmdEdit.cpp +++ b/src/game/UICmdEdit.cpp @@ -14,11 +14,11 @@ // Construction/Destruction ////////////////////////////////////////////////////////////////////// -CUICmdEditDlg::CUICmdEditDlg() {} +CUICmdEdit::CUICmdEdit() {} -CUICmdEditDlg::~CUICmdEditDlg() {} +CUICmdEdit::~CUICmdEdit() {} -bool CUICmdEditDlg::Load(HANDLE hFile) { +bool CUICmdEdit::Load(HANDLE hFile) { if (CN3UIBase::Load(hFile) == false) { return false; } @@ -34,11 +34,11 @@ bool CUICmdEditDlg::Load(HANDLE hFile) { return true; } -bool CUICmdEditDlg::ReceiveMessage(CN3UIBase * pSender, DWORD dwMsg) { +bool CUICmdEdit::ReceiveMessage(CN3UIBase * pSender, DWORD dwMsg) { if (dwMsg == UIMSG_BUTTON_CLICK) { if (pSender->m_szID == "btn_ok") { m_szArg1 = m_pEdit_Box->GetString(); - std::string tempCmdStr = "/" + m_pText_Title->GetString() + " " + m_szArg1; + std::string tempCmdStr = m_pText_Title->GetString() + " " + m_szArg1; CGameProcedure::s_pProcMain->ParseChattingCommand(tempCmdStr); SetVisible(false); @@ -53,9 +53,9 @@ bool CUICmdEditDlg::ReceiveMessage(CN3UIBase * pSender, DWORD dwMsg) { return true; } -void CUICmdEditDlg::Open(std::string msg) { +void CUICmdEdit::Open(std::string msg) { if (!msg.empty()) { - //m_pText_Title->SetString(msg); + m_pText_Title->SetString("/" + msg); m_pEdit_Box->SetString(""); } @@ -63,7 +63,7 @@ void CUICmdEditDlg::Open(std::string msg) { SetVisible(true); } -void CUICmdEditDlg::SetVisible(bool bVisible) { +void CUICmdEdit::SetVisible(bool bVisible) { if (bVisible == this->IsVisible()) { return; } diff --git a/src/game/UICmdEdit.h b/src/game/UICmdEdit.h index a57feb45..97209857 100644 --- a/src/game/UICmdEdit.h +++ b/src/game/UICmdEdit.h @@ -6,7 +6,7 @@ ////////////////////////////////////////////////////////////////////// -class CUICmdEditDlg : public CN3UIBase { +class CUICmdEdit : public CN3UIBase { public: CN3UIString * m_pText_Title; CN3UIButton * m_pBtn_Ok; @@ -15,12 +15,12 @@ class CUICmdEditDlg : public CN3UIBase { std::string m_szArg1; public: - void SetVisible(bool bVisible); + void SetVisible(bool bVisible) override; void Open(std::string msg); bool Load(HANDLE hFile); bool ReceiveMessage(CN3UIBase * pSender, DWORD dwMsg); - CUICmdEditDlg(); - virtual ~CUICmdEditDlg(); + CUICmdEdit(); + virtual ~CUICmdEdit(); }; diff --git a/src/game/UICmdList.cpp b/src/game/UICmdList.cpp index 77e7f849..06bc1cbf 100644 --- a/src/game/UICmdList.cpp +++ b/src/game/UICmdList.cpp @@ -1,108 +1,138 @@ // UICmdListDlg.cpp: implementation of the CUICmdListDlg class. // -////////////////////////////////////////////////////////////////////// #include "StdAfx.h" - #include "LocalInput.h" #include "Resource.h" #include "UICmdList.h" - #include "GameProcedure.h" #include "GameProcMain.h" #include "UIHotKeyDlg.h" #include "UIManager.h" - #include "N3Base/N3UIArea.h" #include "N3Base/N3UIString.h" +#include "N3Base/N3UITooltip.h" #include "N3Base/N3UIScrollBar.h" #include "N3Base/N3SndObj.h" - #include "APISocket.h" #include "PacketDef.h" #include "PlayerMySelf.h" #include "UIManager.h" - #include "N3UIDBCLButton.h" - #include "GameDef.h" ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// -CUICmdListDlg::CUICmdListDlg() { +CUICmdList::CUICmdList() { m_bOpenningNow = false; m_bClosingNow = false; m_fMoveDelta = 0.0f; - m_pBtn_cancel = NULL; - m_pList_CmdCat = NULL; - m_pList_Cmds = NULL; - m_pUICmdEdit = NULL; - m_pScroll_Categories = NULL; - m_pScroll_Commands = NULL; + m_pBtn_cancel = nullptr; + m_pList_CmdCat = nullptr; + m_pList_Cmds = nullptr; + m_pUICmdEdit = nullptr; + m_pScroll_Categories = nullptr; + m_pScroll_Commands = nullptr; + + m_pList_CommandsPrivate = nullptr; + m_pList_CommandsTrade = nullptr; + m_pList_CommandsClan = nullptr; + m_pList_CommandsKnights = nullptr; + m_pList_CommandsParty = nullptr; + m_pList_CommandsGuardianMonster = nullptr; + m_pList_CommandsKing = nullptr; + m_pList_CommandsGM = nullptr; + m_pList_Cmds = nullptr; } -CUICmdListDlg::~CUICmdListDlg() { +CUICmdList::~CUICmdList() { Release(); } -bool CUICmdListDlg::Load(HANDLE hFile) { +bool CUICmdList::Load(HANDLE hFile) { if (CN3UIBase::Load(hFile) == false) { return false; } - m_pBtn_cancel = (CN3UIButton *)this->GetChildByID("btn_cancel"); - __ASSERT(m_pBtn_cancel, "NULL UI Component!!!"); - m_pList_CmdCat = (CN3UIList *)this->GetChildByID("list_curtailment"); - __ASSERT(m_pList_CmdCat, "NULL UI Component!!!"); - m_pList_Cmds = (CN3UIList *)this->GetChildByID("list_content"); - __ASSERT(m_pList_Cmds, "NULL UI Component!!!"); - - //CN3UIArea - // CN3UIBase * pChild = m_pArea_Destroy->GetChildByIndex(i); - /* - m_pScroll_Categories = (CN3UIList *)m_pList_CmdCat->GetChildByIndex(0); - __ASSERT(m_pScroll_Categories, "NULL UI Component!!"); + m_pBtn_cancel = dynamic_cast(GetChildByID("btn_cancel")); + if (!m_pBtn_cancel) { + __ASSERT(m_pBtn_cancel, "NULL UI Component!!!"); + return false; + } + + m_pList_CmdCat = dynamic_cast(GetChildByID("list_curtailment")); + if (!m_pList_CmdCat) { + __ASSERT(m_pList_CmdCat, "NULL UI Component!!!"); + return false; + } + + m_pList_Cmds = dynamic_cast(GetChildByID("list_content")); + if (!m_pList_Cmds) { + __ASSERT(m_pList_Cmds, "NULL UI Component!!!"); + return false; + } + + m_pScroll_Categories = dynamic_cast(m_pList_CmdCat->GetChildByIndex(0)); + if (!m_pScroll_Categories) { + __ASSERT(m_pScroll_Categories, "NULL UI Component!!"); + return false; + } m_pScroll_Categories->SetVisible(true); - m_pScroll_Commands = (CN3UIScrollBar *)m_pList_Cmds->GetChildByIndex(0); - __ASSERT(m_pScroll_Categories, "NULL UI Component!!"); + m_pScroll_Commands = dynamic_cast(m_pList_Cmds->GetChildByIndex(0)); + if (!m_pScroll_Commands) { + __ASSERT(m_pScroll_Commands, "NULL UI Component!!"); + return false; + } m_pScroll_Commands->SetVisible(true); - */ + m_pList_CmdCat->SetScrollBarRef(m_pScroll_Categories); + m_pList_Cmds->SetScrollBarRef(m_pScroll_Commands); - CreateCategoryList(); + InitCommands(); return true; } -void CUICmdListDlg::Release() { +void CUICmdList::Release() { CN3UIBase::Release(); } -void CUICmdListDlg::Open() { +void CUICmdList::Open() { SetVisible(true); - this->SetPos(CN3Base::s_CameraData.vp.Width, 10); + SetPos(CN3Base::s_CameraData.vp.Width, 10); m_fMoveDelta = 0; m_bOpenningNow = true; m_bClosingNow = false; + if (CGameBase::s_pPlayer->m_InfoBase.iAuthority != AUTHORITY_MANAGER) { + if (m_pList_CmdCat->GetChildStrFromList(szGmCategory)) { + m_pList_CmdCat->GetChildStrFromList(szGmCategory)->SetVisible(false); + } + } else { + if (m_pList_CmdCat->GetChildStrFromList(szGmCategory)) { + m_pList_CmdCat->GetChildStrFromList(szGmCategory)->SetVisible(true); + } + } + m_iRBtnDownOffs = -1; } -void CUICmdListDlg::Close(bool bByKey) { + +void CUICmdList::Close(bool bByKey) { SetVisible(false); m_fMoveDelta = 0; m_bOpenningNow = false; m_bClosingNow = true; } -void CUICmdListDlg::Tick() { +void CUICmdList::Tick() { if (m_bOpenningNow) { - POINT ptCur = this->GetPos(); - RECT rc = this->GetRegion(); - float fWidth = (float)(rc.right - rc.left); + POINT ptCur = GetPos(); + RECT rc = GetRegion(); + float fWidth = static_cast(rc.right - rc.left); float fDelta = 5000.0f * CN3Base::s_fSecPerFrm; fDelta *= (fWidth - m_fMoveDelta) / fWidth; @@ -111,18 +141,18 @@ void CUICmdListDlg::Tick() { } m_fMoveDelta += fDelta; - int iXLimit = CN3Base::s_CameraData.vp.Width - (int)fWidth; - ptCur.x = CN3Base::s_CameraData.vp.Width - (int)m_fMoveDelta; + int iXLimit = CN3Base::s_CameraData.vp.Width - static_cast(fWidth); + ptCur.x = CN3Base::s_CameraData.vp.Width - static_cast(m_fMoveDelta); if (ptCur.x <= iXLimit) { ptCur.x = iXLimit; m_bOpenningNow = false; } - this->SetPos(ptCur.x, ptCur.y); + SetPos(ptCur.x, ptCur.y); } else if (m_bClosingNow) { - POINT ptCur = this->GetPos(); - RECT rc = this->GetRegion(); - float fWidth = (float)(rc.right - rc.left); + POINT ptCur = GetPos(); + RECT rc = GetRegion(); + float fWidth = static_cast(rc.right - rc.left); float fDelta = 5000.0f * CN3Base::s_fSecPerFrm; fDelta *= (fWidth - m_fMoveDelta) / fWidth; @@ -132,95 +162,128 @@ void CUICmdListDlg::Tick() { m_fMoveDelta += fDelta; int iXLimit = CN3Base::s_CameraData.vp.Width; - ptCur.x = CN3Base::s_CameraData.vp.Width - (int)(fWidth - m_fMoveDelta); + ptCur.x = CN3Base::s_CameraData.vp.Width - static_cast(fWidth - m_fMoveDelta); if (ptCur.x >= iXLimit) { ptCur.x = iXLimit; m_bClosingNow = false; - this->SetVisibleWithNoSound(false, false, true); + SetVisibleWithNoSound(false, false, true); } - this->SetPos(ptCur.x, ptCur.y); + SetPos(ptCur.x, ptCur.y); } CN3UIBase::Tick(); } -bool CUICmdListDlg::CreateCategoryList() { - if (m_pList_CmdCat == NULL || m_pList_Cmds == NULL) { - return false; +void CUICmdList::InitCommands() { + if (!m_pList_CmdCat) { + return; } - std::string szCategory; - int idStart = IDS_PRIVATE_CMD_CAT; + for (int i = 0; i < CMD_LIST_COUNT; ++i) { + if (i == CMD_LIST_KNIGHTS - COMMANDS_CATEGORY_NAMES_INDEX || + i == CMD_LIST_GUARDIAN - COMMANDS_CATEGORY_NAMES_INDEX || + i == CMD_LIST_KING - COMMANDS_CATEGORY_NAMES_INDEX) { // -> in ver 1298 remove this condition + continue; + } - for (int i = 0; i < 8; i++) { - ::_LoadStringFromResource(i + 7800, szCategory); //load command categories + std::string szCategory; + _LoadStringFromResource(i + COMMANDS_CATEGORY_NAMES_INDEX, szCategory); - if (CGameBase::s_pPlayer->m_InfoBase.iAuthority == 0 && szCategory == "GM") { // if not gm hide this category - continue; + if (i + COMMANDS_CATEGORY_NAMES_INDEX == CMD_LIST_GM) { + szGmCategory = szCategory; } - m_pList_CmdCat->AddString(szCategory); - idStart++; + std::string cmdCategoryTip; + _LoadStringFromResource(i + COMMANDS_CATEGORY_TOOLTIP_INDEX, cmdCategoryTip); + m_pList_CmdCat->AddStringTooltip(szCategory, 0xFFC6C6FB, cmdCategoryTip.c_str(), 0xFF80FF80); } - m_pList_CmdCat->SetFontColor(0xffffff00); //green + int rangeMax = m_pList_CmdCat->GetCount() - MAX_VISIBLE_ITEMS; + m_pScroll_Categories->SetVisibleWithNoSound(rangeMax >= 0); + m_pScroll_Categories->SetRange(0, rangeMax); - int idCur = 8000; //Command list strings start at this index - int idEnd = 9600; //Command list strings end at this index + m_pList_CmdCat->SetFontColor(0xffffff00); // yellow - std::string szCommand; - //create map of commands - for (int i = idCur; idCur < idEnd; idCur++, i++) { - if (idCur == 9000) { - i += 400; // offset and put gm cmds at end of map - } else if (idCur == 9100) { - i -= 500; - idCur = 9200; - } - szCommand.clear(); - ::_LoadStringFromResource(idCur, szCommand); - if (!szCommand.empty() && (i / 100) % 2 == 0) { - m_mapCmds[i] = szCommand; - } - } - - UpdateCommandList(CMD_LIST_PRIVATE); //initialize a cmd list for viewing when opening cmd window + LoadCommandMap(m_mCmd_Private, CMD_WHISPER, CMD_INDIVIDUAL_BATTLE); + LoadCommandMap(m_mCmd_Trade, CMD_TRADE, CMD_MERCHANT); + LoadCommandMap(m_mCmd_Party, CMD_PARTY, CMD_PERMITPARTY); + LoadCommandMap(m_mCmd_Clan, CMD_JOINCLAN, CMD_CLAN_BATTLE); + // LoadCommandMap(m_mCmd_Knights, CMD_CONFEDERACY, CMD_DECLARATION); -> in ver 1298 remove comment and enable + // LoadCommandMap(m_mCmd_Guard, CMD_GUARD_HIDE, CMD_GUARD_DESTROY); + // LoadCommandMap(m_mCmd_King, CMD_KING_ROYALORDER, CMD_KING_REWARD); + LoadCommandMap(m_mCmd_GM, CMD_VISIBLE, CMD_PLC); - return true; + UpdateCommandList(CMD_LIST_PRIVATE); } -bool CUICmdListDlg::UpdateCommandList(uint8_t cmdCat) { - if (m_pList_Cmds == NULL) { - return false; + +void CUICmdList::LoadCommandMap(std::map & cmdMap, int startId, int endId) { + int i = 0; + for (int indexResource = startId; indexResource <= endId; ++indexResource) { + CommandInfo info; + _LoadStringFromResource(indexResource, info.name); + _LoadStringFromResource(indexResource + COMMANDS_TOOLTIP_INDEX, info.tooltip); + cmdMap[i] = info; + std::transform(info.name.begin(), info.name.end(), info.name.begin(), ::toupper); + g_commandMappings[info.name] = indexResource; + i++; } +} +bool CUICmdList::UpdateCommandList(iCommandListCategory cmdCat) { m_pList_Cmds->ResetContent(); + const std::map * cmdMap = nullptr; + + switch (cmdCat) { + case CMD_LIST_PRIVATE: + cmdMap = &m_mCmd_Private; + break; + case CMD_LIST_TRADE: + cmdMap = &m_mCmd_Trade; + break; + case CMD_LIST_PARTY: + cmdMap = &m_mCmd_Party; + break; + case CMD_LIST_CLAN: + cmdMap = &m_mCmd_Clan; + break; + /* in ver 1298 enable this + case CMD_LIST_KNIGHTS: + cmdMap = &m_mCmd_Knights; + break; + case CMD_LIST_GUARDIAN: + cmdMap = &m_mCmd_Guard; + break; + case CMD_LIST_KING: + cmdMap = &m_mCmd_King; + break; +*/ + case CMD_LIST_GM - 3: // - 3 to disable CMD_LIST_KNIGHTS, CMD_LIST_GUARDIAN, CMD_LIST_KING -> in ver 1298 remove -3 + if (CGameBase::s_pPlayer->m_InfoBase.iAuthority == AUTHORITY_MANAGER) { + cmdMap = &m_mCmd_GM; + } + break; + } - int indexStart = cmdCat * 200 + 8000; //start index for correct loc in map - int indexEnd = indexStart + 100; //where to stop iterating - int i = 0; - - for (auto itr = m_mapCmds.begin(); itr != m_mapCmds.end(); ++itr) { - if (itr->first >= indexStart && itr->first < indexEnd) { - m_pList_Cmds->AddString(itr->second); - - CN3UIString * pChild = m_pList_Cmds->GetChildStrFromList(itr->second); - std::string cmdTip; - ::_LoadStringFromResource(itr->first + 100, cmdTip); - if (pChild != NULL) { - pChild->SetTooltipText(cmdTip.c_str()); - } - //SavvyNik tooltip is being loaded in but the rectangle - //that it shows on is too small. Need to figure out where - //this is being set. + if (cmdMap) { + for (const auto & cmdPair : *cmdMap) { + const CommandInfo & info = cmdPair.second; + char tooltipBuffer[256]; + sprintf_s(tooltipBuffer, sizeof(tooltipBuffer), info.tooltip.c_str(), info.name.c_str()); + m_pList_Cmds->AddStringTooltip(info.name, 0xFFC6C6FB, tooltipBuffer, 0xFF80FF80); } } + int rangeMax = m_pList_Cmds->GetCount() - MAX_VISIBLE_ITEMS; + m_pScroll_Commands->SetVisibleWithNoSound(rangeMax >= 0); + m_pScroll_Commands->SetRange(0, rangeMax); + return true; } -bool CUICmdListDlg::ReceiveMessage(CN3UIBase * pSender, DWORD dwMsg) { - if (NULL == pSender) { + +bool CUICmdList::ReceiveMessage(CN3UIBase * pSender, DWORD dwMsg) { + if (!pSender) { return false; } @@ -231,7 +294,8 @@ bool CUICmdListDlg::ReceiveMessage(CN3UIBase * pSender, DWORD dwMsg) { } } else if (dwMsg == UIMSG_LIST_SELCHANGE) { if (pSender == m_pList_CmdCat) { - uint8_t iSel = m_pList_CmdCat->GetCurSel(); + iCommandListCategory iSel = + static_cast(m_pList_CmdCat->GetCurSel() + COMMANDS_CATEGORY_NAMES_INDEX); UpdateCommandList(iSel); return true; } @@ -246,7 +310,7 @@ bool CUICmdListDlg::ReceiveMessage(CN3UIBase * pSender, DWORD dwMsg) { return false; } -void CUICmdListDlg::Render() { +void CUICmdList::Render() { if (!m_bVisible) { return; } @@ -254,30 +318,97 @@ void CUICmdListDlg::Render() { CN3UIBase::Render(); } -//this_ui_add_start -bool CUICmdListDlg::OnKeyPress(int iKey) { +bool CUICmdList::OnKeyPress(int iKey) { return CN3UIBase::OnKeyPress(iKey); } -void CUICmdListDlg::SetVisible(bool bVisible) { +void CUICmdList::SetVisible(bool bVisible) { CN3UIBase::SetVisible(bVisible); if (bVisible) { CGameProcedure::s_pUIMgr->SetVisibleFocusedUI(this); } else { - CGameProcedure::s_pUIMgr->ReFocusUI(); //this_ui + CGameProcedure::s_pUIMgr->ReFocusUI(); // this_ui } } -bool CUICmdListDlg::ExecuteCommand(uint8_t cmdSel) { +bool CUICmdList::ExecuteCommand(uint8_t cmdSel) { std::string command; m_pList_Cmds->GetString(cmdSel, command); - if (command == "PM") { - CGameProcedure::s_pProcMain->OpenCmdEdit(command); + switch (m_pList_CmdCat->GetCurSel() + COMMANDS_CATEGORY_NAMES_INDEX) { + case CMD_LIST_PRIVATE: + ProcessCommand_Private(command); + break; + case CMD_LIST_TRADE: + case CMD_LIST_PARTY: + case CMD_LIST_CLAN: + // case CMD_LIST_KNIGHTS: // -> in ver 1298 enable: CMD_LIST_KNIGHTS, CMD_LIST_GUARDIAN, CMD_LIST_KING + // case CMD_LIST_GUARDIAN: + command = '/' + command; + CGameProcedure::s_pProcMain->ParseChattingCommand(command); + break; + // case CMD_LIST_KING: + + // break; + case CMD_LIST_GM - 3: // - 3 to disable CMD_LIST_KNIGHTS, CMD_LIST_GUARDIAN, CMD_LIST_KING -> in ver 1298 remove -3 + ProcessCommand_GM(command); + break; + default: + break; } - command = '/' + command; - CGameProcedure::s_pProcMain->ParseChattingCommand(command); - return true; -} \ No newline at end of file +} + +void CUICmdList::ProcessCommand_Private(std::string command) { + int cmdSel = m_pList_Cmds->GetCurSel(); + + switch (cmdSel + COMMANDS_CATEGORY_PRIVATE_INDEX) { + case CMD_WHISPER: + CGameProcedure::s_pProcMain->OpenCmdEdit(command); + break; + case CMD_TOWN: + case CMD_EXIT: + case CMD_GREETING: + case CMD_GREETING2: + case CMD_GREETING3: + case CMD_PROVOKE: + case CMD_PROVOKE2: + case CMD_PROVOKE3: + case CMD_GAME_SAVE: + case CMD_RECOMMEND: + case CMD_INDIVIDUAL_BATTLE: + CGameProcedure::s_pProcMain->ParseChattingCommand('/' + command); + break; + } +} +void CUICmdList::ProcessCommand_GM(std::string command) { + int cmdSel = m_pList_Cmds->GetCurSel(); + + switch (cmdSel + COMMANDS_CATEGORY_GM_INDEX) { + case CMD_VISIBLE: + case CMD_CLEAN: + case CMD_RAINING: + case CMD_SNOWING: + case CMD_TIME: + case CMD_NOTICE: + case CMD_ARREST: + case CMD_FORBIDCONNECT: + case CMD_FORBIDCHAT: + case CMD_PERMITCHAT: + case CMD_NOTICEALL: + case CMD_FORBIDUSER: + case CMD_SUMMONUSER: + case CMD_ATTACKDISABLE: + case CMD_ATTACKENABLE: + CGameProcedure::s_pProcMain->OpenCmdEdit(command); + break; + case CMD_INVISIBLE: + case CMD_CU_COUNT: + case CMD_CUTOFF: + case CMD_VIEW: + case CMD_PLC: + CGameProcedure::s_pProcMain->ParseChattingCommand('/' + command); + break; + } +} diff --git a/src/game/UICmdList.h b/src/game/UICmdList.h index 627378ab..f266756b 100644 --- a/src/game/UICmdList.h +++ b/src/game/UICmdList.h @@ -10,51 +10,195 @@ #include "N3Base/N3UIEdit.h" ////////////////////////////////////////////////////////////////////// +const int MAX_VISIBLE_ITEMS = 15; +const int COMMANDS_CATEGORY_NAMES_INDEX = 7800; +const int COMMANDS_CATEGORY_TOOLTIP_INDEX = 7900; +const int COMMANDS_CATEGORY_PRIVATE_INDEX = 8000; +const int COMMANDS_CATEGORY_TRADE_INDEX = 8200; +const int COMMANDS_CATEGORY_PARTY_INDEX = 8400; +const int COMMANDS_CATEGORY_CLAN_INDEX = 8600; +const int COMMANDS_CATEGORY_KNIGHTS_INDEX = 8800; +const int COMMANDS_CATEGORY_GUARDIAN_INDEX = 9200; +const int COMMANDS_CATEGORY_KING_INDEX = 9400; +const int COMMANDS_CATEGORY_GM_INDEX = 9000; +const int COMMANDS_TOOLTIP_INDEX = 100; -class CUICmdListDlg : public CN3UIBase { +enum iCommandListCategory { + CMD_LIST_PRIVATE = IDS_CMD_CATEGORY_PRIVATE, + CMD_LIST_TRADE = IDS_CMD_CATEGORY_TRADE, + CMD_LIST_PARTY = IDS_CMD_CATEGORY_PARTY, + CMD_LIST_CLAN = IDS_CMD_CATEGORY_CLAN, + CMD_LIST_KNIGHTS = IDS_CMD_CATEGORY_KNIGHTS, + CMD_LIST_GUARDIAN = IDS_CMD_CATEGORY_GUARDIAN, + CMD_LIST_KING = IDS_CMD_CATEGORY_KING, + CMD_LIST_GM = IDS_CMD_CATEGORY_GM, + CMD_LIST_COUNT = 8 +}; + +enum iPrivateCommand { + CMD_WHISPER = IDS_CMD_WHISPER, + CMD_TOWN = IDS_CMD_TOWN, + CMD_EXIT = IDS_CMD_EXIT, + CMD_GREETING = IDS_CMD_GREETING, + CMD_GREETING2 = IDS_CMD_GREETING2, + CMD_GREETING3 = IDS_CMD_GREETING3, + CMD_PROVOKE = IDS_CMD_PROVOKE, + CMD_PROVOKE2 = IDS_CMD_PROVOKE2, + CMD_PROVOKE3 = IDS_CMD_PROVOKE3, + CMD_GAME_SAVE = IDS_CMD_GAME_SAVE, + CMD_RECOMMEND = IDS_CMD_RECOMMEND, + CMD_INDIVIDUAL_BATTLE = IDS_CMD_INDIVIDUAL_BATTLE, + CMD_PRIVATE_COUNT = 12 +}; + +enum iTradeCommand { + CMD_TRADE = IDS_CMD_TRADE, + CMD_FORBIDTRADE = IDS_CMD_FORBIDTRADE, + CMD_PERMITTRADE = IDS_CMD_PERMITTRADE, + CMD_MERCHANT = IDS_CMD_MERCHANT, + CMD_TRADE_COUNT = 5 +}; + +enum iPartyCommand { + CMD_PARTY = IDS_CMD_PARTY, + CMD_LEAVEPARTY = IDS_CMD_LEAVEPARTY, + CMD_RECRUITPARTY = IDS_CMD_RECRUITPARTY, + CMD_SEEKING_PARTY = IDS_CMD_SEEKING_PARTY, + CMD_FORBIDPARTY = IDS_CMD_FORBIDPARTY, + CMD_PERMITPARTY = IDS_CMD_PERMITPARTY, + CMD_PARTY_COUNT = 7 +}; + +enum iClanCommand { + CMD_JOINCLAN = IDS_CMD_JOINCLAN, + CMD_WITHDRAWCLAN = IDS_CMD_WITHDRAWCLAN, + CMD_FIRECLAN = IDS_CMD_FIRECLAN, + CMD_COMMAND = IDS_CMD_COMMAND, + CMD_CLAN_WAR = IDS_CMD_CLAN_WAR, + CMD_SURRENDER = IDS_CMD_SURRENDER, + CMD_APPOINTVICECHIEF = IDS_CMD_APPOINTVICECHIEF, + CMD_CLAN_CHAT = IDS_CMD_CLAN_CHAT, + CMD_CLAN_BATTLE = IDS_CMD_CLAN_BATTLE, + CMD_CLAN_COUNT = 10 +}; + +enum iKnightsCommand { + CMD_CONFEDERACY = IDS_CMD_CONFEDERACY, + CMD_BAN_KNIGHTS = IDS_CMD_BAN_KNIGHTS, + CMD_QUIT_KNIGHTS = IDS_CMD_QUIT_KNIGHTS, + CMD_BASE = IDS_CMD_BASE, + CMD_DECLARATION = IDS_CMD_DECLARATION, + CMD_KNGIHTS_COUNT = 6 +}; + +enum iGuardianCommand { + CMD_GUARD_HIDE = IDS_CMD_GUARD_HIDE, + CMD_GUARD = IDS_CMD_GUARD, + CMD_GUARD_DEFEND = IDS_CMD_GUARD_DEFEND, + CMD_GUARD_LOOK_OUT = IDS_CMD_GUARD_LOOK_OUT, + CMD_GUARD_FORMATION = IDS_CMD_GUARD_FORMATION, + CMD_GUARD_REST = IDS_CMD_GUARD_REST, + CMD_GUARD_DESTROY = IDS_CMD_GUARD_DESTROY, + CMD_GUARD_COUNT = 8 +}; +enum iKingCommand { + CMD_KING_ROYALORDER = IDS_CMD_KING_ROYALORDER, + CMD_KING_PRIZE = IDS_CMD_KING_PRIZE, + CMD_KING_EXPRATE = IDS_CMD_KING_EXPRATE, + CMD_KING_DROPRATE = IDS_CMD_KING_DROPRATE, + CMD_KING_RAIN = IDS_CMD_KING_RAIN, + CMD_KING_SNOW = IDS_CMD_KING_SNOW, + CMD_KING_CLEAR = IDS_CMD_KING_CLEAR, + CMD_KING_REWARD = IDS_CMD_KING_REWARD, + CMD_KING_COUNT = 9 +}; + +enum iGmCommand { + CMD_VISIBLE = IDS_CMD_VISIBLE, + CMD_INVISIBLE = IDS_CMD_INVISIBLE, + CMD_CLEAN = IDS_CMD_CLEAN, + CMD_RAINING = IDS_CMD_RAINING, + CMD_SNOWING = IDS_CMD_SNOWING, + CMD_TIME = IDS_CMD_TIME, + CMD_CU_COUNT = IDS_CMD_CU_COUNT, + CMD_NOTICE = IDS_CMD_NOTICE, + CMD_ARREST = IDS_CMD_ARREST, + CMD_FORBIDCONNECT = IDS_CMD_FORBIDCONNECT, + CMD_FORBIDCHAT = IDS_CMD_FORBIDCHAT, + CMD_PERMITCHAT = IDS_CMD_PERMITCHAT, + CMD_NOTICEALL = IDS_CMD_NOTICEALL, + CMD_CUTOFF = IDS_CMD_CUTOFF, + CMD_VIEW = IDS_CMD_VIEW, + CMD_UNVIEW = IDS_CMD_UNVIEW, + CMD_FORBIDUSER = IDS_CMD_FORBIDUSER, + CMD_SUMMONUSER = IDS_CMD_SUMMONUSER, + CMD_ATTACKDISABLE = IDS_CMD_ATTACKDISABLE, + CMD_ATTACKENABLE = IDS_CMD_ATTACKENABLE, + CMD_PLC = IDS_CMD_PLC, + CMD_GM_COUNT = 22 +}; + +class CUICmdList : public CN3UIBase { bool m_bDestoyDlgAlive; class CUICmdEdit * m_pUICmdEdit; CN3UIButton * m_pBtn_cancel; CN3UIList * m_pList_CmdCat; + CN3UIList * m_pList_CommandsPrivate; + CN3UIList * m_pList_CommandsTrade; + CN3UIList * m_pList_CommandsClan; + CN3UIList * m_pList_CommandsKnights; + CN3UIList * m_pList_CommandsParty; + CN3UIList * m_pList_CommandsGuardianMonster; + CN3UIList * m_pList_CommandsKing; + CN3UIList * m_pList_CommandsGM; CN3UIList * m_pList_Cmds; CN3UIScrollBar * m_pScroll_Categories; CN3UIScrollBar * m_pScroll_Commands; - protected: - bool m_bOpenningNow; - bool m_bClosingNow; - float m_fMoveDelta; - int m_iRBtnDownOffs; - bool m_bRBtnProcessing; - - enum iCmd { - CMD_LIST_PRIVATE, - CMD_LIST_TRADE, - CMD_LIST_PARTY, - CMD_LIST_CLAN, - CMD_LIST_KNIGHTS, - CMD_LIST_GUARDIAN, - CMD_LIST_KING, - CMD_LIST_GM + public: + struct CommandInfo { + std::string name; + std::string tooltip; }; - std::map m_mapCmds; + std::map m_mCmd_Private; + std::map m_mCmd_Trade; + std::map m_mCmd_Party; + std::map m_mCmd_Clan; + std::map m_mCmd_Knights; + std::map m_mCmd_Guard; + std::map m_mCmd_King; + std::map m_mCmd_GM; + std::map g_commandMappings; + + protected: + bool m_bOpenningNow; + bool m_bClosingNow; + float m_fMoveDelta; + int m_iRBtnDownOffs; + bool m_bRBtnProcessing; + std::string szGmCategory; + std::map m_CommandMap; public: - void SetVisible(bool bVisible); - - bool OnKeyPress(int iKey); - virtual void Release(); - virtual void Tick(); - virtual bool ReceiveMessage(CN3UIBase * pSender, DWORD dwMsg); - void Render(); - void Open(); - void Close(bool bByKey = false); - bool Load(HANDLE hFile); - bool CreateCategoryList(); - bool UpdateCommandList(uint8_t cmd); - bool ExecuteCommand(uint8_t cmdSel); - - CUICmdListDlg(); - virtual ~CUICmdListDlg(); + void SetVisible(bool bVisible) override; + + bool OnKeyPress(int iKey) override; + void Release() override; + void Tick() override; + bool ReceiveMessage(CN3UIBase * pSender, DWORD dwMsg) override; + void Render(); + void Open(); + void Close(bool bByKey = false); + bool Load(HANDLE hFile); + void InitCommands(); + bool CreateCategoryList(); + bool UpdateCommandList(iCommandListCategory cmd); + void LoadCommandMap(std::map & cmdMap, int startId, int endId); + bool ExecuteCommand(uint8_t cmdSel); + void ProcessCommand_Private(std::string command); + void ProcessCommand_GM(std::string command); + + CUICmdList(); + virtual ~CUICmdList(); }; diff --git a/src/game/res/Resource.h b/src/game/res/Resource.h index b71172fd..664011e3 100644 --- a/src/game/res/Resource.h +++ b/src/game/res/Resource.h @@ -442,34 +442,16 @@ #define IDS_WANT_PARTY_MEMBER 6123 #define IDS_SETTING_KARUS_SCREEN 6124 #define IDS_SETTING_ELMORAD_SCREEN 6125 -/* -#define IDS_CMD_WHISPER 6200 -#define IDS_CMD_TOWN 6201 -#define IDS_CMD_TRADE 6202 -#define IDS_CMD_EXIT 6203 -#define IDS_CMD_PARTY 6204 -#define IDS_CMD_LEAVEPARTY 6205 -#define IDS_CMD_RECRUITPARTY 6206 -#define IDS_CMD_JOINCLAN 6207 -#define IDS_CMD_WITHDRAWCLAN 6208 -#define IDS_CMD_FIRECLAN 6209 -#define IDS_CMD_APPOINTVICECHIEF 6210 -#define IDS_CMD_GREETING 6211 -#define IDS_CMD_EXCITE 6212 -#define IDS_CMD_VISIBLE 6213 -#define IDS_CMD_INVISIBLE 6214 -#define IDS_CMD_CLEAN 6215 -#define IDS_CMD_RAINING 6216 -#define IDS_CMD_SNOWING 6217 -#define IDS_CMD_TIME 6218 -#define IDS_CMD_CU_COUNT 6219 -#define IDS_CMD_NOTICE 6220 -#define IDS_CMD_ARREST 6221 -#define IDS_CMD_FORBIDCONNECT 6222 -#define IDS_CMD_FORBIDCHAT 6223 -#define IDS_CMD_PERMITCHAT 6224 -#define IDS_CMD_GAME_SAVE 6225 -*/ + +#define IDS_CMD_CATEGORY_PRIVATE 7800 +#define IDS_CMD_CATEGORY_TRADE 7801 +#define IDS_CMD_CATEGORY_PARTY 7802 +#define IDS_CMD_CATEGORY_CLAN 7803 +#define IDS_CMD_CATEGORY_KNIGHTS 7804 +#define IDS_CMD_CATEGORY_GUARDIAN 7805 +#define IDS_CMD_CATEGORY_KING 7806 +#define IDS_CMD_CATEGORY_GM 7807 + #define IDS_CMD_WHISPER 8000 #define IDS_CMD_TOWN 8001 #define IDS_CMD_EXIT 8002 @@ -536,6 +518,23 @@ #define IDS_CMD_ATTACKENABLE 9019 #define IDS_CMD_PLC 9020 +#define IDS_CMD_GUARD_HIDE 9200 +#define IDS_CMD_GUARD 9201 +#define IDS_CMD_GUARD_DEFEND 9202 +#define IDS_CMD_GUARD_LOOK_OUT 9203 +#define IDS_CMD_GUARD_FORMATION 9204 +#define IDS_CMD_GUARD_REST 9205 +#define IDS_CMD_GUARD_DESTROY 9206 + +#define IDS_CMD_KING_ROYALORDER 9400 +#define IDS_CMD_KING_PRIZE 9401 +#define IDS_CMD_KING_EXPRATE 9402 +#define IDS_CMD_KING_DROPRATE 9403 +#define IDS_CMD_KING_RAIN 9404 +#define IDS_CMD_KING_SNOW 9405 +#define IDS_CMD_KING_CLEAR 9406 +#define IDS_CMD_KING_REWARD 9407 + #define IDS_PARTY_BBS_REGISTER 6300 #define IDS_PARTY_BBS_REGISTER_CANCEL 6301 #define IDS_TRADE_BBS_SELL_REGISTER 6302 From 75b23d405f23528cfcf31eb92ea98e6c361d6024 Mon Sep 17 00:00:00 2001 From: Adrian Tracz Date: Mon, 26 Aug 2024 14:21:46 +0200 Subject: [PATCH 3/4] Add Whisper Chat Windows Functionality --- src/game/APISocket.h | 11 +- src/game/GameProcMain.cpp | 178 ++++++++- src/game/GameProcMain.h | 8 +- src/game/KnightOnLine.vcxproj | 4 + src/game/KnightOnLine.vcxproj.filters | 12 + src/game/UIChat.cpp | 80 ++++ src/game/UIChat.h | 21 + src/game/UIChatWhisperHide.cpp | 193 +++++++++ src/game/UIChatWhisperHide.h | 65 ++++ src/game/UIChatWhisperOpen.cpp | 538 ++++++++++++++++++++++++++ src/game/UIChatWhisperOpen.h | 101 +++++ src/game/res/Resource.h | 1 + src/server/Ebenezer/Define.h | 21 +- src/server/Ebenezer/User.cpp | 84 ++-- src/server/Ebenezer/User.h | 3 + 15 files changed, 1279 insertions(+), 41 deletions(-) create mode 100644 src/game/UIChatWhisperHide.cpp create mode 100644 src/game/UIChatWhisperHide.h create mode 100644 src/game/UIChatWhisperOpen.cpp create mode 100644 src/game/UIChatWhisperOpen.h diff --git a/src/game/APISocket.h b/src/game/APISocket.h index a72b360b..bb78392f 100644 --- a/src/game/APISocket.h +++ b/src/game/APISocket.h @@ -261,7 +261,12 @@ class CAPISocket { //패킷 만들기 함수 static void MP_AddByte(BYTE * dest, int & iOffset, BYTE byte) { CopyMemory(dest + iOffset, &byte, 1); - iOffset++; + iOffset++; + } + + static void MP_AddUInt8(BYTE * dest, int & iOffset, uint8_t value) { + CopyMemory(dest + iOffset, &value, sizeof(uint8_t)); + iOffset += sizeof(uint8_t); } static void MP_AddShort(BYTE * dest, int & iOffset, short value) { CopyMemory(dest + iOffset, &value, 2); @@ -316,6 +321,10 @@ class CAPISocket { iOffset += 8; return *(__int64 *)(buf + iOffset - 8); } + static uint8_t Parse_GetUInt8(const BYTE * buf, int & iOffset) { + iOffset += 1; + return *(const uint8_t *)(buf + iOffset - 1); + } CAPISocket(); virtual ~CAPISocket(); diff --git a/src/game/GameProcMain.cpp b/src/game/GameProcMain.cpp index 95e92e99..d8b8f666 100644 --- a/src/game/GameProcMain.cpp +++ b/src/game/GameProcMain.cpp @@ -60,6 +60,8 @@ #include "UIDead.h" #include "UIRookieTip.h" #include "UIExitMenu.h" +#include "UIChatWhisperOpen.h" +#include "UIChatWhisperHide.h" #include "SubProcPerTrade.h" #include "CountableItemEditDlg.h" @@ -198,6 +200,8 @@ CGameProcMain::~CGameProcMain() { delete m_pTargetSymbol; // 플레이어가 타겟으로 잡은 캐릭터의 위치위에 그리면 된다.. delete m_pLightMgr; + delete m_pUIChatWhiserOpen; + delete m_pUIChatWhiserHide; } void CGameProcMain::Release() { @@ -953,16 +957,29 @@ bool CGameProcMain::ProcessPacket(DataPack * pDataPack, int & iOffset) { int iLen = CAPISocket::Parse_GetShort(pDataPack->m_pData, iOffset); // ID 문자열 길이.. CAPISocket::Parse_GetString(pDataPack->m_pData, iOffset, szID, iLen); // ID 문자열.. - e_ChatMode eCM = N3_CHAT_UNKNOWN; - if (szID.empty()) { + e_ChatMode eCM = N3_CHAT_UNKNOWN; + + if (iLen == -1) { // User has blocked private messages + ::_LoadStringFromResource(IDS_USER_HAS_BLOCKED_WHISPER, szMsg); + eCM = N3_CHAT_NORMAL; + this->MsgOutput(szMsg, 0xffffff00); + + } else if (szID.empty()) { // Failed connect to chat ::_LoadStringFromResource(IDS_CHAT_SELECT_TARGET_FAIL, szMsg); eCM = N3_CHAT_NORMAL; - } else { - ::_LoadStringFromResource(IDS_CHAT_SELECT_TARGET_SUCCESS, szMsg); - eCM = N3_CHAT_PRIVATE; - } + this->MsgOutput(szMsg, 0xffffff00); - this->MsgOutput(szID + szMsg, 0xffffff00); + } else if (szID.length() > 0) { //Connected to the private chat + if (CGameBase::s_pPlayer->m_InfoBase.szID != szID) { + eCM = N3_CHAT_PRIVATE; + auto it = m_pUIChatDlg->whisperWindows.find(szID); + if (it == m_pUIChatDlg->whisperWindows.end()) { + ::_LoadStringFromResource(IDS_CHAT_SELECT_TARGET_SUCCESS, szMsg); + this->MsgOutput(szMsg, 0xffffff00); + } + CGameProcedure::s_pProcMain->MsgSend_Whisper(szID); + } + } m_pUIChatDlg->ChangeChattingMode(eCM); // 자동으로 귓속말 모드로 바꾸어 준다.. } return true; @@ -1475,6 +1492,7 @@ void CGameProcMain::MsgSend_ChatSelectTarget(const std::string & szTargetID) { BYTE byBuff[32]; CAPISocket::MP_AddByte(byBuff, iOffset, N3_CHAT_SELECT_TARGET); + CAPISocket::MP_AddUInt8(byBuff, iOffset, 1); CAPISocket::MP_AddShort(byBuff, iOffset, (short)szTargetID.size()); CAPISocket::MP_AddString(byBuff, iOffset, szTargetID); @@ -2086,6 +2104,16 @@ bool CGameProcMain::MsgRecv_Chat(DataPack * pDataPack, int & iOffset) { int iChatLen = CAPISocket::Parse_GetShort(pDataPack->m_pData, iOffset); // 채팅 문자열 길이.. CAPISocket::Parse_GetString(pDataPack->m_pData, iOffset, szChat, iChatLen); + int iTmp = szChat.find(' '); + string pTalker; + + if (iID != s_pPlayer->IDNumber()) { + pTalker = szChat.substr(0, iTmp); + } else { + pTalker = s_pPlayer->IDString(); + } + + if (eCM == N3_CHAT_CONTINUE_DELETE) { //지속 공지 삭제... m_pUIChatDlg->DeleteContinueMsg(); return true; @@ -2100,7 +2128,12 @@ bool CGameProcMain::MsgRecv_Chat(DataPack * pDataPack, int & iOffset) { crChat = D3DCOLOR_ARGB(255, 255, 255, 255); break; case N3_CHAT_PRIVATE: - crChat = D3DCOLOR_ARGB(255, 192, 192, 0); + if (CGameBase::s_pPlayer->IDString() == pTalker) { + crChat = D3DCOLOR_ARGB(255, 128, 255, 255); + } else { + crChat = D3DCOLOR_ARGB(255, 192, 192, 0); + break; + } break; case N3_CHAT_PARTY: crChat = D3DCOLOR_ARGB(255, 0, 192, 192); @@ -2172,10 +2205,49 @@ bool CGameProcMain::MsgRecv_Chat(DataPack * pDataPack, int & iOffset) { (N3_CHAT_NORMAL == eCM || N3_CHAT_SHOUT == eCM)) { // 보통 채팅 혹은 외치기일때만.. pBPC->BalloonStringSet(szChat, crChat); } + if (eCM == N3_CHAT_PRIVATE) { + std::string szText = (iTmp > 0) ? szChat.substr(iTmp + 3, szChat.length()) : szChat; + + e_Nation eNation = pBPC->m_InfoBase.eNation; + __TABLE_UI_RESRC * pTbl = s_pTbl_UI->Find(eNation); + + // + if (pTalker == s_pPlayer->IDString()) { // Send to myself + + if (!m_pUIChatDlg->whisperTarget.empty()) { + + auto it = m_pUIChatDlg->whisperWindows.find(m_pUIChatDlg->whisperTarget); + if (it == m_pUIChatDlg->whisperWindows.end()) { + m_pUIChatDlg->InitializeWhisperWindows(m_pUIChatDlg->whisperTarget, true); + } + + m_pUIChatDlg->whisperWindows[m_pUIChatDlg->whisperTarget].Open->AddChatMsg(szText, crChat); + } + } else { // Send to other player + + auto it = m_pUIChatDlg->whisperWindows.find(pTalker); + if (it != m_pUIChatDlg->whisperWindows.end()) { + + } else { + int whisperCount = m_pUIChatDlg->whisperWindows.size(); + auto [posX, posY] = m_pUIChatDlg->CalculateWhisperPosition(whisperCount); + + m_pUIChatDlg->InitializeWhisperWindows(pTalker, false); + m_pUIChatDlg->whisperWindows[pTalker].Hide->SetPos(posX, posY); + } - // 채팅창에 넣기.. - m_pUIChatDlg->AddChatMsg(eCM, szChat, crChat); + if(m_pUIChatDlg->whisperWindows[pTalker].Hide->IsVisible()) { + m_pUIChatDlg->whisperWindows[pTalker].messageNotRead = true; + m_pUIChatDlg->whisperWindows[pTalker].Hide->m_messageNotRead = true; + } + m_pUIChatDlg->whisperWindows[pTalker].Open->AddChatMsg(szText, crChat); + } + } else { + // Put it in the chat window.. + m_pUIChatDlg->AddChatMsg(eCM, szChat, crChat); + } + return true; } @@ -4787,6 +4859,68 @@ void CGameProcMain::CommandExitMenu() { } } +bool CGameProcMain::WhisperOpen(std::string szTargetWhisperName, POINT pos) { + if (m_pUIChatDlg->whisperWindows.find(szTargetWhisperName) == m_pUIChatDlg->whisperWindows.end()) { + e_Nation eNation = s_pPlayer->m_InfoBase.eNation; + __TABLE_UI_RESRC * pTbl = s_pTbl_UI->Find(eNation); + + m_pUIChatDlg->InitializeWhisperWindows(szTargetWhisperName, true); + } + + if (pos.x == NULL && pos.y == NULL) { + m_pUIChatDlg->whisperWindows[szTargetWhisperName].Open->SetPos(100, CN3Base::s_CameraData.vp.Height - 400); + } else { + m_pUIChatDlg->whisperWindows[szTargetWhisperName].Open->SetPos(pos.x, pos.y); + } + + m_pUIChatDlg->whisperWindows[szTargetWhisperName].Open->SetState(UI_STATE_COMMON_NONE); + m_pUIChatDlg->whisperWindows[szTargetWhisperName].Open->Open(szTargetWhisperName); + s_pUIMgr->SetFocusedUI(m_pUIChatDlg->whisperWindows[szTargetWhisperName].Open); + m_pUIChatDlg->whisperWindows[szTargetWhisperName].Open->SetFocus(); + + return true; +} + +bool CGameProcMain::WhisperHide(std::string szTargetWhisperName, POINT pos) { + auto & whisperWindows = m_pUIChatDlg->whisperWindows; + auto it = whisperWindows.find(szTargetWhisperName); + + if (m_pUIChatDlg->GetEnableKillFocus()) { + m_pUIChatDlg->SetEnableKillFocus(false); + m_pUIChatDlg->KillFocus(); + } + m_pUIChatDlg->KillFocus(); + + if (it != whisperWindows.end()) { + + it->second.Hide->SetPos(pos.x, pos.y); + it->second.Hide->SetVisible(true); + it->second.Hide->SetState(UI_STATE_COMMON_NONE); + + it->second.Hide->Open(szTargetWhisperName); + it->second.Open->KillFocus(); + it->second.Open->SetEnableKillFocus(false); + it->second.Hide->KillFocus(); + it->second.Hide->SetEnableKillFocus(false); + s_pUIMgr->ReFocusUI(); + + return true; + } + + return false; +} + +void CGameProcMain::MsgSend_Whisper(std::string szTargetWhisperName) { + m_pUIChatDlg->whisperTarget = szTargetWhisperName; + + POINT pos; + pos.x = NULL; + pos.y = NULL; + + CGameProcMain::WhisperOpen(szTargetWhisperName, pos); + return; +} + void CGameProcMain::MsgOutput(const std::string & szMsg, D3DCOLOR crMsg) { m_pUIMsgDlg->AddMsg(szMsg, crMsg); } @@ -5575,7 +5709,7 @@ void CGameProcMain::ParseChattingCommand(const std::string & szCmd) { if (m_pUIStateBarAndMiniMap) { m_pUIStateBarAndMiniMap->SetSystemTimeVisibility(false); } - } + } int eCmd = -1; @@ -7724,7 +7858,7 @@ bool CGameProcMain::OnMouseRbtnDown(POINT ptCur, POINT ptPrev) { if (fRotY || fRotX) { SetGameCursor(NULL); - POINT ptToScreen{ptPrev.x, ptPrev.y}; + POINT ptToScreen{ ptPrev.x, ptPrev.y }; ::ClientToScreen(s_hWndBase, &ptToScreen); ::SetCursorPos(ptToScreen.x, ptToScreen.y); s_pLocalInput->MouseSetPos(ptPrev.x, ptPrev.y); @@ -7745,17 +7879,33 @@ bool CGameProcMain::OnMouseRDBtnPress(POINT ptCur, POINT ptPrev) { } void CGameProcMain::ProcessUIKeyInput(bool bEnable) { + auto it = m_pUIChatDlg->whisperWindows.find(m_pUIChatDlg->whisperTarget); + if (m_pUIChatDlg && !m_pUIChatDlg->IsChatMode()) { CGameProcedure::ProcessUIKeyInput(); if (s_pLocalInput->IsKeyPress(DIK_RETURN) && !s_bKeyPress) { - m_pUIChatDlg->SetFocus(); + if (m_pUIChatDlg->whisperTarget.empty()) { + m_pUIChatDlg->SetFocus(); + } + else { + if (it != m_pUIChatDlg->whisperWindows.end()) { + m_pUIChatDlg->whisperWindows[m_pUIChatDlg->whisperTarget].Open->SetFocus(); + } + } } - } else if (m_pUIChatDlg && m_pUIChatDlg->IsChatMode()) { + } + else if (m_pUIChatDlg && m_pUIChatDlg->IsChatMode()) { s_bKeyPress = false; if (m_pUIChatDlg->GetEnableKillFocus()) { m_pUIChatDlg->SetEnableKillFocus(false); m_pUIChatDlg->KillFocus(); } + if (!m_pUIChatDlg->whisperTarget.empty() && it != m_pUIChatDlg->whisperWindows.end()) { + if(m_pUIChatDlg->whisperWindows[m_pUIChatDlg->whisperTarget].Open->GetEnableKillFocus()){ + m_pUIChatDlg->whisperWindows[m_pUIChatDlg->whisperTarget].Open->SetEnableKillFocus(false); + m_pUIChatDlg->whisperWindows[m_pUIChatDlg->whisperTarget].Open->KillFocus(); + } + } } } diff --git a/src/game/GameProcMain.h b/src/game/GameProcMain.h index 5f1f8d67..534aa270 100644 --- a/src/game/GameProcMain.h +++ b/src/game/GameProcMain.h @@ -7,6 +7,7 @@ #include "GameProcedure.h" #include + typedef typename std::set::iterator it_ID; typedef std::pair pair_ID; @@ -24,10 +25,12 @@ class CGameProcMain : public CGameProcedure { class CUIInventory * m_pUIInventory; // 인벤토리 class CUIVarious * m_pUIVar; // 캐릭터 상태창, 기사단 관리 등이 페이지로 들어간 다용도 UI class CUIChat * m_pUIChatDlg; // 채팅 입출력 대화상자.. + class CUIChatWhisperOpen * m_pUIChatWhiserOpen; + class CUIChatWhisperHide * m_pUIChatWhiserHide; class CUIMessageWnd * m_pUIMsgDlg; // 게임 메시지 출력 상자. class CUIStateBar * m_pUIStateBarAndMiniMap; // mp,hp,exp, minimap.... class CUICmd * m_pUICmd; // 왼쪽 하단의 명령버튼 창.. - class CUICmdEdit * m_pUICmdList; + class CUICmdList * m_pUICmdList; class CUICmdEdit * m_pUICmdEditDlg; class CUITargetBar * m_pUITargetBar; // 타겟 상태창.. class CUITransactionDlg * m_pUITransactionDlg; @@ -244,6 +247,8 @@ class CGameProcMain : public CGameProcedure { void CommandCameraChange(); // 카메라 시점 바꾸기.. void CommandExitMenu(); void CommandSitDown(bool bLimitInterval, bool bSitDown, bool bImmediately = false); + bool WhisperOpen(std::string szTargetWhisperName, POINT pos); + bool WhisperHide(std::string szTargetWhisperName, POINT pos); void CommandTargetSelect_NearstEnemy(); // 가장 가까운 적 타겟 잡기.. void CommandTargetSelect_NearstOurForce(); // 가장 가까운 파티 타겟잡기.. @@ -264,6 +269,7 @@ class CGameProcMain : public CGameProcedure { void MsgSend_Rotation(); // 서버에게 회전 패킷을 날린다.. void MsgSend_Chat(enum e_ChatMode eMode, const std::string & szChat); // 서버에게 채팅 메시지를 날린다.. void MsgSend_ChatSelectTarget(const std::string & szTargetID); // 일대일 채팅 상대 정하기. + void MsgSend_Whisper(std::string szTargetWhisperName); void MsgSend_Regen(); bool MsgSend_RequestItemBundleOpen(CPlayerNPC * pCorpse); // 아이템 상자를 열거나 시체를 뒤진다.. void MsgSend_RequestTargetHP(short siIDTarget, diff --git a/src/game/KnightOnLine.vcxproj b/src/game/KnightOnLine.vcxproj index 44ff4187..c30f569b 100644 --- a/src/game/KnightOnLine.vcxproj +++ b/src/game/KnightOnLine.vcxproj @@ -255,6 +255,7 @@ + @@ -322,6 +323,7 @@ + @@ -512,7 +514,9 @@ + + diff --git a/src/game/KnightOnLine.vcxproj.filters b/src/game/KnightOnLine.vcxproj.filters index af99826c..1667a694 100644 --- a/src/game/KnightOnLine.vcxproj.filters +++ b/src/game/KnightOnLine.vcxproj.filters @@ -652,6 +652,12 @@ Procedure - Main\UI + + Procedure - Main\UI + + + Procedure - Main\UI + @@ -1175,6 +1181,12 @@ Procedure - Main\UI + + Procedure - Main\UI + + + Procedure - Main\UI + diff --git a/src/game/UIChat.cpp b/src/game/UIChat.cpp index de6bcabe..86da2ccc 100644 --- a/src/game/UIChat.cpp +++ b/src/game/UIChat.cpp @@ -6,6 +6,7 @@ #include "UIChat.h" #include "PacketDef.h" #include "GameProcMain.h" +#include "PlayerMySelf.h" #include "UIMessageWnd.h" #include "UIManager.h" @@ -45,6 +46,8 @@ CUIChat::CUIChat() //생성자 와 파괴자에서 Release안 불러 주나?? m_bChatParty = true; m_bKillFocus = false; + + whisperTarget = ""; } CUIChat::~CUIChat() { @@ -78,6 +81,18 @@ CUIChat::~CUIChat() { // } DeleteContinueMsg(); + whisperTarget = ""; + for (auto & pair : whisperWindows) { + if (pair.second.Open) { + delete pair.second.Open; + pair.second.Open = nullptr; + } + if (pair.second.Hide) { + delete pair.second.Hide; + pair.second.Hide = nullptr; + } + } + whisperWindows.clear(); } void CUIChat::Release() { @@ -835,3 +850,68 @@ void CUIChat::SetNoticeTitle(const std::string & szString, D3DCOLOR color) { m_pNoticeTitle->SetColor(color); } } + +void CUIChat::InitializeWhisperWindows(const std::string & nickname, bool isSender) +{ + e_Nation eNation = CGameBase::s_pPlayer->m_InfoBase.eNation; + __TABLE_UI_RESRC * pTbl = CGameProcedure::s_pProcMain->s_pTbl_UI->Find(eNation); + + ChatWhisperWindows & window = whisperWindows[nickname]; + + window.Open = new CUIChatWhisperOpen(); + window.Open->Init(CGameProcedure::s_pUIMgr); + window.Open->LoadFromFile(pTbl->szWhisper_open); + window.Open->SetPos(100, CN3Base::s_CameraData.vp.Height - 400); + window.Open->SetVisible(isSender); + if (isSender) { + window.Open->Open(nickname); + window.Open->SetFocus(); + } + + window.Hide = new CUIChatWhisperHide(); + window.Hide->Init(CGameProcedure::s_pUIMgr); + window.Hide->LoadFromFile(pTbl->szWhisper_close); + window.Hide->SetVisible(!isSender); + if (!isSender) { + window.Hide->Open(nickname); + } +} +bool CUIChat::deleteWhisperWinodws(const std::string & nickname) { + auto it = whisperWindows.find(nickname); + if (it != whisperWindows.end()) { + if (it->second.Open != nullptr) { + delete it->second.Open; + it->second.Open = nullptr; + } + if (it->second.Hide != nullptr) { + delete it->second.Hide; + it->second.Hide = nullptr; + } + + whisperWindows.erase(it); + return true; + } + + return false; +} + +std::pair CUIChat::CalculateWhisperPosition(int activeWhisperWindowsCount) { + int posX = 100; + int baseY = CN3Base::s_CameraData.vp.Height - 400; + int chatY = activeWhisperWindowsCount; + + if (activeWhisperWindowsCount > 7 && activeWhisperWindowsCount <= 14) { + posX = 248; + chatY = 8 - activeWhisperWindowsCount; + } else if (activeWhisperWindowsCount > 14 && activeWhisperWindowsCount <= 21) { + posX = 396; + chatY = 15 - activeWhisperWindowsCount; + } else if (activeWhisperWindowsCount > 21 && activeWhisperWindowsCount <= 28) { + posX = 544; + chatY = 22 - activeWhisperWindowsCount; + } else if (activeWhisperWindowsCount > 28) { + chatY = 0; + } + + return {posX, baseY + chatY * 23}; +} diff --git a/src/game/UIChat.h b/src/game/UIChat.h index b1c822ef..53082757 100644 --- a/src/game/UIChat.h +++ b/src/game/UIChat.h @@ -5,6 +5,8 @@ #pragma once #include "N3Base/N3UIBase.h" +#include "UIChatWhisperOpen.h" +#include "UIChatWhisperHide.h" #include //enum e_ChatBuffer { CHAT_BUFFER_NORMAL = 0, CHAT_BUFFER_PRIVATE, CHAT_BUFFER_PARTY, CHAT_BUFFER_KNIGHTS, CHAT_BUFFER_COUNT }; @@ -20,6 +22,17 @@ struct __ChatInfo { } }; +struct ChatWhisperWindows { + CUIChatWhisperOpen* Open; + CUIChatWhisperHide* Hide; + bool messageNotRead; + + ChatWhisperWindows() + : Open(nullptr) + , Hide(nullptr) + , messageNotRead(false) {} +}; + typedef deque<__ChatInfo *> ChatList; typedef ChatList::iterator ChatListItor; typedef ChatList::reverse_iterator ChatListReverseItor; @@ -61,6 +74,11 @@ class CUIChat : public CN3UIBase { bool m_bChatParty; bool m_bKillFocus; + + public: + std::unordered_map whisperWindows; + std::string whisperTarget; + // e_ChatBuffer m_eChatBuffer; // 채팅 표시 모드 .. 버퍼가 나누어져있다.. /* @@ -105,6 +123,9 @@ class CUIChat : public CN3UIBase { D3DCOLOR color = 0xffffffff); // 채팅 메세지를 저장하고 알맞은 형태로 화면에 출력해준다. void AddContinueMsg(e_ChatMode eCM, const std::string & szString, D3DCOLOR color = 0xffffffff); void AdjustScroll(); // 스크롤 위치등 조정.. + void InitializeWhisperWindows(const std::string & nickname, bool isSender); + std::pair CalculateWhisperPosition(int activeWhisperWindowsCount); + bool deleteWhisperWinodws(const std::string & nickname); BOOL IsChatMode(); void SetFocus(); diff --git a/src/game/UIChatWhisperHide.cpp b/src/game/UIChatWhisperHide.cpp new file mode 100644 index 00000000..db4d07cb --- /dev/null +++ b/src/game/UIChatWhisperHide.cpp @@ -0,0 +1,193 @@ +// UIChat.cpp: implementation of the CUIChat class. +// +////////////////////////////////////////////////////////////////////// + +#include "StdAfx.h" +#include "UIChatWhisperHide.h" +#include "UIChatWhisperOpen.h" +#include "PacketDef.h" +#include "GameProcMain.h" +#include "UIMessageWnd.h" +#include "UIManager.h" + +#include "N3Base/N3UIString.h" +#include "N3Base/N3UIScrollBar.h" +#include "N3Base/N3UIEdit.h" //son, chat_in + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +CUIChatWhisperHide::CUIChatWhisperHide() { +} + +CUIChatWhisperHide::~CUIChatWhisperHide() {} + +void CUIChatWhisperHide::Release() { + CN3UIBase::Release(); + + m_pText_UserName = NULL; + m_pBtn_close = NULL; +} + +void CUIChatWhisperHide::Open(string userName) { + SetVisible(true); + m_pText_UserName->SetString(userName); + + return; +} + +bool CUIChatWhisperHide::ReceiveMessage(CN3UIBase * pSender, DWORD dwMsg) { + if (NULL == pSender) { + return false; + } + + else if (dwMsg == UIMSG_BUTTON_CLICK) { + if (pSender->m_szID == "btn_open") { + SetVisible(false); + POINT chatPosition = GetPos(); + m_messageNotRead = false; + CGameProcedure::s_pProcMain->WhisperOpen(m_pText_UserName->GetString(), chatPosition); + } + + } + //son, chat_in + else if (dwMsg == UIMSG_EDIT_RETURN) { + CN3UIEdit * pEdit = (CN3UIEdit *)pSender; + + } else { + SetState(UI_STATE_COMMON_MOVE); + } + //son, chat_in + + return true; +} + +bool CUIChatWhisperHide::Load(HANDLE hFile) { + if (false == CN3UIBase::Load(hFile)) { + return false; + } + + m_pText_UserName = (CN3UIString *)GetChildByID("exit_id"); + __ASSERT(m_pText_UserName, "NULL UI Component!!"); + + m_pBtn_open = (CN3UIButton *)GetChildByID("btn_open"); + __ASSERT(m_pBtn_open, "NULL UI Component!!"); + + m_pBtn_bar = (CN3UIButton *)GetChildByID("btn_bar"); + __ASSERT(m_pBtn_bar, "NULL UI Component!!"); + + return true; +} + + +void CUIChatWhisperHide::Render() { + if (!m_bVisible) { + return; + } + + DWORD dwTime = GetTickCount(); + + if (m_messageNotRead) { + if (((dwTime / 1000) & 1) == 1) { + GetChildByID("btn_bar")->SetState(UI_STATE_BUTTON_ON); + } else { + GetChildByID("btn_bar")->SetState(UI_STATE_BUTTON_NORMAL); + } + + } else { + GetChildByID("btn_bar")->SetState(UI_STATE_BUTTON_NORMAL); + } + + CN3UIBase::Render(); +} + +//son, chat_in +void CUIChatWhisperHide::SetFocus() { + SetEnableKillFocus(false); + this->SetString(""); + if (m_pEdit) { + m_pEdit->SetFocus(); + } +} + +void CUIChatWhisperHide::KillFocus() { + this->SetString(""); + if (m_pEdit) { + m_pEdit->KillFocus(); + } +} + +void CUIChatWhisperHide::SetString(const std::string & szChat) { + m_szString = szChat; + if (m_pEdit) { + m_pEdit->SetString(m_szString); + m_pEdit->SetCaretPos(m_szString.size()); + } +} + +void CUIChatWhisperHide::SetCaretPos(int iPos) { + /* + if (IsChatMode() && m_pEdit) + { + m_pEdit->SetCaretPos(iPos); + } + */ +} + +BOOL CUIChatWhisperHide::MoveOffset(int iOffsetX, int iOffsetY) { + if (0 == iOffsetX && 0 == iOffsetY) { + return FALSE; + } + // ui żµżŞ + m_rcRegion.left += iOffsetX; + m_rcRegion.top += iOffsetY; + m_rcRegion.right += iOffsetX; + m_rcRegion.bottom += iOffsetY; + + // movable żµżŞ + m_rcMovable.left += iOffsetX; + m_rcMovable.top += iOffsetY; + m_rcMovable.right += iOffsetX; + m_rcMovable.bottom += iOffsetY; + + // children ÁÂÇĄ °»˝Ĺ + CN3UIBase * pCUI = NULL; // Child UI... + for (UIListItor itor = m_Children.begin(); m_Children.end() != itor; ++itor) { + pCUI = (*itor); + __ASSERT(pCUI, "child UI pointer is NULL!"); + pCUI->MoveOffset(iOffsetX, iOffsetY); + } + + return TRUE; +} + +void CUIChatWhisperHide::SetRegion(const RECT & Rect) { + CN3UIBase::SetRegion(Rect); +} + +void CUIChatWhisperHide::SetNewMessageAnimation(bool animationActivated) { + if (animationActivated) { + static float fTime; + static float fTimePrevFps = CN3Base::TimeGet(); + if (fTime > fTimePrevFps + 0.5f) { + fTimePrevFps = fTime; + } + } +} + +bool CUIChatWhisperHide::OnKeyPress(int iKey) { + switch (iKey) { + case DIK_ESCAPE: { //hotkey°ˇ Ć÷Äż˝ş ŔâÇôŔÖŔ»¶§´Â ´Ů¸Ą ui¸¦ ´ÝŔ»Ľö ľřŔ¸ąÇ·Î DIK_ESCAPE°ˇ µéľîżŔ¸é Ć÷Äż˝ş¸¦ ´Ů˝ĂŔâ°í + //ż­·ÁŔÖ´Â ´Ů¸Ą ŔŻľĆŔ̸¦ ´ÝľĆÁŘ´Ů. + CGameProcedure::s_pUIMgr->ReFocusUI(); //this_ui + CN3UIBase * pFocus = CGameProcedure::s_pUIMgr->GetFocusedUI(); + if (pFocus && pFocus != this) { + pFocus->OnKeyPress(iKey); + } + } + return true; + } + + return CN3UIBase::OnKeyPress(iKey); +} diff --git a/src/game/UIChatWhisperHide.h b/src/game/UIChatWhisperHide.h new file mode 100644 index 00000000..de7ac519 --- /dev/null +++ b/src/game/UIChatWhisperHide.h @@ -0,0 +1,65 @@ +// UIChatWhisperHide.h: interface for the CUIChat class. +// +////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "N3Base/N3UIBase.h" +#include + +class CUIChatWhisperHide : public CN3UIBase { + public: + static class CGameProcCharacterSelect * s_pProcCharacterSelect; + + protected: + int m_iCurContinueMsg; + CN3UIString * m_pNoticeTitle; + CN3UIString * + m_pChatOut; + CN3UIScrollBar * m_pScrollbar; + int m_iChatLineCount; + RECT m_rcChatOutRegion; + CN3UIString ** m_ppUILines; + + CN3UIEdit * m_pEdit; //son, chat_in + std::string m_szString; //son, chat_in + + CN3UIString * m_pText_UserName; + CN3UIButton * m_pBtn_close; + CN3UIButton * m_pBtn_open; + CN3UIButton * m_pBtn_bar; + + bool m_bKillFocus; + + // Operations + public: + void ShowContinueMsg(); + void DeleteContinueMsg(); + bool OnKeyPress(int iKey); + bool GetEnableKillFocus() { return m_bKillFocus; } + void SetEnableKillFocus(bool bKillFocus) { m_bKillFocus = bKillFocus; } + void ChatListenEnable(); + void SetNewMessageAnimation(bool animationActivated = true); + virtual BOOL MoveOffset(int iOffsetX, int iOffsetY); + virtual bool ReceiveMessage(CN3UIBase * pSender, DWORD dwMsg); + virtual void Release(); + virtual bool Load(HANDLE hFile); + virtual void SetRegion( + const RECT & + Rect); + + void SetString(const std::string & szChat); + void SetCaretPos(int iPos); + const std::string & GetString() const { return m_szString; } + void Open(string userName); + void Render(); + + bool m_messageNotRead; + + BOOL IsChatMode(); + void SetFocus(); + void KillFocus(); + + CUIChatWhisperHide(); + virtual ~CUIChatWhisperHide(); +}; diff --git a/src/game/UIChatWhisperOpen.cpp b/src/game/UIChatWhisperOpen.cpp new file mode 100644 index 00000000..fe04992b --- /dev/null +++ b/src/game/UIChatWhisperOpen.cpp @@ -0,0 +1,538 @@ +// UIWhisperOpen.cpp: implementation of the CUIWhisperOpen class. +// GuTeK +////////////////////////////////////////////////////////////////////// + +#include "StdAfx.h" +#include "UIChatWhisperOpen.h" +#include "UIChatWhisperHide.h" +#include "UIChat.h" +#include "PacketDef.h" +#include "GameProcMain.h" +#include "UIManager.h" + +#include "N3Base/N3UIString.h" +#include "N3Base/N3UIScrollBar.h" +#include "N3Base/N3UIEdit.h" //son, chat_in +#include "N3Base/N3UIList.h" //son, chat_in + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +CUIChatWhisperOpen::CUIChatWhisperOpen() { + + if (m_ppUILines) { delete[] m_ppUILines; m_ppUILines = NULL; } + + ChatListPmItor itor; + for (itor = m_ChatBuffer.begin(); m_ChatBuffer.end() != itor; ++itor) + { + __WhisperMessage * pChatInfo = (*itor); + if (pChatInfo) delete pChatInfo; + } + m_ChatBuffer.clear(); + + for (itor = m_LineBuffer.begin(); m_LineBuffer.end() != itor; ++itor) + { + __WhisperMessage * pChatInfo = (*itor); + if (pChatInfo) delete pChatInfo; + } + m_LineBuffer.clear(); + + + DeleteContinueMsg(); + +} + +CUIChatWhisperOpen::~CUIChatWhisperOpen() { +} + +void CUIChatWhisperOpen::Release() { + CN3UIBase::Release(); + + //m_pText_UserName = NULL; + m_pBtn_Close = NULL; +} + +bool CUIChatWhisperOpen::Load(HANDLE hFile) { + if (false == CN3UIBase::Load(hFile)) { + return false; + } + + m_pText_UserName = (CN3UIString *)GetChildByID("exit_id"); + __ASSERT(m_pText_UserName, "NULL UI Component!!"); + + m_pBtn_Close = (CN3UIButton *)GetChildByID("btn_close"); + __ASSERT(m_pBtn_Close, "NULL UI Component!!"); + m_pBtn_Hide = (CN3UIButton *)GetChildByID("btn_hide"); + __ASSERT(m_pBtn_Hide, "NULL UI Component!!"); + m_pBtn_Chat = GetChildByID("btn_chat"); + __ASSERT(m_pBtn_Chat, "NULL UI Component!!"); + + m_pScrollbar = (CN3UIScrollBar *)GetChildByID("scroll"); + __ASSERT(m_pScrollbar, "NULL UI Component!!"); + + m_pMessage_Text = (CN3UIEdit *)GetChildByID("edit_chat"); + __ASSERT(m_pMessage_Text, "NULL UI Component!!"); + m_pMessage_Text->SetMaxString(256); + + m_pMessages_List = (CN3UIString *)GetChildByID("exit_chat"); + __ASSERT(m_pMessages_List, "NULL UI Component!!"); + + m_rcChatOutRegion = m_pMessages_List->GetRegion(); + + CreateLines(); + + return true; +} + +void CUIChatWhisperOpen::Open(string userName) { + m_pText_UserName->SetString(userName); + m_pMessage_Text->SetMaxString(512); + SetVisible(true); + CGameProcedure::s_pProcMain->m_pUIChatDlg->ChangeChattingMode(N3_CHAT_PRIVATE); + return; +} + +bool CUIChatWhisperOpen::ReceiveMessage(CN3UIBase * pSender, DWORD dwMsg) { + if (NULL == pSender) { + return false; + } + + if (dwMsg == UIMSG_SCROLLBAR_POS) { + int iCurLinePos = m_pScrollbar->GetCurrentPos(); + SetTopLine(iCurLinePos); + } else if (dwMsg == UIMSG_BUTTON_CLICK) { + POINT chatPosition = GetPos(); + + if (pSender->m_szID == "btn_close") { + SetVisible(false); + KillFocus(); + CGameProcedure::s_pUIMgr->ReFocusUI(); + CGameProcedure::s_pProcMain->m_pUIChatDlg->whisperTarget = ""; + CGameProcedure::s_pProcMain->m_pUIChatDlg->ChangeChattingMode(N3_CHAT_NORMAL); + return CGameProcedure::s_pProcMain->m_pUIChatDlg->deleteWhisperWinodws(m_pText_UserName->GetString()); + + } else if (pSender->m_szID == "btn_hide") { + + SetEnableKillFocus(false); + KillFocus(); + CGameProcedure::s_pProcMain->m_pUIChatDlg->KillFocus(); + CGameProcedure::s_pProcMain->m_pUIChatDlg->ChangeChattingMode(N3_CHAT_NORMAL); + + CGameProcedure::s_pUIMgr->ReFocusUI(); + SetVisible(false); + CGameProcedure::s_pProcMain->m_pUIChatDlg->whisperTarget = ""; + + auto it = CGameProcedure::s_pProcMain->m_pUIChatDlg->whisperWindows.find(m_pText_UserName->GetString()); + if (it != CGameProcedure::s_pProcMain->m_pUIChatDlg->whisperWindows.end()) { + CGameProcedure::s_pProcMain->m_pUIChatDlg->whisperWindows[m_pText_UserName->GetString()] + .messageNotRead = false; + + } + + CGameProcedure::s_pProcMain->WhisperHide(m_pText_UserName->GetString(), chatPosition); + } + + } else if (dwMsg == UI_MOUSE_LBCLICK && (pSender->m_szID == "btn_bar" || pSender->m_szID == "exit_id")) { + SetState(UI_STATE_COMMON_MOVE); + } else if (dwMsg == UI_MOUSE_LBCLICK && pSender->m_szID == "edit_chat"){ + + CGameProcedure::s_pProcMain->m_pUIChatDlg->whisperTarget = m_pText_UserName->GetString(); + + + } else if (dwMsg == UIMSG_EDIT_RETURN) { + CN3UIEdit * m_pBtn_message = (CN3UIEdit *)pSender; + + m_szString = m_pBtn_message->GetString(); + int iStrLen = m_szString.size(); + if (iStrLen > 0) { + CGameProcedure::s_pProcMain->MsgSend_ChatSelectTarget(m_pText_UserName->GetString()); + CGameProcedure::s_pProcMain->m_pUIChatDlg->whisperTarget = m_pText_UserName->GetString(); + CGameProcedure::s_pProcMain->MsgSend_Chat(N3_CHAT_PRIVATE, m_szString.c_str()); + + m_pBtn_message->SetString(""); + } + + SetEnableKillFocus(true); + } + + return true; +} + +void CUIChatWhisperOpen::AddLineBuffer(const std::string & szString, D3DCOLOR color) { + if (szString.empty()) { + return; + } + + const int iStrLen = szString.size(); + SIZE size; + if (FALSE == m_pMessages_List->GetTextExtent(szString, iStrLen, &size)) { + __ASSERT(0, "no device context"); + return; + } + + const int iRegionWidth = m_rcChatOutRegion.right - m_rcChatOutRegion.left; + + int iCX = 0; + int iCount = 0; + int iLineStart = 0; + + while (iCount < iStrLen) { + if ('\n' == szString[iCount]) // \n + { + __WhisperMessage * pLineInfo = new __WhisperMessage; + m_LineBuffer.push_back(pLineInfo); + + pLineInfo->color = color; + if ((iCount - iLineStart) > 0) { + int iLineLength = iCount - iLineStart + 1; + std::string szLine; + pLineInfo->szChat = szString.substr(iLineStart, iLineLength); + } + + ++iCount; + iLineStart = iCount; + iCX = 0; + } else { + int iCC = 0; + if (0x80 & szString[iCount]) { + iCC = 2; // 2BYTE + } else { + iCC = 1; // 1BYTE + } + + BOOL bFlag = m_pMessages_List->GetTextExtent(&(szString[iCount]), iCC, &size); + __ASSERT(bFlag, "cannot get size of dfont"); + if ((iCX + size.cx) > iRegionWidth) + { + int iLineLength = iCount - iLineStart; + if (iLineLength > 0) { + __WhisperMessage * pLineInfo = new __WhisperMessage; + m_LineBuffer.push_back(pLineInfo); + + pLineInfo->color = color; + pLineInfo->szChat = szString.substr(iLineStart, iLineLength); + } else { + __ASSERT(iRegionWidth > 15, "The region is too narrow to print even a single character"); + break; + } + iLineStart = iCount; + iCX = 0; + } + iCount += iCC; + iCX += size.cx; + } + } + + int iLineLength = iStrLen - iLineStart; + if (iLineLength > 0) { + __WhisperMessage * pLineInfo = new __WhisperMessage; + m_LineBuffer.push_back(pLineInfo); + + pLineInfo->color = color; + pLineInfo->szChat = szString.substr(iLineStart, iLineLength); + } +} +void CUIChatWhisperOpen::AddChatMsg(const std::string & szString, D3DCOLOR color) { + if (szString.empty()) { + return; + } + __WhisperMessage * pChatInfo = new __WhisperMessage(szString, color); + m_ChatBuffer.push_back(pChatInfo); + + if (m_ChatBuffer.size() > 255) { + __WhisperMessage * pTemp = m_ChatBuffer.front(); + if (pTemp) { + delete pTemp; + } + + m_ChatBuffer.pop_front(); + } + + this->AddLineBuffer(szString, color); + this->AdjustScroll(); +} + +void CUIChatWhisperOpen::CreateLines() { + if (m_ppUILines) { + for (int i = 0; i < m_iChatLineCount; ++i) { + if (m_ppUILines[i]) { + delete m_ppUILines[i]; + m_ppUILines[i] = NULL; + } + } + delete[] m_ppUILines; + m_ppUILines = NULL; + } + SIZE size; + if (m_pMessages_List && m_pMessages_List->GetTextExtent("M", lstrlen("M"), &size) && size.cy > 0) { // The letter 'M' is used for measuring text width because it's typically the widest character, providing a better estimate of the maximum text width. + m_iChatLineCount = (m_rcChatOutRegion.bottom - m_rcChatOutRegion.top) / size.cy; + } else { + return; + } + const std::string & szFontName = m_pMessages_List->GetFontName(); + DWORD dwFontHeight = m_pMessages_List->GetFontHeight(); + DWORD dwFontFlag = m_pMessages_List->GetFontFlags(); + + if (m_iChatLineCount <= 0 || szFontName.empty()) { + return; + } + + m_ppUILines = new CN3UIString *[m_iChatLineCount]; + for (int i = 0; i < m_iChatLineCount; ++i) { + RECT rc; + SetRect(&rc, m_rcChatOutRegion.left, m_rcChatOutRegion.top + (i * size.cy), m_rcChatOutRegion.right, + m_rcChatOutRegion.top + ((i + 1) * size.cy)); + m_ppUILines[i] = new CN3UIString(); + m_ppUILines[i]->Init(this); + m_ppUILines[i]->SetRegion(rc); + m_ppUILines[i]->SetStyle(UISTYLE_STRING_SINGLELINE | UISTYLE_STRING_ALIGNLEFT | UISTYLE_STRING_ALIGNTOP); + m_ppUILines[i]->SetFont(szFontName, dwFontHeight, dwFontFlag & D3DFONT_BOLD, dwFontFlag & D3DFONT_ITALIC); + } +} + +void CUIChatWhisperOpen::AdjustScroll() { + int iCurLinePos = m_pScrollbar->GetCurrentPos(); + BOOL bAutoScroll = (m_pScrollbar->GetMaxPos() == iCurLinePos) ? TRUE : FALSE; + + while ( + m_LineBuffer.size() > MAX_CHAT_LINES_PM && + 0 < iCurLinePos) + { + __WhisperMessage * pTemp = m_LineBuffer.front(); + if (pTemp) { + delete pTemp; + } + m_LineBuffer.pop_front(); + --iCurLinePos; + } + + int iLineBufferSize = m_LineBuffer.size(); + int iMaxScrollPos = iLineBufferSize - m_iChatLineCount; + if (iMaxScrollPos < 0) { + iMaxScrollPos = 0; + } + m_pScrollbar->SetRange(0, iMaxScrollPos); + + if (bAutoScroll) { + iCurLinePos = iMaxScrollPos; + } + if (iCurLinePos < 0) { + iCurLinePos = 0; + } + + m_pScrollbar->SetCurrentPos(iCurLinePos); + + SetTopLine(iCurLinePos); +} + +void CUIChatWhisperOpen::Render() { + if (m_pMessage_Text->HaveFocus()) { + m_pBtn_Chat->SetState(UI_STATE_BUTTON_DOWN); + } else { + m_pBtn_Chat->SetState(UI_STATE_BUTTON_NORMAL); + } + + if (!m_bVisible) { + return; + } + + CN3UIBase::Render(); +} + +void CUIChatWhisperOpen::SetTopLine(int iTopLine) { + if (m_iChatLineCount <= 0) { + return; + } + + const int iLineBufferSize = m_LineBuffer.size(); + if (iTopLine < 0) { + iTopLine = 0; + } else if (iTopLine > iLineBufferSize) { + iTopLine = iLineBufferSize; + } + + __WhisperMessage ** ppLineInfos = new __WhisperMessage *[m_iChatLineCount]; + ZeroMemory(ppLineInfos, sizeof(__WhisperMessage *) * m_iChatLineCount); + + int i, iCurLine = 0; + for (i = 0; i < m_iChatLineCount; ++i) { + iCurLine = iTopLine + i; + if (iLineBufferSize <= iCurLine) { + break; + } + ppLineInfos[i] = m_LineBuffer[iCurLine]; + } + + __ASSERT(m_ppUILines, "null pointer"); + int iRealLine = i; + int iRealLineCount = 0; + for (int i = 0; i < iRealLine; ++i) { + ++iRealLineCount; + if (NULL == m_ppUILines[i]) { + continue; + } + m_ppUILines[i]->SetColor(ppLineInfos[i]->color); + m_ppUILines[i]->SetString(ppLineInfos[i]->szChat); + } + for (int i = iRealLineCount; i < m_iChatLineCount; ++i) { + if (NULL == m_ppUILines[i]) { + continue; + } + m_ppUILines[i]->SetString(""); + } + delete[] ppLineInfos; +} + +void CUIChatWhisperOpen::RecalcLineBuffers() { + int iMaxScrollPos = 0; + ChatListPmItor itor; + for (itor = m_LineBuffer.begin(); m_LineBuffer.end() != itor; ++itor) { + __WhisperMessage * pLineBuff = (*itor); + if (pLineBuff) { + delete pLineBuff; + } + } + + m_LineBuffer.clear(); + + for (itor = m_ChatBuffer.begin(); m_ChatBuffer.end() != itor; ++itor) { + __WhisperMessage * pChatBuff = (*itor); + if (pChatBuff) { + AddLineBuffer(pChatBuff->szChat, pChatBuff->color); + } + } + + while (m_LineBuffer.size() > MAX_CHAT_LINES_PM) + { + __WhisperMessage * pLineBuff = m_ChatBuffer.front(); + if (pLineBuff) { + delete pLineBuff; + } + + m_LineBuffer.pop_front(); + } + + int iLineBufferSize = m_LineBuffer.size(); + iMaxScrollPos = iLineBufferSize - m_iChatLineCount; + + if (iMaxScrollPos < 0) { + iMaxScrollPos = 0; + } + m_pScrollbar->SetRange(0, iMaxScrollPos); + m_pScrollbar->SetCurrentPos(iMaxScrollPos); + + SetTopLine(iMaxScrollPos); +} + +//son, chat_in +void CUIChatWhisperOpen::SetFocus() { + SetEnableKillFocus(false); + this->SetString(""); + if (m_pMessage_Text) { + m_pMessage_Text->SetFocus(); + } +} + +void CUIChatWhisperOpen::KillFocus() { + this->SetString(""); + if (m_pMessage_Text) { + m_pMessage_Text->KillFocus(); + } +} + +BOOL CUIChatWhisperOpen::IsChatMode() { + return ((m_pMessage_Text && GetFocusedEdit() == m_pMessage_Text) ? TRUE : FALSE); +} +//son, chat_in + +void CUIChatWhisperOpen::SetString(const std::string & szChat) { + m_szString = szChat; + if (m_pMessage_Text) { + m_pMessage_Text->SetString(m_szString); + m_pMessage_Text->SetCaretPos(m_szString.size()); + } +} + +void CUIChatWhisperOpen::SetCaretPos(int iPos) { + if (IsChatMode() && m_pMessage_Text) { + m_pMessage_Text->SetCaretPos(iPos); + } +} + +BOOL CUIChatWhisperOpen::MoveOffset(int iOffsetX, int iOffsetY) { + if (0 == iOffsetX && 0 == iOffsetY) { + return FALSE; + } + m_rcRegion.left += iOffsetX; + m_rcRegion.top += iOffsetY; + m_rcRegion.right += iOffsetX; + m_rcRegion.bottom += iOffsetY; + + m_rcMovable.left += iOffsetX; + m_rcMovable.top += iOffsetY; + m_rcMovable.right += iOffsetX; + m_rcMovable.bottom += iOffsetY; + + CN3UIBase * pCUI = NULL; + for (UIListItor itor = m_Children.begin(); m_Children.end() != itor; ++itor) { + pCUI = (*itor); + __ASSERT(pCUI, "child UI pointer is NULL!"); + pCUI->MoveOffset(iOffsetX, iOffsetY); + } + + + return TRUE; +} + +void CUIChatWhisperOpen::SetRegion(const RECT & Rect) { + CN3UIBase::SetRegion(Rect); +} + +void CUIChatWhisperOpen::DeleteContinueMsg() { + m_iCurContinueMsg = 0; + + ChatListPmItor itor; + for (itor = m_ContinueMsg.begin(); m_ContinueMsg.end() != itor; ++itor) { + __WhisperMessage * pChatInfo = (*itor); + if (pChatInfo) { + delete pChatInfo; + } + } + m_ContinueMsg.clear(); +} + +void CUIChatWhisperOpen::ShowContinueMsg() { + int iSize = m_ContinueMsg.size(); + if (m_iCurContinueMsg > iSize) { + m_iCurContinueMsg = 0; + } + + int iCnt = 0; + ChatListPmItor itor; + for (itor = m_ContinueMsg.begin(); m_ContinueMsg.end() != itor; ++itor) { + if (iCnt == m_iCurContinueMsg) { + m_iCurContinueMsg++; + __WhisperMessage * pChatInfo = (*itor); + if (pChatInfo) { + AddChatMsg(pChatInfo->szChat, pChatInfo->color); + } + } + } +} + +bool CUIChatWhisperOpen::OnKeyPress(int iKey) { + switch (iKey) { + case DIK_ESCAPE: { + CGameProcedure::s_pUIMgr->ReFocusUI(); //this_ui + CN3UIBase * pFocus = CGameProcedure::s_pUIMgr->GetFocusedUI(); + if (pFocus && pFocus != this) { + pFocus->OnKeyPress(iKey); + } + } + return true; + } + + return CN3UIBase::OnKeyPress(iKey); +} + diff --git a/src/game/UIChatWhisperOpen.h b/src/game/UIChatWhisperOpen.h new file mode 100644 index 00000000..2d82daec --- /dev/null +++ b/src/game/UIChatWhisperOpen.h @@ -0,0 +1,101 @@ +// UIChat.h: interface for the CUIChat class. +// +////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "N3Base/N3UIBase.h" +#include + +struct __WhisperMessage { + std::string szChat; + D3DCOLOR color; + + __WhisperMessage(){}; + __WhisperMessage(const std::string & szChat_Arg, D3DCOLOR color_Arg) { + szChat = szChat_Arg; + color = color_Arg; + } +}; + +typedef deque<__WhisperMessage *> ChatListPm; +typedef ChatListPm::iterator ChatListPmItor; +typedef ChatListPm::reverse_iterator ChatListPmReverseItor; + +const int MAX_CHAT_LINES_PM = 100; + +class CUIChatWhisperOpen : public CN3UIBase { + protected: + ChatListPm m_ChatBuffer; + ChatListPm m_LineBuffer; + ChatListPm m_ContinueMsg; + int m_iCurContinueMsg; + + CN3UIString * m_pNoticeTitle; + CN3UIString * + m_pChatOut; + CN3UIScrollBar * m_pScrollbar; + int m_iChatLineCount; + RECT m_rcChatOutRegion; + CN3UIString ** m_ppUILines; + + CN3UIEdit * m_pMessage_Text; + CN3UIString * m_pMessages_List; + + CN3UIEdit * m_pEdit; //son, chat_in + std::string m_szString; //son, chat_in + + CN3UIString * m_pText_UserName; + CN3UIButton * m_pBtn_Close; + CN3UIButton * m_pBtn_Hide; + CN3UIBase * m_pBtn_Chat; + + enum e_ChatMode m_eChatMode; + + bool m_bChatNormal; + bool m_bChatPrivate; + bool m_bChatClan; + bool m_bChatShout; + bool m_bChatParty; + + bool m_bKillFocus; + + protected: + void SetTopLine(int iTopLine); + void AddLineBuffer(const std::string & szString, + D3DCOLOR color); + void RecalcLineBuffers(); + void CreateLines(); + + // Operations + public: + void ShowContinueMsg(); + void DeleteContinueMsg(); + bool OnKeyPress(int iKey); + bool GetEnableKillFocus() { return m_bKillFocus; } + void SetEnableKillFocus(bool bKillFocus) { m_bKillFocus = bKillFocus; } + virtual BOOL MoveOffset(int iOffsetX, int iOffsetY); + virtual bool ReceiveMessage(CN3UIBase * pSender, DWORD dwMsg); + virtual void Release(); + virtual bool Load(HANDLE hFile); + virtual void SetRegion( + const RECT & + Rect); + + void SetString(const std::string & szChat); + void SetCaretPos(int iPos); + const std::string & GetString() const { return m_szString; } //son, chat_in + void AddChatMsg(const std::string & szString, + D3DCOLOR color = 0xffffffff); + void AddContinueMsg(e_ChatMode eCM, const std::string & szString, D3DCOLOR color = 0xffffffff); + void AdjustScroll(); + void Open(string userName); + void Render(); + + BOOL IsChatMode(); + void SetFocus(); + void KillFocus(); + + CUIChatWhisperOpen(); + virtual ~CUIChatWhisperOpen(); +}; diff --git a/src/game/res/Resource.h b/src/game/res/Resource.h index 664011e3..db519038 100644 --- a/src/game/res/Resource.h +++ b/src/game/res/Resource.h @@ -443,6 +443,7 @@ #define IDS_SETTING_KARUS_SCREEN 6124 #define IDS_SETTING_ELMORAD_SCREEN 6125 +#define IDS_USER_HAS_BLOCKED_WHISPER 7636 #define IDS_CMD_CATEGORY_PRIVATE 7800 #define IDS_CMD_CATEGORY_TRADE 7801 #define IDS_CMD_CATEGORY_PARTY 7802 diff --git a/src/server/Ebenezer/Define.h b/src/server/Ebenezer/Define.h index 11d3907d..b374f112 100644 --- a/src/server/Ebenezer/Define.h +++ b/src/server/Ebenezer/Define.h @@ -341,7 +341,11 @@ inline BYTE GetByte(char * sBuf, int & index) { index++; return (BYTE)(*(sBuf + t_index)); }; - +inline uint8_t GetUInt8(char * sBuf, int & index) { + uint8_t value = *(reinterpret_cast(sBuf + index)); + index += 1; + return value; +} inline int GetShort(char * sBuf, int & index) { index += 2; return *(short *)(sBuf + index - 2); @@ -378,7 +382,12 @@ inline void SetShort(char * tBuf, int sShort, int & index) { CopyMemory(tBuf + index, &temp, 2); index += 2; }; +inline void SetUInt8(char * tBuf, uint8_t sUInt8, int & index) { + uint8_t temp = (short)sUInt8; + CopyMemory(tBuf + index, &temp, 1); + index += 1; +}; inline void SetDWORD(char * tBuf, DWORD sDWORD, int & index) { CopyMemory(tBuf + index, &sDWORD, 4); index += 4; @@ -541,3 +550,13 @@ inline void TimeTrace(TCHAR * pMsg) { time.GetHour(), time.GetMinute()); TRACE(szMsg); }; + +enum ChatTargetStatus { + USER_NOT_FOUND = 0, + USER_BLOCKS_CHAT = -1, + USER_FOUND = 1 +}; +enum MessageType : uint8_t { + CHAT_TARGET_SELECT = 1, + BLOCK_CHAT = 2, +}; diff --git a/src/server/Ebenezer/User.cpp b/src/server/Ebenezer/User.cpp index 9fc43a83..edaba854 100644 --- a/src/server/Ebenezer/User.cpp +++ b/src/server/Ebenezer/User.cpp @@ -104,6 +104,7 @@ void CUser::Initialize() { m_sExchangeUser = -1; m_bExchangeOK = 0x00; m_sPrivateChatUser = -1; + m_bBlockPrivateChat = 0; m_bNeedParty = 0x01; m_fHPLastTimeNormal = 0.0f; // For Automatic HP recovery. @@ -6432,37 +6433,72 @@ BOOL CUser::ItemEquipAvailable(_ITEM_TABLE * pTable) { } void CUser::ChatTargetSelect(char * pBuf) { - int index = 0, send_index = 0, idlen = 0; - CUser * pUser = NULL; - char chatid[MAX_ID_SIZE + 1]; - memset(chatid, 0x00, MAX_ID_SIZE + 1); - char send_buff[128]; - memset(send_buff, 0x00, 128); + char targetUserID[MAX_ID_SIZE + 1] = {0}; + char packetBuffer[128] = {0}; - idlen = GetShort(pBuf, index); - if (idlen > MAX_ID_SIZE || idlen < 0) { - return; - } - GetString(chatid, pBuf, idlen, index); - int i; - for (i = 0; i < MAX_USER; i++) { - pUser = (CUser *)m_pMain->m_Iocport.m_SockArray[i]; - if (pUser && pUser->GetState() == STATE_GAMESTART) { - if (_strnicmp(chatid, pUser->m_pUserData->m_id, MAX_ID_SIZE) == 0) { - m_sPrivateChatUser = i; + int bufferIndex = 0; + int packetIndex = 0; + + uint8_t messageType = GetUInt8(pBuf, bufferIndex); + + switch (messageType) { + case CHAT_TARGET_SELECT: { + int targetUserIDLength = GetShort(pBuf, bufferIndex); + if (targetUserIDLength <= 0 || targetUserIDLength > MAX_ID_SIZE) { + return; + } + + GetString(targetUserID, pBuf, targetUserIDLength, bufferIndex); + + CUser * targetUser = nullptr; + ChatTargetStatus chatStatus = USER_NOT_FOUND; + + for (int i = 0; i < MAX_USER; i++) { + targetUser = static_cast(m_pMain->m_Iocport.m_SockArray[i]); + if (targetUser && targetUser->GetState() == STATE_GAMESTART && + _strnicmp(targetUserID, targetUser->m_pUserData->m_id, MAX_ID_SIZE) == 0) { + if (targetUser->isBlockingPrivateChat()) { + chatStatus = USER_BLOCKS_CHAT; + } else { + m_sPrivateChatUser = i; + chatStatus = USER_FOUND; + } break; } } + + SetByte(packetBuffer, WIZ_CHAT_TARGET, packetIndex); + + switch (chatStatus) { + case USER_NOT_FOUND: + SetShort(packetBuffer, 0, packetIndex); + break; + + case USER_BLOCKS_CHAT: + SetShort(packetBuffer, -1, packetIndex); + break; + + case USER_FOUND: + int userIDLength = strlen(targetUser->m_pUserData->m_id); + SetShort(packetBuffer, userIDLength, packetIndex); + SetString(packetBuffer, targetUser->m_pUserData->m_id, userIDLength, packetIndex); + break; + } + break; } - SetByte(send_buff, WIZ_CHAT_TARGET, send_index); - if (i == MAX_USER) { - SetShort(send_buff, 0, send_index); - } else { - SetShort(send_buff, strlen(chatid), send_index); - SetString(send_buff, chatid, strlen(chatid), send_index); + case BLOCK_CHAT: { + uint8_t blockWhisperStatus = GetUInt8(pBuf, bufferIndex); + if (blockWhisperStatus == 0 || blockWhisperStatus == 1) { + m_bBlockPrivateChat = blockWhisperStatus; + } + break; } - Send(send_buff, send_index); + default: + break; + } + + Send(packetBuffer, packetIndex); } // AI server에 User정보를 전부 전송... diff --git a/src/server/Ebenezer/User.h b/src/server/Ebenezer/User.h index 8641c32c..54523a7b 100644 --- a/src/server/Ebenezer/User.h +++ b/src/server/Ebenezer/User.h @@ -97,7 +97,9 @@ class CUser : public CIOCPSocket2 { ItemList m_ExchangeItemList; _ITEM_DATA m_MirrorItem[HAVE_MAX]; // 교환시 백업 아이템 리스트를 쓴다. + //Private chat short m_sPrivateChatUser; + BOOL m_bBlockPrivateChat; float m_fHPLastTimeNormal; // For Automatic HP recovery. float m_fHPStartTimeNormal; @@ -257,6 +259,7 @@ class CUser : public CIOCPSocket2 { void FriendAccept(char * pBuf); void FriendRequest(char * pBuf); void Friend(char * pBuf); + BOOL isBlockingPrivateChat() { return m_bBlockPrivateChat; } BOOL WarpListObjectEvent(short objectindex, short nid); BOOL FlagObjectEvent(short objectindex, short nid); BOOL GateLeverObjectEvent(short objectindex, short nid); From 5b505915ea5150546585b7f187afbb3bc7853b4d Mon Sep 17 00:00:00 2001 From: Adrian Tracz Date: Mon, 26 Aug 2024 15:58:01 +0200 Subject: [PATCH 4/4] Clang format --- src/game/APISocket.h | 2 +- src/game/GameProcMain.cpp | 34 +++++++--------- src/game/GameProcMain.h | 19 +++++---- src/game/UIChat.cpp | 9 ++--- src/game/UIChat.h | 8 ++-- src/game/UIChatWhisperHide.cpp | 4 +- src/game/UIChatWhisperHide.h | 37 ++++++++--------- src/game/UIChatWhisperOpen.cpp | 72 +++++++++++++++------------------- src/game/UIChatWhisperOpen.h | 47 ++++++++++------------ src/game/res/Resource.h | 16 ++++---- src/server/Ebenezer/User.cpp | 18 ++++----- 11 files changed, 120 insertions(+), 146 deletions(-) diff --git a/src/game/APISocket.h b/src/game/APISocket.h index bb78392f..e1e5385a 100644 --- a/src/game/APISocket.h +++ b/src/game/APISocket.h @@ -261,7 +261,7 @@ class CAPISocket { //패킷 만들기 함수 static void MP_AddByte(BYTE * dest, int & iOffset, BYTE byte) { CopyMemory(dest + iOffset, &byte, 1); - iOffset++; + iOffset++; } static void MP_AddUInt8(BYTE * dest, int & iOffset, uint8_t value) { diff --git a/src/game/GameProcMain.cpp b/src/game/GameProcMain.cpp index d8b8f666..93bee40e 100644 --- a/src/game/GameProcMain.cpp +++ b/src/game/GameProcMain.cpp @@ -957,7 +957,7 @@ bool CGameProcMain::ProcessPacket(DataPack * pDataPack, int & iOffset) { int iLen = CAPISocket::Parse_GetShort(pDataPack->m_pData, iOffset); // ID 문자열 길이.. CAPISocket::Parse_GetString(pDataPack->m_pData, iOffset, szID, iLen); // ID 문자열.. - e_ChatMode eCM = N3_CHAT_UNKNOWN; + e_ChatMode eCM = N3_CHAT_UNKNOWN; if (iLen == -1) { // User has blocked private messages ::_LoadStringFromResource(IDS_USER_HAS_BLOCKED_WHISPER, szMsg); @@ -976,7 +976,7 @@ bool CGameProcMain::ProcessPacket(DataPack * pDataPack, int & iOffset) { if (it == m_pUIChatDlg->whisperWindows.end()) { ::_LoadStringFromResource(IDS_CHAT_SELECT_TARGET_SUCCESS, szMsg); this->MsgOutput(szMsg, 0xffffff00); - } + } CGameProcedure::s_pProcMain->MsgSend_Whisper(szID); } } @@ -2113,7 +2113,6 @@ bool CGameProcMain::MsgRecv_Chat(DataPack * pDataPack, int & iOffset) { pTalker = s_pPlayer->IDString(); } - if (eCM == N3_CHAT_CONTINUE_DELETE) { //지속 공지 삭제... m_pUIChatDlg->DeleteContinueMsg(); return true; @@ -2205,7 +2204,7 @@ bool CGameProcMain::MsgRecv_Chat(DataPack * pDataPack, int & iOffset) { (N3_CHAT_NORMAL == eCM || N3_CHAT_SHOUT == eCM)) { // 보통 채팅 혹은 외치기일때만.. pBPC->BalloonStringSet(szChat, crChat); } - if (eCM == N3_CHAT_PRIVATE) { + if (eCM == N3_CHAT_PRIVATE) { std::string szText = (iTmp > 0) ? szChat.substr(iTmp + 3, szChat.length()) : szChat; e_Nation eNation = pBPC->m_InfoBase.eNation; @@ -2215,7 +2214,6 @@ bool CGameProcMain::MsgRecv_Chat(DataPack * pDataPack, int & iOffset) { if (pTalker == s_pPlayer->IDString()) { // Send to myself if (!m_pUIChatDlg->whisperTarget.empty()) { - auto it = m_pUIChatDlg->whisperWindows.find(m_pUIChatDlg->whisperTarget); if (it == m_pUIChatDlg->whisperWindows.end()) { m_pUIChatDlg->InitializeWhisperWindows(m_pUIChatDlg->whisperTarget, true); @@ -2227,7 +2225,6 @@ bool CGameProcMain::MsgRecv_Chat(DataPack * pDataPack, int & iOffset) { auto it = m_pUIChatDlg->whisperWindows.find(pTalker); if (it != m_pUIChatDlg->whisperWindows.end()) { - } else { int whisperCount = m_pUIChatDlg->whisperWindows.size(); auto [posX, posY] = m_pUIChatDlg->CalculateWhisperPosition(whisperCount); @@ -2236,7 +2233,7 @@ bool CGameProcMain::MsgRecv_Chat(DataPack * pDataPack, int & iOffset) { m_pUIChatDlg->whisperWindows[pTalker].Hide->SetPos(posX, posY); } - if(m_pUIChatDlg->whisperWindows[pTalker].Hide->IsVisible()) { + if (m_pUIChatDlg->whisperWindows[pTalker].Hide->IsVisible()) { m_pUIChatDlg->whisperWindows[pTalker].messageNotRead = true; m_pUIChatDlg->whisperWindows[pTalker].Hide->m_messageNotRead = true; } @@ -2247,7 +2244,7 @@ bool CGameProcMain::MsgRecv_Chat(DataPack * pDataPack, int & iOffset) { // Put it in the chat window.. m_pUIChatDlg->AddChatMsg(eCM, szChat, crChat); } - + return true; } @@ -4892,7 +4889,6 @@ bool CGameProcMain::WhisperHide(std::string szTargetWhisperName, POINT pos) { m_pUIChatDlg->KillFocus(); if (it != whisperWindows.end()) { - it->second.Hide->SetPos(pos.x, pos.y); it->second.Hide->SetVisible(true); it->second.Hide->SetState(UI_STATE_COMMON_NONE); @@ -4904,10 +4900,10 @@ bool CGameProcMain::WhisperHide(std::string szTargetWhisperName, POINT pos) { it->second.Hide->SetEnableKillFocus(false); s_pUIMgr->ReFocusUI(); - return true; + return true; } - return false; + return false; } void CGameProcMain::MsgSend_Whisper(std::string szTargetWhisperName) { @@ -5709,7 +5705,7 @@ void CGameProcMain::ParseChattingCommand(const std::string & szCmd) { if (m_pUIStateBarAndMiniMap) { m_pUIStateBarAndMiniMap->SetSystemTimeVisibility(false); } - } + } int eCmd = -1; @@ -7858,7 +7854,7 @@ bool CGameProcMain::OnMouseRbtnDown(POINT ptCur, POINT ptPrev) { if (fRotY || fRotX) { SetGameCursor(NULL); - POINT ptToScreen{ ptPrev.x, ptPrev.y }; + POINT ptToScreen{ptPrev.x, ptPrev.y}; ::ClientToScreen(s_hWndBase, &ptToScreen); ::SetCursorPos(ptToScreen.x, ptToScreen.y); s_pLocalInput->MouseSetPos(ptPrev.x, ptPrev.y); @@ -7886,26 +7882,24 @@ void CGameProcMain::ProcessUIKeyInput(bool bEnable) { if (s_pLocalInput->IsKeyPress(DIK_RETURN) && !s_bKeyPress) { if (m_pUIChatDlg->whisperTarget.empty()) { m_pUIChatDlg->SetFocus(); - } - else { + } else { if (it != m_pUIChatDlg->whisperWindows.end()) { m_pUIChatDlg->whisperWindows[m_pUIChatDlg->whisperTarget].Open->SetFocus(); } } } - } - else if (m_pUIChatDlg && m_pUIChatDlg->IsChatMode()) { + } else if (m_pUIChatDlg && m_pUIChatDlg->IsChatMode()) { s_bKeyPress = false; if (m_pUIChatDlg->GetEnableKillFocus()) { m_pUIChatDlg->SetEnableKillFocus(false); m_pUIChatDlg->KillFocus(); } if (!m_pUIChatDlg->whisperTarget.empty() && it != m_pUIChatDlg->whisperWindows.end()) { - if(m_pUIChatDlg->whisperWindows[m_pUIChatDlg->whisperTarget].Open->GetEnableKillFocus()){ + if (m_pUIChatDlg->whisperWindows[m_pUIChatDlg->whisperTarget].Open->GetEnableKillFocus()) { m_pUIChatDlg->whisperWindows[m_pUIChatDlg->whisperTarget].Open->SetEnableKillFocus(false); m_pUIChatDlg->whisperWindows[m_pUIChatDlg->whisperTarget].Open->KillFocus(); - } - } + } + } } } diff --git a/src/game/GameProcMain.h b/src/game/GameProcMain.h index 534aa270..9d74ec87 100644 --- a/src/game/GameProcMain.h +++ b/src/game/GameProcMain.h @@ -7,7 +7,6 @@ #include "GameProcedure.h" #include - typedef typename std::set::iterator it_ID; typedef std::pair pair_ID; @@ -22,17 +21,17 @@ class CGameProcMain : public CGameProcedure { #ifdef _N3_64GRID_ CServerMesh * m_pSMesh; // 서버에게 필요한 메쉬 클래스.. #endif - class CUIInventory * m_pUIInventory; // 인벤토리 - class CUIVarious * m_pUIVar; // 캐릭터 상태창, 기사단 관리 등이 페이지로 들어간 다용도 UI - class CUIChat * m_pUIChatDlg; // 채팅 입출력 대화상자.. + class CUIInventory * m_pUIInventory; // 인벤토리 + class CUIVarious * m_pUIVar; // 캐릭터 상태창, 기사단 관리 등이 페이지로 들어간 다용도 UI + class CUIChat * m_pUIChatDlg; // 채팅 입출력 대화상자.. class CUIChatWhisperOpen * m_pUIChatWhiserOpen; class CUIChatWhisperHide * m_pUIChatWhiserHide; - class CUIMessageWnd * m_pUIMsgDlg; // 게임 메시지 출력 상자. - class CUIStateBar * m_pUIStateBarAndMiniMap; // mp,hp,exp, minimap.... - class CUICmd * m_pUICmd; // 왼쪽 하단의 명령버튼 창.. - class CUICmdList * m_pUICmdList; - class CUICmdEdit * m_pUICmdEditDlg; - class CUITargetBar * m_pUITargetBar; // 타겟 상태창.. + class CUIMessageWnd * m_pUIMsgDlg; // 게임 메시지 출력 상자. + class CUIStateBar * m_pUIStateBarAndMiniMap; // mp,hp,exp, minimap.... + class CUICmd * m_pUICmd; // 왼쪽 하단의 명령버튼 창.. + class CUICmdList * m_pUICmdList; + class CUICmdEdit * m_pUICmdEditDlg; + class CUITargetBar * m_pUITargetBar; // 타겟 상태창.. class CUITransactionDlg * m_pUITransactionDlg; class CUIDroppedItemDlg * m_pUIDroppedItemDlg; class CSubProcPerTrade * m_pSubProcPerTrade; diff --git a/src/game/UIChat.cpp b/src/game/UIChat.cpp index 86da2ccc..2deaad12 100644 --- a/src/game/UIChat.cpp +++ b/src/game/UIChat.cpp @@ -851,9 +851,8 @@ void CUIChat::SetNoticeTitle(const std::string & szString, D3DCOLOR color) { } } -void CUIChat::InitializeWhisperWindows(const std::string & nickname, bool isSender) -{ - e_Nation eNation = CGameBase::s_pPlayer->m_InfoBase.eNation; +void CUIChat::InitializeWhisperWindows(const std::string & nickname, bool isSender) { + e_Nation eNation = CGameBase::s_pPlayer->m_InfoBase.eNation; __TABLE_UI_RESRC * pTbl = CGameProcedure::s_pProcMain->s_pTbl_UI->Find(eNation); ChatWhisperWindows & window = whisperWindows[nickname]; @@ -889,10 +888,10 @@ bool CUIChat::deleteWhisperWinodws(const std::string & nickname) { } whisperWindows.erase(it); - return true; + return true; } - return false; + return false; } std::pair CUIChat::CalculateWhisperPosition(int activeWhisperWindowsCount) { diff --git a/src/game/UIChat.h b/src/game/UIChat.h index 53082757..37e98058 100644 --- a/src/game/UIChat.h +++ b/src/game/UIChat.h @@ -23,8 +23,8 @@ struct __ChatInfo { }; struct ChatWhisperWindows { - CUIChatWhisperOpen* Open; - CUIChatWhisperHide* Hide; + CUIChatWhisperOpen * Open; + CUIChatWhisperHide * Hide; bool messageNotRead; ChatWhisperWindows() @@ -123,9 +123,9 @@ class CUIChat : public CN3UIBase { D3DCOLOR color = 0xffffffff); // 채팅 메세지를 저장하고 알맞은 형태로 화면에 출력해준다. void AddContinueMsg(e_ChatMode eCM, const std::string & szString, D3DCOLOR color = 0xffffffff); void AdjustScroll(); // 스크롤 위치등 조정.. - void InitializeWhisperWindows(const std::string & nickname, bool isSender); + void InitializeWhisperWindows(const std::string & nickname, bool isSender); std::pair CalculateWhisperPosition(int activeWhisperWindowsCount); - bool deleteWhisperWinodws(const std::string & nickname); + bool deleteWhisperWinodws(const std::string & nickname); BOOL IsChatMode(); void SetFocus(); diff --git a/src/game/UIChatWhisperHide.cpp b/src/game/UIChatWhisperHide.cpp index db4d07cb..8dc6bd38 100644 --- a/src/game/UIChatWhisperHide.cpp +++ b/src/game/UIChatWhisperHide.cpp @@ -18,8 +18,7 @@ // Construction/Destruction ////////////////////////////////////////////////////////////////////// -CUIChatWhisperHide::CUIChatWhisperHide() { -} +CUIChatWhisperHide::CUIChatWhisperHide() {} CUIChatWhisperHide::~CUIChatWhisperHide() {} @@ -80,7 +79,6 @@ bool CUIChatWhisperHide::Load(HANDLE hFile) { return true; } - void CUIChatWhisperHide::Render() { if (!m_bVisible) { return; diff --git a/src/game/UIChatWhisperHide.h b/src/game/UIChatWhisperHide.h index de7ac519..2349f18f 100644 --- a/src/game/UIChatWhisperHide.h +++ b/src/game/UIChatWhisperHide.h @@ -12,14 +12,13 @@ class CUIChatWhisperHide : public CN3UIBase { static class CGameProcCharacterSelect * s_pProcCharacterSelect; protected: - int m_iCurContinueMsg; - CN3UIString * m_pNoticeTitle; - CN3UIString * - m_pChatOut; - CN3UIScrollBar * m_pScrollbar; - int m_iChatLineCount; - RECT m_rcChatOutRegion; - CN3UIString ** m_ppUILines; + int m_iCurContinueMsg; + CN3UIString * m_pNoticeTitle; + CN3UIString * m_pChatOut; + CN3UIScrollBar * m_pScrollbar; + int m_iChatLineCount; + RECT m_rcChatOutRegion; + CN3UIString ** m_ppUILines; CN3UIEdit * m_pEdit; //son, chat_in std::string m_szString; //son, chat_in @@ -33,24 +32,22 @@ class CUIChatWhisperHide : public CN3UIBase { // Operations public: - void ShowContinueMsg(); - void DeleteContinueMsg(); - bool OnKeyPress(int iKey); - bool GetEnableKillFocus() { return m_bKillFocus; } - void SetEnableKillFocus(bool bKillFocus) { m_bKillFocus = bKillFocus; } - void ChatListenEnable(); - void SetNewMessageAnimation(bool animationActivated = true); - virtual BOOL MoveOffset(int iOffsetX, int iOffsetY); + void ShowContinueMsg(); + void DeleteContinueMsg(); + bool OnKeyPress(int iKey); + bool GetEnableKillFocus() { return m_bKillFocus; } + void SetEnableKillFocus(bool bKillFocus) { m_bKillFocus = bKillFocus; } + void ChatListenEnable(); + void SetNewMessageAnimation(bool animationActivated = true); + virtual BOOL MoveOffset(int iOffsetX, int iOffsetY); virtual bool ReceiveMessage(CN3UIBase * pSender, DWORD dwMsg); virtual void Release(); virtual bool Load(HANDLE hFile); - virtual void SetRegion( - const RECT & - Rect); + virtual void SetRegion(const RECT & Rect); void SetString(const std::string & szChat); void SetCaretPos(int iPos); - const std::string & GetString() const { return m_szString; } + const std::string & GetString() const { return m_szString; } void Open(string userName); void Render(); diff --git a/src/game/UIChatWhisperOpen.cpp b/src/game/UIChatWhisperOpen.cpp index fe04992b..ef890bca 100644 --- a/src/game/UIChatWhisperOpen.cpp +++ b/src/game/UIChatWhisperOpen.cpp @@ -20,31 +20,32 @@ ////////////////////////////////////////////////////////////////////// CUIChatWhisperOpen::CUIChatWhisperOpen() { - - if (m_ppUILines) { delete[] m_ppUILines; m_ppUILines = NULL; } + if (m_ppUILines) { + delete[] m_ppUILines; + m_ppUILines = NULL; + } - ChatListPmItor itor; - for (itor = m_ChatBuffer.begin(); m_ChatBuffer.end() != itor; ++itor) - { + ChatListPmItor itor; + for (itor = m_ChatBuffer.begin(); m_ChatBuffer.end() != itor; ++itor) { __WhisperMessage * pChatInfo = (*itor); - if (pChatInfo) delete pChatInfo; - } + if (pChatInfo) { + delete pChatInfo; + } + } m_ChatBuffer.clear(); - for (itor = m_LineBuffer.begin(); m_LineBuffer.end() != itor; ++itor) - { + for (itor = m_LineBuffer.begin(); m_LineBuffer.end() != itor; ++itor) { __WhisperMessage * pChatInfo = (*itor); - if (pChatInfo) delete pChatInfo; - } + if (pChatInfo) { + delete pChatInfo; + } + } m_LineBuffer.clear(); - - DeleteContinueMsg(); - + DeleteContinueMsg(); } -CUIChatWhisperOpen::~CUIChatWhisperOpen() { -} +CUIChatWhisperOpen::~CUIChatWhisperOpen() {} void CUIChatWhisperOpen::Release() { CN3UIBase::Release(); @@ -113,7 +114,6 @@ bool CUIChatWhisperOpen::ReceiveMessage(CN3UIBase * pSender, DWORD dwMsg) { return CGameProcedure::s_pProcMain->m_pUIChatDlg->deleteWhisperWinodws(m_pText_UserName->GetString()); } else if (pSender->m_szID == "btn_hide") { - SetEnableKillFocus(false); KillFocus(); CGameProcedure::s_pProcMain->m_pUIChatDlg->KillFocus(); @@ -122,12 +122,11 @@ bool CUIChatWhisperOpen::ReceiveMessage(CN3UIBase * pSender, DWORD dwMsg) { CGameProcedure::s_pUIMgr->ReFocusUI(); SetVisible(false); CGameProcedure::s_pProcMain->m_pUIChatDlg->whisperTarget = ""; - + auto it = CGameProcedure::s_pProcMain->m_pUIChatDlg->whisperWindows.find(m_pText_UserName->GetString()); if (it != CGameProcedure::s_pProcMain->m_pUIChatDlg->whisperWindows.end()) { CGameProcedure::s_pProcMain->m_pUIChatDlg->whisperWindows[m_pText_UserName->GetString()] .messageNotRead = false; - } CGameProcedure::s_pProcMain->WhisperHide(m_pText_UserName->GetString(), chatPosition); @@ -135,10 +134,8 @@ bool CUIChatWhisperOpen::ReceiveMessage(CN3UIBase * pSender, DWORD dwMsg) { } else if (dwMsg == UI_MOUSE_LBCLICK && (pSender->m_szID == "btn_bar" || pSender->m_szID == "exit_id")) { SetState(UI_STATE_COMMON_MOVE); - } else if (dwMsg == UI_MOUSE_LBCLICK && pSender->m_szID == "edit_chat"){ - + } else if (dwMsg == UI_MOUSE_LBCLICK && pSender->m_szID == "edit_chat") { CGameProcedure::s_pProcMain->m_pUIChatDlg->whisperTarget = m_pText_UserName->GetString(); - } else if (dwMsg == UIMSG_EDIT_RETURN) { CN3UIEdit * m_pBtn_message = (CN3UIEdit *)pSender; @@ -165,7 +162,7 @@ void CUIChatWhisperOpen::AddLineBuffer(const std::string & szString, D3DCOLOR co } const int iStrLen = szString.size(); - SIZE size; + SIZE size; if (FALSE == m_pMessages_List->GetTextExtent(szString, iStrLen, &size)) { __ASSERT(0, "no device context"); return; @@ -196,15 +193,14 @@ void CUIChatWhisperOpen::AddLineBuffer(const std::string & szString, D3DCOLOR co } else { int iCC = 0; if (0x80 & szString[iCount]) { - iCC = 2; // 2BYTE + iCC = 2; // 2BYTE } else { iCC = 1; // 1BYTE } BOOL bFlag = m_pMessages_List->GetTextExtent(&(szString[iCount]), iCC, &size); __ASSERT(bFlag, "cannot get size of dfont"); - if ((iCX + size.cx) > iRegionWidth) - { + if ((iCX + size.cx) > iRegionWidth) { int iLineLength = iCount - iLineStart; if (iLineLength > 0) { __WhisperMessage * pLineInfo = new __WhisperMessage; @@ -265,7 +261,9 @@ void CUIChatWhisperOpen::CreateLines() { m_ppUILines = NULL; } SIZE size; - if (m_pMessages_List && m_pMessages_List->GetTextExtent("M", lstrlen("M"), &size) && size.cy > 0) { // The letter 'M' is used for measuring text width because it's typically the widest character, providing a better estimate of the maximum text width. + if (m_pMessages_List && m_pMessages_List->GetTextExtent("M", lstrlen("M"), &size) && + size.cy > + 0) { // The letter 'M' is used for measuring text width because it's typically the widest character, providing a better estimate of the maximum text width. m_iChatLineCount = (m_rcChatOutRegion.bottom - m_rcChatOutRegion.top) / size.cy; } else { return; @@ -292,13 +290,10 @@ void CUIChatWhisperOpen::CreateLines() { } void CUIChatWhisperOpen::AdjustScroll() { - int iCurLinePos = m_pScrollbar->GetCurrentPos(); + int iCurLinePos = m_pScrollbar->GetCurrentPos(); BOOL bAutoScroll = (m_pScrollbar->GetMaxPos() == iCurLinePos) ? TRUE : FALSE; - while ( - m_LineBuffer.size() > MAX_CHAT_LINES_PM && - 0 < iCurLinePos) - { + while (m_LineBuffer.size() > MAX_CHAT_LINES_PM && 0 < iCurLinePos) { __WhisperMessage * pTemp = m_LineBuffer.front(); if (pTemp) { delete pTemp; @@ -365,7 +360,7 @@ void CUIChatWhisperOpen::SetTopLine(int iTopLine) { } __ASSERT(m_ppUILines, "null pointer"); - int iRealLine = i; + int iRealLine = i; int iRealLineCount = 0; for (int i = 0; i < iRealLine; ++i) { ++iRealLineCount; @@ -385,7 +380,7 @@ void CUIChatWhisperOpen::SetTopLine(int iTopLine) { } void CUIChatWhisperOpen::RecalcLineBuffers() { - int iMaxScrollPos = 0; + int iMaxScrollPos = 0; ChatListPmItor itor; for (itor = m_LineBuffer.begin(); m_LineBuffer.end() != itor; ++itor) { __WhisperMessage * pLineBuff = (*itor); @@ -403,8 +398,7 @@ void CUIChatWhisperOpen::RecalcLineBuffers() { } } - while (m_LineBuffer.size() > MAX_CHAT_LINES_PM) - { + while (m_LineBuffer.size() > MAX_CHAT_LINES_PM) { __WhisperMessage * pLineBuff = m_ChatBuffer.front(); if (pLineBuff) { delete pLineBuff; @@ -419,7 +413,7 @@ void CUIChatWhisperOpen::RecalcLineBuffers() { if (iMaxScrollPos < 0) { iMaxScrollPos = 0; } - m_pScrollbar->SetRange(0, iMaxScrollPos); + m_pScrollbar->SetRange(0, iMaxScrollPos); m_pScrollbar->SetCurrentPos(iMaxScrollPos); SetTopLine(iMaxScrollPos); @@ -481,7 +475,6 @@ BOOL CUIChatWhisperOpen::MoveOffset(int iOffsetX, int iOffsetY) { pCUI->MoveOffset(iOffsetX, iOffsetY); } - return TRUE; } @@ -508,7 +501,7 @@ void CUIChatWhisperOpen::ShowContinueMsg() { m_iCurContinueMsg = 0; } - int iCnt = 0; + int iCnt = 0; ChatListPmItor itor; for (itor = m_ContinueMsg.begin(); m_ContinueMsg.end() != itor; ++itor) { if (iCnt == m_iCurContinueMsg) { @@ -535,4 +528,3 @@ bool CUIChatWhisperOpen::OnKeyPress(int iKey) { return CN3UIBase::OnKeyPress(iKey); } - diff --git a/src/game/UIChatWhisperOpen.h b/src/game/UIChatWhisperOpen.h index 2d82daec..5471be5e 100644 --- a/src/game/UIChatWhisperOpen.h +++ b/src/game/UIChatWhisperOpen.h @@ -8,8 +8,8 @@ #include struct __WhisperMessage { - std::string szChat; - D3DCOLOR color; + std::string szChat; + D3DCOLOR color; __WhisperMessage(){}; __WhisperMessage(const std::string & szChat_Arg, D3DCOLOR color_Arg) { @@ -18,8 +18,8 @@ struct __WhisperMessage { } }; -typedef deque<__WhisperMessage *> ChatListPm; -typedef ChatListPm::iterator ChatListPmItor; +typedef deque<__WhisperMessage *> ChatListPm; +typedef ChatListPm::iterator ChatListPmItor; typedef ChatListPm::reverse_iterator ChatListPmReverseItor; const int MAX_CHAT_LINES_PM = 100; @@ -29,15 +29,14 @@ class CUIChatWhisperOpen : public CN3UIBase { ChatListPm m_ChatBuffer; ChatListPm m_LineBuffer; ChatListPm m_ContinueMsg; - int m_iCurContinueMsg; + int m_iCurContinueMsg; - CN3UIString * m_pNoticeTitle; - CN3UIString * - m_pChatOut; + CN3UIString * m_pNoticeTitle; + CN3UIString * m_pChatOut; CN3UIScrollBar * m_pScrollbar; - int m_iChatLineCount; + int m_iChatLineCount; RECT m_rcChatOutRegion; - CN3UIString ** m_ppUILines; + CN3UIString ** m_ppUILines; CN3UIEdit * m_pMessage_Text; CN3UIString * m_pMessages_List; @@ -61,34 +60,30 @@ class CUIChatWhisperOpen : public CN3UIBase { bool m_bKillFocus; protected: - void SetTopLine(int iTopLine); - void AddLineBuffer(const std::string & szString, - D3DCOLOR color); - void RecalcLineBuffers(); + void SetTopLine(int iTopLine); + void AddLineBuffer(const std::string & szString, D3DCOLOR color); + void RecalcLineBuffers(); void CreateLines(); // Operations public: - void ShowContinueMsg(); - void DeleteContinueMsg(); - bool OnKeyPress(int iKey); - bool GetEnableKillFocus() { return m_bKillFocus; } - void SetEnableKillFocus(bool bKillFocus) { m_bKillFocus = bKillFocus; } - virtual BOOL MoveOffset(int iOffsetX, int iOffsetY); + void ShowContinueMsg(); + void DeleteContinueMsg(); + bool OnKeyPress(int iKey); + bool GetEnableKillFocus() { return m_bKillFocus; } + void SetEnableKillFocus(bool bKillFocus) { m_bKillFocus = bKillFocus; } + virtual BOOL MoveOffset(int iOffsetX, int iOffsetY); virtual bool ReceiveMessage(CN3UIBase * pSender, DWORD dwMsg); virtual void Release(); virtual bool Load(HANDLE hFile); - virtual void SetRegion( - const RECT & - Rect); + virtual void SetRegion(const RECT & Rect); void SetString(const std::string & szChat); void SetCaretPos(int iPos); const std::string & GetString() const { return m_szString; } //son, chat_in - void AddChatMsg(const std::string & szString, - D3DCOLOR color = 0xffffffff); + void AddChatMsg(const std::string & szString, D3DCOLOR color = 0xffffffff); void AddContinueMsg(e_ChatMode eCM, const std::string & szString, D3DCOLOR color = 0xffffffff); - void AdjustScroll(); + void AdjustScroll(); void Open(string userName); void Render(); diff --git a/src/game/res/Resource.h b/src/game/res/Resource.h index db519038..18ba26ce 100644 --- a/src/game/res/Resource.h +++ b/src/game/res/Resource.h @@ -444,14 +444,14 @@ #define IDS_SETTING_ELMORAD_SCREEN 6125 #define IDS_USER_HAS_BLOCKED_WHISPER 7636 -#define IDS_CMD_CATEGORY_PRIVATE 7800 -#define IDS_CMD_CATEGORY_TRADE 7801 -#define IDS_CMD_CATEGORY_PARTY 7802 -#define IDS_CMD_CATEGORY_CLAN 7803 -#define IDS_CMD_CATEGORY_KNIGHTS 7804 -#define IDS_CMD_CATEGORY_GUARDIAN 7805 -#define IDS_CMD_CATEGORY_KING 7806 -#define IDS_CMD_CATEGORY_GM 7807 +#define IDS_CMD_CATEGORY_PRIVATE 7800 +#define IDS_CMD_CATEGORY_TRADE 7801 +#define IDS_CMD_CATEGORY_PARTY 7802 +#define IDS_CMD_CATEGORY_CLAN 7803 +#define IDS_CMD_CATEGORY_KNIGHTS 7804 +#define IDS_CMD_CATEGORY_GUARDIAN 7805 +#define IDS_CMD_CATEGORY_KING 7806 +#define IDS_CMD_CATEGORY_GM 7807 #define IDS_CMD_WHISPER 8000 #define IDS_CMD_TOWN 8001 diff --git a/src/server/Ebenezer/User.cpp b/src/server/Ebenezer/User.cpp index edaba854..640c9132 100644 --- a/src/server/Ebenezer/User.cpp +++ b/src/server/Ebenezer/User.cpp @@ -6433,11 +6433,11 @@ BOOL CUser::ItemEquipAvailable(_ITEM_TABLE * pTable) { } void CUser::ChatTargetSelect(char * pBuf) { - char targetUserID[MAX_ID_SIZE + 1] = {0}; - char packetBuffer[128] = {0}; + char targetUserID[MAX_ID_SIZE + 1] = {0}; + char packetBuffer[128] = {0}; - int bufferIndex = 0; - int packetIndex = 0; + int bufferIndex = 0; + int packetIndex = 0; uint8_t messageType = GetUInt8(pBuf, bufferIndex); @@ -6458,15 +6458,15 @@ void CUser::ChatTargetSelect(char * pBuf) { if (targetUser && targetUser->GetState() == STATE_GAMESTART && _strnicmp(targetUserID, targetUser->m_pUserData->m_id, MAX_ID_SIZE) == 0) { if (targetUser->isBlockingPrivateChat()) { - chatStatus = USER_BLOCKS_CHAT; + chatStatus = USER_BLOCKS_CHAT; } else { m_sPrivateChatUser = i; - chatStatus = USER_FOUND; + chatStatus = USER_FOUND; } break; } } - + SetByte(packetBuffer, WIZ_CHAT_TARGET, packetIndex); switch (chatStatus) { @@ -6475,7 +6475,7 @@ void CUser::ChatTargetSelect(char * pBuf) { break; case USER_BLOCKS_CHAT: - SetShort(packetBuffer, -1, packetIndex); + SetShort(packetBuffer, -1, packetIndex); break; case USER_FOUND: @@ -6484,7 +6484,7 @@ void CUser::ChatTargetSelect(char * pBuf) { SetString(packetBuffer, targetUser->m_pUserData->m_id, userIDLength, packetIndex); break; } - break; + break; } case BLOCK_CHAT: {