Jump to content

Авто добавление статов при удержании кнопки


Grim4ik

Recommended Posts

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 by Grim4ik
  • Like 1
Link to comment
Share on other sites

13 часов назад, Graf сказал:

@Grim4ik Добрый вечер. Не уверен в корректности "заменить весь код". Хотя бы комментарии добавьте, чтобы люди могли нужные части кода себе перетащить.

Добрый день! 

Поправил, сделал просто замены функции по шагам, не трогая целый код!
 

  • Like 1
Link to comment
Share on other sites

Небольшой 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;
}

 

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Chat

Chat

Please enter your display name

×
×
  • Create New...