Grim4ik Posted Wednesday at 11:39 AM Share Posted Wednesday at 11:39 AM (edited) UIStateForm.cpp 1) Находим строку: using namespace GUI; Под ней вставляем: namespace { enum class EStatBtn { NONE, STR, AGI, CON, STA, DEX }; static bool s_holdActive = false; static EStatBtn s_activeBtn = EStatBtn::NONE; static int s_stage = 0; static DWORD s_intervalMs = 300; static DWORD s_nextTick = 0; static EStatBtn ResolveStatBtnByName(const std::string& n) { if (n == "btnStr") return EStatBtn::STR; if (n == "btnAgi") return EStatBtn::AGI; if (n == "btnCon") return EStatBtn::CON; if (n == "btnSta") return EStatBtn::STA; if (n == "btnDex") return EStatBtn::DEX; return EStatBtn::NONE; } static int AttrIdFromBtn(EStatBtn b) { switch (b) { case EStatBtn::STR: return ATTR_STR; case EStatBtn::AGI: return ATTR_AGI; case EStatBtn::CON: return ATTR_CON; case EStatBtn::STA: return ATTR_STA; case EStatBtn::DEX: return ATTR_DEX; default: return -1; } } static void DoAddOne(EStatBtn btn) { const int attrId = AttrIdFromBtn(btn); if (attrId < 0) return; CCharacter* pCha = g_stUIBoat.GetHuman(); if (!pCha) return; SGameAttr* ga = pCha->getGameAttr(); if (!ga || ga->get(ATTR_AP) <= 0) return; CChaAttr attr; attr.ResetChangeFlag(); attr.DirectSetAttr(attrId, 1); attr.SetChangeBitFlag(attrId); if (auto* proCir = (CProCirculateCS*)g_NetIF->GetProCir()) proCir->SynBaseAttribute(&attr); } static POINT GetClientCursor(HWND hwnd) { POINT p; ::GetCursorPos(&p); if (hwnd) ::ScreenToClient(hwnd, &p); return p; } static bool IsMouseOverBtn(HWND hwnd, CForm* frm, CGuiData* btn) { if (!frm || !btn || !btn->GetIsShow()) return false; POINT c = GetClientCursor(hwnd); const int x = frm->GetLeft() + btn->GetLeft(); const int y = frm->GetTop() + btn->GetTop(); const int w = btn->GetWidth(); const int h = btn->GetHeight(); return (c.x >= x && c.x < x + w && c.y >= y && c.y < y + h); } static CGuiData* ButtonByEnum(CTextButton* btnStr, CTextButton* btnAgi, CTextButton* btnCon, CTextButton* btnSta, CTextButton* btnDex, EStatBtn b) { switch (b) { case EStatBtn::STR: return btnStr; case EStatBtn::AGI: return btnAgi; case EStatBtn::CON: return btnCon; case EStatBtn::STA: return btnSta; case EStatBtn::DEX: return btnDex; default: return nullptr; } } static void StartHold(EStatBtn b) { s_activeBtn = b; s_holdActive = (b != EStatBtn::NONE); s_stage = 0; s_intervalMs = 300; s_nextTick = ::GetTickCount() + s_intervalMs; } static void StopHold() { s_holdActive = false; s_activeBtn = EStatBtn::NONE; } } 2) Находим существующую функцию: void CStateMgr::FrameMove(DWORD dwTime) { if( frmState->GetIsShow() ) { static CTimeWork time(100); if( time.IsTimeOut( dwTime ) ) RefreshStateFrm(); } } Заменяем целиком функцию на: void CStateMgr::FrameMove(DWORD dwTime) { if (frmState->GetIsShow()) { static CTimeWork time(100); if (time.IsTimeOut(dwTime)) RefreshStateFrm(); } HWND hwnd = ::GetActiveWindow(); const bool lmbDown = (::GetAsyncKeyState(VK_LBUTTON) & 0x8000) != 0; if (lmbDown && !s_holdActive) { if (IsMouseOverBtn(hwnd, frmState, btnStr)) StartHold(EStatBtn::STR); else if (IsMouseOverBtn(hwnd, frmState, btnAgi)) StartHold(EStatBtn::AGI); else if (IsMouseOverBtn(hwnd, frmState, btnCon)) StartHold(EStatBtn::CON); else if (IsMouseOverBtn(hwnd, frmState, btnSta)) StartHold(EStatBtn::STA); else if (IsMouseOverBtn(hwnd, frmState, btnDex)) StartHold(EStatBtn::DEX); } if (s_holdActive) { CGuiData* activeBtnPtr = ButtonByEnum(btnStr, btnAgi, btnCon, btnSta, btnDex, s_activeBtn); const bool stillOver = IsMouseOverBtn(hwnd, frmState, activeBtnPtr); if (!lmbDown || !stillOver) { StopHold(); } } if (s_holdActive) { DWORD now = ::GetTickCount(); if (now >= s_nextTick) { DoAddOne(s_activeBtn); if (s_stage == 0) s_intervalMs = 150; else if (s_stage == 1) s_intervalMs = 100; else s_intervalMs = 80; ++s_stage; s_nextTick = now + s_intervalMs; } } } 3) Найти функцию: void CStateMgr::MainMouseDown(CGuiData *pSender, int x, int y, DWORD key) Если в функции есть строки ниже, их удалить или замутить, остальное без изменения: s_activeBtn = ResolveStatBtnByName(name); // ← ЭТО УДАЛИТЬ, если было s_holdActive = true; // ← ТАКОГО ТОЖЕ БЫТЬ НЕ ДОЛЖНО Это все! Edited yesterday at 06:18 AM by Grim4ik 1 Quote Link to comment Share on other sites More sharing options...
Graf Posted Wednesday at 05:04 PM Share Posted Wednesday at 05:04 PM @Grim4ik Добрый вечер. Не уверен в корректности "заменить весь код". Хотя бы комментарии добавьте, чтобы люди могли нужные части кода себе перетащить. 1 Quote Link to comment Share on other sites More sharing options...
Grim4ik Posted yesterday at 06:20 AM Author Share Posted yesterday at 06:20 AM 13 часов назад, Graf сказал: @Grim4ik Добрый вечер. Не уверен в корректности "заменить весь код". Хотя бы комментарии добавьте, чтобы люди могли нужные части кода себе перетащить. Добрый день! Поправил, сделал просто замены функции по шагам, не трогая целый код! 1 Quote Link to comment Share on other sites More sharing options...
Grim4ik Posted yesterday at 07:51 AM Author Share Posted yesterday at 07:51 AM Небольшой UPDATE Словил баг, что защита сервера выкидывает, при добавлении большого количества статов за раз. По этому добавление внизу, делает мини паузу через каждые 25 статов и с сервера больше не выбрасывает. 1) В функции namespace после static DWORD s_nextTick = 0; вставляем: static int s_holdCount = 0; 2) В static void StartHold(EStatBtn b) после s_nextTick = ::GetTickCount() + s_intervalMs; вставляем: s_holdCount = 0; 3) В FrameMove заменить кусок функции if (now >= s_nextTick) { ... } на: if (now >= s_nextTick) { if (s_holdCount >= 25) { StopHold(); return; } CCharacter* pCha = g_stUIBoat.GetHuman(); if (!pCha) { StopHold(); return; } SGameAttr* ga = pCha->getGameAttr(); if (!ga || ga->get(ATTR_AP) <= 0) { StopHold(); return; } DoAddOne(s_activeBtn); ++s_holdCount; if (s_stage == 0) s_intervalMs = 150; else if (s_stage == 1) s_intervalMs = 100; else s_intervalMs = 80; ++s_stage; s_nextTick = now + s_intervalMs; } Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.