Noticias:

SMF - Just Installed!

Menú principal

Source MuHelper.cpp main 5.2

Publicado por Dakosmu, Feb 10, 2025, 04:04 PM

Tema anterior - Siguiente tema

Dakosmu

Source MuHelper.cpp main 5.2


MuHelper.cpp

#include "stdafx.h"

#include <thread>
#include <atomic>
#include <chrono>
#include <cmath>

#include "ZzzAI.h"
#include "ZzzCharacter.h"
#include "ZzzInterface.h"
#include "NewUISystem.h"
#include "Utilities/Log/muConsoleDebug.h"
#include "SkillManager.h"
#include "PartyManager.h"
#include "MapManager.h"
#include "WSclient.h"

#include "MuHelper.h"

constexpr int MAX_ACTIONABLE_DISTANCE = 10;
constexpr int DEFAULT_DURABILITY_THRESHOLD = 50;

SpinLock _targetsLock;
SpinLock _itemsLock;

namespace MUHelper
{
    CMuHelper g_MuHelper;

    void CALLBACK CMuHelper::TimerProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
    {
        g_MuHelper.WorkLoop(hwnd, uMsg, idEvent, dwTime);
    }

    void CMuHelper::Save(const ConfigData& config)
    {
        m_config = config;

        PRECEIVE_MUHELPER_DATA netData;
        ConfigDataSerDe::Serialize(m_config, netData);

        SocketClient->ToGameServer()->SendMuHelperSaveDataRequest(reinterpret_cast<BYTE*>(&netData), sizeof(netData));
    }

    void CMuHelper::Load(const ConfigData& config)
    {
        m_config = config;
    }

    ConfigData CMuHelper::GetConfig() const {
        return m_config;
    }

    void CMuHelper::Toggle()
    {
        if (m_bActive)
        {
            TriggerStop();
        }
        else
        {
            TriggerStart();
        }
    }

    void CMuHelper::TriggerStart()
    {
        SocketClient->ToGameServer()->SendMuHelperStatusChangeRequest(0);
    }

    void CMuHelper::TriggerStop()
    {
        SocketClient->ToGameServer()->SendMuHelperStatusChangeRequest(1);
    }

    void CMuHelper::Start()
    {
        if (m_bActive)
        {
            return;
        }

        m_iTotalCost = 0;
        m_iComboState = 0;
        m_iCurrentBuffIndex = 0;
        m_iCurrentBuffPartyIndex = 0;
        m_iCurrentTarget = -1;
        m_iCurrentSkill = m_config.aiSkill[0];
        m_iCurrentItem = MAX_ITEMS;
        m_posOriginal = { Hero->PositionX, Hero->PositionY };

        m_iHuntingDistance = ComputeDistanceByRange(m_config.iHuntingRange);
        m_iObtainingDistance = ComputeDistanceByRange(m_config.iObtainingRange);

        m_iSecondsElapsed = 0;
        m_iSecondsAway = 0;

        m_bTimerActivatedBuffOngoing = false;
        m_bPetActivated = false;

        m_iLoopCounter = 0;

        m_bActive = true;
        g_ConsoleDebug->Write(MCD_NORMAL, L"[MU Helper] Started");
    }

    void CMuHelper::Stop()
    {
        m_bActive = false;
        g_ConsoleDebug->Write(MCD_NORMAL, L"[MU Helper] Stopped");
    }

    void CMuHelper::WorkLoop(HWND hWnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
    {
        if (!m_bActive)
        {
            return;
        }

        if (Hero->SafeZone)
        {
            g_ConsoleDebug->Write(MCD_NORMAL, L"[MU Helper] Entered safezone. Stopping.");
            TriggerStop();
            return;
        }

        Work();

        if (m_iLoopCounter++ == 4)
        {
            m_iSecondsElapsed++;

            if (ComputeDistanceBetween({ Hero->PositionX, Hero->PositionY }, m_posOriginal) > 1)
            {
                m_iSecondsAway++;
            }
            else
            {
                m_iSecondsAway = 0;
            }

            m_iLoopCounter = 0;
        }
    }

    void CMuHelper::Work()
    {
        try
        {
            if (!ActivatePet())
            {
                return;
            }

            if (!Buff())
            {
                return;
            }

            if (!RecoverHealth())
            {
                return;
            }

            if (!ObtainItem())
            {
                return;
            }

            if (!Regroup())
            {
                return;
            }

            Attack();

            RepairEquipments();
        }
        catch (...)
        {
            g_ConsoleDebug->Write(MCD_NORMAL, L"[MU Helper] Exception occurred. Ignoring...");
        }
    }

    void CMuHelper::AddTarget(int iTargetId, bool bIsAttacking)
    {
        if (!m_bActive)
        {
            return;
        }

        CHARACTER* pTarget = FindCharacterByKey(iTargetId);
        if (!pTarget || pTarget == Hero)
        {
            return;
        }

        int iDistance = ComputeDistanceFromTarget(pTarget);

        if ((iDistance <= m_iHuntingDistance)
            || (bIsAttacking && m_config.bLongRangeCounterAttack))
        {
            _targetsLock.lock();

            m_setTargets.insert(iTargetId);

            if (bIsAttacking)
            {
                m_setTargetsAttacking.insert(iTargetId);
            }

            _targetsLock.unlock();
        }

        if (m_config.bUseSelfDefense)
        {
            pTarget->Object.Kind = KIND_MONSTER;
            m_iCurrentTarget = iTargetId;
        }
    }

    void CMuHelper::DeleteTarget(int iTargetId)
    {
        _targetsLock.lock();

        m_setTargets.erase(iTargetId);
        m_setTargetsAttacking.erase(iTargetId);

        _targetsLock.unlock();

        if (iTargetId == m_iCurrentTarget)
        {
            m_iCurrentTarget = -1;
        }
    }

    void CMuHelper::DeleteAllTargets()
    {
        _targetsLock.lock();

        m_setTargets.clear();
        m_setTargetsAttacking.clear();

        _targetsLock.unlock();
    }

    int CMuHelper::ComputeDistanceByRange(int iRange)
    {
        return ComputeDistanceBetween({ 0, 0 }, { iRange, iRange });
    }

    int CMuHelper::ComputeDistanceFromTarget(CHARACTER* pTarget)
    {
        POINT posA, posB;

        posA = { Hero->PositionX, Hero->PositionY };
        posB = { pTarget->PositionX, pTarget->PositionY };
        int iPrevDistance = ComputeDistanceBetween(posA, posB);

        posA = { Hero->PositionX, Hero->PositionY };
        posB = { pTarget->TargetX, pTarget->TargetX };
        int iNextDistance = ComputeDistanceBetween(posA, posB);

        return min(iPrevDistance, iNextDistance);
    }

    int CMuHelper::ComputeDistanceBetween(POINT posA, POINT posB)
    {
        int iDx = posA.x - posB.x;
        int iDy = posA.y - posB.y;

        return static_cast<int>(std::ceil(std::sqrt(iDx * iDx + iDy * iDy)));
    }

    int CMuHelper::GetNearestTarget()
    {
        int iClosestMonsterId = -1;
        int iMinDistance = m_config.iHuntingRange + 1;

        std::set<int> setTargets;
        {
            _targetsLock.lock();
            setTargets = m_setTargets;
            _targetsLock.unlock();
        }

        for (const int& iMonsterId : setTargets)
        {
            int iIndex = FindCharacterIndex(iMonsterId);
            CHARACTER* pTarget = &CharactersClient[iIndex];

            int iDistance = ComputeDistanceFromTarget(pTarget);
            if (iDistance < iMinDistance)
            {
                iMinDistance = iDistance;
                iClosestMonsterId = iMonsterId;
            }
        }

        return iClosestMonsterId;
    }

    int CMuHelper::GetFarthestAttackingTarget()
    {
        int iFarthestMonsterId = -1;
        int iMaxDistance = -1;

        std::set<int> setTargets;
        {
            _targetsLock.lock();
            setTargets = m_setTargetsAttacking;
            _targetsLock.unlock();
        }

        for (const int& iMonsterId : setTargets)
        {
            int iIndex = FindCharacterIndex(iMonsterId);
            CHARACTER* pTarget = &CharactersClient[iIndex];

            int iDistance = ComputeDistanceFromTarget(pTarget);
            if (iDistance > iMaxDistance)
            {
                iMaxDistance = iDistance;
                iFarthestMonsterId = iMonsterId;
            }
        }

        return iFarthestMonsterId;
    }

    void CMuHelper::CleanupTargets()
    {
        std::set<int> setTargets;
        {
            _targetsLock.lock();
            setTargets = m_setTargets;
            _targetsLock.unlock();
        }

        for (const int& iMonsterId : setTargets)
        {
            int iIndex = FindCharacterIndex(iMonsterId);
            if (iIndex == MAX_CHARACTERS_CLIENT)
            {
                DeleteTarget(iMonsterId);
            }

            CHARACTER* pTarget = &CharactersClient[iIndex];
            if (!pTarget || (pTarget && (pTarget->Dead > 0 || !pTarget->Object.Live)))
            {
                DeleteTarget(iMonsterId);
            }
        }
    }

    int CMuHelper::ActivatePet()
    {
        if (!m_config.bUseDarkRaven)
        {
            return 1;
        }

        if (m_bPetActivated)
        {
            return 1;
        }

        if (m_config.iDarkRavenMode == PET_ATTACK_CEASE)
        {
            SocketClient->ToGameServer()->SendPetCommandRequest(PET_TYPE_DARK_SPIRIT, AT_PET_COMMAND_DEFAULT, 0xFFFF);
        }
        else if (m_config.iDarkRavenMode == PET_ATTACK_AUTO)
        {
            SocketClient->ToGameServer()->SendPetCommandRequest(PET_TYPE_DARK_SPIRIT, AT_PET_COMMAND_RANDOM, 0xFFFF);
        }
        else if (m_config.iDarkRavenMode == PET_ATTACK_TOGETHER)
        {
            SocketClient->ToGameServer()->SendPetCommandRequest(PET_TYPE_DARK_SPIRIT, AT_PET_COMMAND_OWNER, 0xFFFF);
        }

        m_bPetActivated = true;
        return 1;
    }

    int CMuHelper::Buff()
    {
        if (!HasAssignedBuffSkill())
        {
            return 1;
        }

        if (m_config.bSupportParty && g_pPartyManager->IsPartyActive())
        {
            PARTY_t* pMember = &Party[m_iCurrentBuffPartyIndex];
            CHARACTER* pChar = g_pPartyManager->GetPartyMemberChar(pMember);

            if (pChar != NULL
                && pMember->Map == gMapManager.WorldActive
                && ComputeDistanceFromTarget(pChar) <= MAX_ACTIONABLE_DISTANCE)
            {
                if (!m_config.bBuffDurationParty
                    && m_config.iBuffCastInterval != 0
                    && m_iSecondsElapsed % m_config.iBuffCastInterval == 0)
                {
                    m_bTimerActivatedBuffOngoing = true;
                }

                if (!BuffTarget(pChar, m_config.aiBuff[m_iCurrentBuffIndex]))
                {
                    return 0;
                }
            }

            m_iCurrentBuffPartyIndex = (m_iCurrentBuffPartyIndex + 1) % (sizeof(Party) / sizeof(Party[0]));
        }
        else
        {
            if (!m_config.bBuffDuration
                && m_config.iBuffCastInterval != 0
                && m_iSecondsElapsed % m_config.iBuffCastInterval == 0)
            {
                m_bTimerActivatedBuffOngoing = true;
            }

            if (!BuffTarget(Hero, m_config.aiBuff[m_iCurrentBuffIndex]))
            {
                return 0;
            }
        }

        if (m_iCurrentBuffPartyIndex == 0)
        {
            m_iCurrentBuffIndex = (m_iCurrentBuffIndex + 1) % m_config.aiBuff.size();

            // Reaching this branch means everyone's been buffed,
            // so we're resetting the timer activated buff flag
            if (m_iCurrentBuffIndex == 0)
            {
                m_bTimerActivatedBuffOngoing = false;
            }
        }

        return 1;
    }

    int CMuHelper::BuffTarget(CHARACTER* pTargetChar, int iBuffSkill)
    {
        // TODO: List other buffs here
        if ((iBuffSkill == AT_SKILL_ATTACK
            || iBuffSkill == AT_SKILL_ATT_POWER_UP
            || iBuffSkill == AT_SKILL_ATT_POWER_UP + 1
            || iBuffSkill == AT_SKILL_ATT_POWER_UP + 2
            || iBuffSkill == AT_SKILL_ATT_POWER_UP + 3
            || iBuffSkill == AT_SKILL_ATT_POWER_UP + 4)
            && (!g_isCharacterBuff((&pTargetChar->Object), eBuff_Attack) || m_bTimerActivatedBuffOngoing))
        {
            return SimulateSkill(iBuffSkill, true, pTargetChar->Key);
        }

        if ((iBuffSkill == AT_SKILL_DEFENSE
            || iBuffSkill == AT_SKILL_DEF_POWER_UP
            || iBuffSkill == AT_SKILL_DEF_POWER_UP + 1
            || iBuffSkill == AT_SKILL_DEF_POWER_UP + 2
            || iBuffSkill == AT_SKILL_DEF_POWER_UP + 3
            || iBuffSkill == AT_SKILL_DEF_POWER_UP + 4)
            && (!g_isCharacterBuff((&pTargetChar->Object), eBuff_Defense) || m_bTimerActivatedBuffOngoing))
        {
            return SimulateSkill(iBuffSkill, true, pTargetChar->Key);
        }

        if ((iBuffSkill == AT_SKILL_INFINITY_ARROW) &&
            (!g_isCharacterBuff((&pTargetChar->Object), eBuff_InfinityArrow)))
        {
            return SimulateSkill(iBuffSkill, false, pTargetChar->Key);
        }

        if ((iBuffSkill == AT_SKILL_WIZARDDEFENSE
            || iBuffSkill == AT_SKILL_SOUL_UP
            || iBuffSkill == AT_SKILL_SOUL_UP + 1
            || iBuffSkill == AT_SKILL_SOUL_UP + 2
            || iBuffSkill == AT_SKILL_SOUL_UP + 3
            || iBuffSkill == AT_SKILL_SOUL_UP + 4)
            && (!g_isCharacterBuff((&pTargetChar->Object), eBuff_WizDefense) || m_bTimerActivatedBuffOngoing))
        {
            return SimulateSkill(iBuffSkill, true, pTargetChar->Key);
        }

        if ((iBuffSkill == AT_SKILL_VITALITY
            || iBuffSkill == AT_SKILL_LIFE_UP
            || iBuffSkill == AT_SKILL_LIFE_UP + 1
            || iBuffSkill == AT_SKILL_LIFE_UP + 2
            || iBuffSkill == AT_SKILL_LIFE_UP + 3
            || iBuffSkill == AT_SKILL_LIFE_UP + 4)
            && (!g_isCharacterBuff((&pTargetChar->Object), eBuff_Life) || m_bTimerActivatedBuffOngoing))
        {
            if (m_iComboState == 2)
            {
                return 1;
            }

            return SimulateSkill(iBuffSkill, false, pTargetChar->Key);
        }

        if ((iBuffSkill == AT_SKILL_SWELL_OF_MAGICPOWER)
            && (!g_isCharacterBuff((&pTargetChar->Object), eBuff_SwellOfMagicPower)))
        {
            return SimulateSkill(iBuffSkill, false, pTargetChar->Key);
        }

        if ((iBuffSkill == AT_SKILL_ADD_CRITICAL)
            && (!g_isCharacterBuff((&pTargetChar->Object), eBuff_AddCriticalDamage)))
        {
            return SimulateSkill(iBuffSkill, false, pTargetChar->Key);
        }

        if ((iBuffSkill == AT_SKILL_ALICE_BERSERKER)
            && (!g_isCharacterBuff((&pTargetChar->Object), eBuff_Berserker)))
        {
            return SimulateSkill(iBuffSkill, false, pTargetChar->Key);
        }
        if ((iBuffSkill == AT_SKILL_ALICE_THORNS)
            && (!g_isCharacterBuff((&pTargetChar->Object), eBuff_Thorns)))
        {
            return SimulateSkill(iBuffSkill, false, pTargetChar->Key);
        }

        return 1;
    }

    int CMuHelper::ConsumePotion()
    {
        int64_t iLife = CharacterAttribute->Life;
        int64_t iLifeMax = CharacterAttribute->LifeMax;

        if (m_config.bUseHealPotion && iLifeMax > 0 && iLife > 0)
        {
            int64_t iRemaining = (iLife * 100 + iLifeMax - 1) / iLifeMax;
            if (iRemaining <= m_config.iPotionThreshold)
            {
                int iPotionIndex = g_pMyInventory->FindHealingItemIndex();
                if (iPotionIndex != -1)
                {
                    SendRequestUse(iPotionIndex, 0);
                }
            }
        }

        return 1;
    }

    int CMuHelper::RecoverHealth()
    {
        if (!Heal())
        {
            return 0;
        }
       
        if (!DrainLife())
        {
            return 0;
        }

        if (!ConsumePotion())
        {
            return 0;
        }

        return 1;
    }

    int CMuHelper::Heal()
    {
        if (!m_config.bAutoHeal)
        {
            return 1;
        }

        int iHealingSkill = GetHealingSkill();
        if (iHealingSkill == -1)
        {
            return 1;
        }

        if (m_config.bAutoHealParty && g_pPartyManager->IsPartyActive())
        {
            PARTY_t* pMember = &Party[m_iCurrentHealPartyIndex];
            CHARACTER* pChar = g_pPartyManager->GetPartyMemberChar(pMember);

            if (pChar != NULL)
            {
                if (pChar == Hero)
                {
                    return HealSelf(iHealingSkill);
                }
                else if (pMember->Map == gMapManager.WorldActive
                    && pMember->stepHP * 10 <= m_config.iHealPartyThreshold
                    && ComputeDistanceFromTarget(pChar) <= MAX_ACTIONABLE_DISTANCE)
                {
                    return SimulateSkill(iHealingSkill, true, pChar->Key);
                }
            }
            m_iCurrentHealPartyIndex = (m_iCurrentHealPartyIndex + 1) % (sizeof(Party) / sizeof(Party[0]));
        }
        else
        {
            return HealSelf(iHealingSkill);
        }

        return 1;
    }

    int CMuHelper::HealSelf(int iHealingSkill)
    {
        int64_t iLife = CharacterAttribute->Life;
        int64_t iLifeMax = CharacterAttribute->LifeMax;
        int64_t iRemaining = (iLife * 100 + iLifeMax - 1) / iLifeMax;

        if (iRemaining <= m_config.iHealThreshold)
        {
            return SimulateSkill(iHealingSkill, true, HeroKey);
        }

        return 1;
    }

    int CMuHelper::DrainLife()
    {
        if (!m_config.bUseDrainLife)
        {
            return 1;
        }

        int iDrainLife = GetDrainLifeSkill();
        if (iDrainLife == -1)
        {
            return 1;
        }

        int64_t iLife = CharacterAttribute->Life;
        int64_t iLifeMax = CharacterAttribute->LifeMax;
        int64_t iRemaining = (iLife * 100 + iLifeMax - 1) / iLifeMax;

        if (iRemaining <= m_config.iHealThreshold)
        {
            m_iCurrentTarget = GetNearestTarget();
            if (m_iCurrentTarget != -1)
            {
                return SimulateSkill(iDrainLife, true, m_iCurrentTarget);
            }
        }

        return 1;
    }

    int CMuHelper::RepairEquipments()
    {
        if (m_config.bRepairItem)
        {
            for (int i = 0; i < MAX_EQUIPMENT; i++)
            {
                ITEM* pItem = &CharacterMachine->Equipment[i];
                if (!pItem || pItem->Type == -1)
                {
                    continue;
                }

                ITEM_ATTRIBUTE* pAttr = &ItemAttribute[pItem->Type];
                if (!pAttr)
                {
                    continue;
                }

                int iLevel = pItem->Level;
                int iDurability = pItem->Durability;
                int iMaxDurability = CalcMaxDurability(pItem, pAttr, iLevel);

                int64_t iHealth = (iDurability * 100 + iMaxDurability - 1) / iMaxDurability;

                if (iHealth <= DEFAULT_DURABILITY_THRESHOLD)
                {
                    int64_t iGoldCost = CalcSelfRepairCost(ItemValue(pItem, 2), iDurability, iMaxDurability, pItem->Type);
                    if (iGoldCost <= CharacterMachine->Gold)
                    {
                        SocketClient->ToGameServer()->SendRepairItemRequest(i, 1);
                    }
                }
            }
        }

        return 1;
    }

    int CMuHelper::Attack()
    {
        if (m_iCurrentTarget == -1)
        {
            if (!m_setTargets.empty())
            {
                CleanupTargets();

                if (m_config.bLongRangeCounterAttack)
                {
                    m_iCurrentTarget = GetFarthestAttackingTarget();
                }
               
                if (m_iCurrentTarget == -1)
                {
                    m_iCurrentTarget = GetNearestTarget();
                }
            }
            else
            {
                m_iComboState = 0;
                return 0;
            }
        }

        if (m_config.bUseCombo)
        {
            return SimulateComboAttack();
        }

        m_iCurrentSkill = SelectAttackSkill();
        if (m_iCurrentSkill > 0)
        {
            SimulateAttack(m_iCurrentSkill);
        }

        return 1;
    }

    int CMuHelper::SelectAttackSkill()
    {
        // try skill 2 activation conditions
        if (m_config.aiSkill[1] > 0 && m_config.aiSkill[1] < MAX_SKILLS)
        {
            if ((m_config.aiSkillCondition[1] & ON_TIMER)
                && m_config.aiSkillInterval[1] != 0
                && m_iSecondsElapsed % m_config.aiSkillInterval[1] == 0)
            {
                return m_config.aiSkill[1];
            }

            if (m_config.aiSkillCondition[1] & ON_CONDITION)
            {
                if (m_config.aiSkillCondition[1] & ON_MOBS_NEARBY)
                {
                    int iCount = m_setTargets.size();

                    if (((m_config.aiSkillCondition[1] & ON_MORE_THAN_TWO_MOBS) && iCount >= 2)
                        || ((m_config.aiSkillCondition[1] & ON_MORE_THAN_THREE_MOBS) && iCount >= 3)
                        || ((m_config.aiSkillCondition[1] & ON_MORE_THAN_FOUR_MOBS) && iCount >= 4)
                        || ((m_config.aiSkillCondition[1] & ON_MORE_THAN_FIVE_MOBS) && iCount >= 5))
                    {
                        return m_config.aiSkill[1];
                    }
                }
                else if (m_config.aiSkillCondition[1] & ON_MOBS_ATTACKING)
                {
                    int iCount = m_setTargetsAttacking.size();

                    if (((m_config.aiSkillCondition[1] & ON_MORE_THAN_TWO_MOBS) && iCount >= 2)
                        || ((m_config.aiSkillCondition[1] & ON_MORE_THAN_THREE_MOBS) && iCount >= 3)
                        || ((m_config.aiSkillCondition[1] & ON_MORE_THAN_FOUR_MOBS) && iCount >= 4)
                        || ((m_config.aiSkillCondition[1] & ON_MORE_THAN_FIVE_MOBS) && iCount >= 5))
                    {
                        return m_config.aiSkill[1];
                    }
                }
            }
        }

        // try skill 3 activation conditions
        if (m_config.aiSkill[2] > 0 && m_config.aiSkill[2] < MAX_SKILLS)
        {
            if ((m_config.aiSkillCondition[2] & ON_TIMER)
                && m_config.aiSkillInterval[2] != 0
                && m_iSecondsElapsed % m_config.aiSkillInterval[2] == 0)
            {
                return m_config.aiSkill[2];
            }

            if (m_config.aiSkillCondition[2] & ON_CONDITION)
            {
                if (m_config.aiSkillCondition[2] & ON_MOBS_NEARBY)
                {
                    int iCount = m_setTargets.size();

                    if (((m_config.aiSkillCondition[2] & ON_MORE_THAN_TWO_MOBS) && iCount >= 2)
                        || ((m_config.aiSkillCondition[2] & ON_MORE_THAN_THREE_MOBS) && iCount >= 3)
                        || ((m_config.aiSkillCondition[2] & ON_MORE_THAN_FOUR_MOBS) && iCount >= 4)
                        || ((m_config.aiSkillCondition[2] & ON_MORE_THAN_FIVE_MOBS) && iCount >= 5))
                    {
                        return m_config.aiSkill[2];
                    }
                }
                else if (m_config.aiSkillCondition[2] & ON_MOBS_ATTACKING)
                {
                    int iCount = m_setTargetsAttacking.size();

                    if (((m_config.aiSkillCondition[2] & ON_MORE_THAN_TWO_MOBS) && iCount >= 2)
                        || ((m_config.aiSkillCondition[2] & ON_MORE_THAN_THREE_MOBS) && iCount >= 3)
                        || ((m_config.aiSkillCondition[2] & ON_MORE_THAN_FOUR_MOBS) && iCount >= 4)
                        || ((m_config.aiSkillCondition[2] & ON_MORE_THAN_FIVE_MOBS) && iCount >= 5))
                    {
                        return m_config.aiSkill[2];
                    }
                }
            }
        }

        // no skill for activation yet, default to basic skill
        if (m_config.aiSkill[0] > 0)
        {
            return m_config.aiSkill[0];
        }

        return -1;
    }

    int CMuHelper::SimulateComboAttack()
    {
        for (int i = 0; i < m_config.aiSkill.size(); i++)
        {
            if (m_config.aiSkill[i] == 0)
            {
                return 0;
            }
        }

        if (SimulateAttack(m_config.aiSkill[m_iComboState]))
        {
            m_iComboState = (m_iComboState + 1) % 3;
        }

        return 1;
    }

    int CMuHelper::SimulateAttack(int iSkill)
    {
        return SimulateSkill(iSkill, true, m_iCurrentTarget);
    }

    int CMuHelper::SimulateSkill(int iSkill, bool bTargetRequired, int iTarget)
    {
        extern MovementSkill g_MovementSkill;
        extern int SelectedCharacter;
        extern int TargetX, TargetY;

        g_MovementSkill.m_iSkill = iSkill;
        g_MovementSkill.m_bMagic = true;

        float fSkillDistance = gSkillManager.GetSkillDistance(iSkill, Hero);

        if (bTargetRequired)
        {
            if (iTarget == -1)
            {
                return 0;
            }

            SelectedCharacter = FindCharacterIndex(iTarget);
            if (SelectedCharacter == MAX_CHARACTERS_CLIENT)
            {
                DeleteTarget(iTarget);
                return 0;
            }

            CHARACTER* pTarget = &CharactersClient[SelectedCharacter];
            if (pTarget->Dead > 0)
            {
                DeleteTarget(iTarget);
                return 0;
            }

            g_MovementSkill.m_iTarget = SelectedCharacter;

            TargetX = (int)(pTarget->Object.Position[0] / TERRAIN_SCALE);
            TargetY = (int)(pTarget->Object.Position[1] / TERRAIN_SCALE);

            PATH_t tempPath;
            bool bHasPath = PathFinding2(Hero->PositionX, Hero->PositionY, TargetX, TargetY, &tempPath, m_iHuntingDistance + fSkillDistance);
            bool bTargetNear = CheckTile(Hero, &Hero->Object, fSkillDistance);
            bool bNoWall = CheckWall(Hero->PositionX, Hero->PositionY, TargetX, TargetY);

            // target not reachable, ignore it
            if (!bHasPath)
            {
                DeleteTarget(iTarget);
                return 0;
            }

            // target is not near or the path is obstructed by a wall, move closer
            if (!bTargetNear || !bNoWall)
            {
                Hero->Path.Lock.lock();

                // Limit movement to 2 steps at a time
                int pathNum = min(tempPath.PathNum, 2);
                for (int i = 0; i < pathNum; i++)
                {
                    Hero->Path.PathX[i] = tempPath.PathX[i];
                    Hero->Path.PathY[i] = tempPath.PathY[i];
                }
                Hero->Path.PathNum = pathNum;
                Hero->Path.CurrentPath = 0;
                Hero->Path.CurrentPathFloat = 0;

                Hero->Path.Lock.unlock();

                SendMove(Hero, &Hero->Object);
                return 0;
            }
        }
        else
        {
            TargetX = Hero->PositionX;
            TargetY = Hero->PositionY;
        }

        int iSkillResult = ExecuteSkill(Hero, iSkill, fSkillDistance);
        if (iSkillResult == -1)
        {
            DeleteTarget(iTarget);
        }

        return (int)(iSkillResult == 1);
    }

    int CMuHelper::Regroup()
    {
        if (m_config.bReturnToOriginalPosition && m_iSecondsAway > m_config.iMaxSecondsAway)
        {
            if (!SimulateMove(m_posOriginal))
            {
                return 0;
            }

            m_iSecondsAway = 0;
            m_iComboState = 0;
            m_iCurrentTarget = -1;
        }

        return 1;
    }

    int CMuHelper::SimulateMove(POINT posMove)
    {
        extern int TargetX, TargetY;

        Hero->MovementType = MOVEMENT_MOVE;
        TargetX = (int)posMove.x;
        TargetY = (int)posMove.y;

        if (!CheckTile(Hero, &Hero->Object, 1.5f))
        {
            if (PathFinding2((Hero->PositionX), (Hero->PositionY), TargetX, TargetY, &Hero->Path))
            {
                SendMove(Hero, &Hero->Object);
            }
            return 0;
        }

        return 1;
    }

    bool CMuHelper::HasAssignedBuffSkill()
    {
        for (int i = 0; i < m_config.aiBuff.size(); i++)
        {
            if (m_config.aiBuff[i] != 0)
            {
                return true;
            }
        }

        return false;
    }

    int CMuHelper::GetHealingSkill()
    {
        std::vector<int> aiHealingSkills =
        {
            AT_SKILL_HEAL_UP,
            AT_SKILL_HEAL_UP + 1,
            AT_SKILL_HEAL_UP + 2,
            AT_SKILL_HEAL_UP + 3,
            AT_SKILL_HEAL_UP + 4,
            AT_SKILL_HEALING
        };

        for (int i = 0; i < aiHealingSkills.size(); i++)
        {
            int iSkillIndex = g_pSkillList->GetSkillIndex(aiHealingSkills[i]);
            if (iSkillIndex != -1)
            {
                return aiHealingSkills[i];
            }
        }

        return -1;
    }

    int CMuHelper::GetDrainLifeSkill()
    {
        std::vector<int> aiDrainLifeSkills =
        {
            AT_SKILL_ALICE_DRAINLIFE_UP,
            AT_SKILL_ALICE_DRAINLIFE_UP + 1,
            AT_SKILL_ALICE_DRAINLIFE_UP + 2,
            AT_SKILL_ALICE_DRAINLIFE_UP + 3,
            AT_SKILL_ALICE_DRAINLIFE_UP + 4,
            AT_SKILL_ALICE_DRAINLIFE,
        };

        for (int i = 0; i < aiDrainLifeSkills.size(); i++)
        {
            int iSkillIndex = g_pSkillList->GetSkillIndex(aiDrainLifeSkills[i]);
            if (iSkillIndex != -1)
            {
                return aiDrainLifeSkills[i];
            }
        }

        return -1;
    }

    int CMuHelper::ObtainItem()
    {
        if (m_iCurrentItem == MAX_ITEMS)
        {
            m_iCurrentItem = SelectItemToObtain();
            if (m_iCurrentItem == MAX_ITEMS)
            {
                return 1;
            }
        }

        ITEM_t* pDrop = &Items[m_iCurrentItem];
        ITEM* pItem = &pDrop->Item;

        if (!pDrop->Object.Live)
        {
            DeleteItem(m_iCurrentItem);
            return 1;
        }

        extern int TargetX;
        extern int TargetY;

        TargetX = (int)(Items[m_iCurrentItem].Object.Position[0] / TERRAIN_SCALE);
        TargetY = (int)(Items[m_iCurrentItem].Object.Position[1] / TERRAIN_SCALE);

        int iDistance = ComputeDistanceBetween({ Hero->PositionX, Hero->PositionY }, { TargetX, TargetY });
        if (iDistance <= m_iObtainingDistance)
        {
            if (!CheckTile(Hero, &Hero->Object, 1.5f))
            {
                if (PathFinding2((Hero->PositionX), (Hero->PositionY), TargetX, TargetY, &Hero->Path))
                {
                    SendMove(Hero, &Hero->Object);
                }

                return 0;
            }
            else
            {
                SocketClient->ToGameServer()->SendPickupItemRequest(m_iCurrentItem);
                DeleteItem(m_iCurrentItem);
            }
        }

        return 1;
    }

    bool CMuHelper::ShouldObtainItem(int iItemId)
    {
        ITEM_t* pDrop = &Items[iItemId];
        ITEM* pItem = &pDrop->Item;

        if ((m_config.bPickZen && IsMoneyItem(pItem))
            || (m_config.bPickJewel && IsJewelItem(pItem))
            || (m_config.bPickAncient && IsAncientItem(pItem))
            || (m_config.bPickExcellent && IsExcellentItem(pItem)))
        {
            return true;
        }

        if (m_config.bPickExtraItems)
        {
            std::wstring strDisplayName = GetItemDisplayName(pItem);

            for (const auto& str : m_config.aExtraItems)
            {
                // Check if the search keyword is in the item's display name
                if (strDisplayName.find(str) != std::wstring::npos)
                {
                    return true;
                }
            }
        }

        return m_config.bPickAllItems;
    }

    void CMuHelper::AddItem(int iItemId, POINT posWhere)
    {
        _itemsLock.lock();
        m_setItems.insert(iItemId);
        _itemsLock.unlock();
    }

    void CMuHelper::DeleteItem(int iItemId)
    {
        _itemsLock.lock();
        m_setItems.erase(iItemId);
        _itemsLock.unlock();

        if (iItemId == m_iCurrentItem)
        {
            m_iCurrentItem = MAX_ITEMS;
        }
    }

    int CMuHelper::SelectItemToObtain()
    {
        int iClosestItemId = MAX_ITEMS;
        int iMinDistance = m_config.iObtainingRange + 1;

        std::set<int> setItems;
        {
            _itemsLock.lock();
            setItems = m_setItems;
            _itemsLock.unlock();
        }

        for (const int& iItemId : setItems)
        {
            if (!ShouldObtainItem(iItemId))
            {
                continue;
            }

            int iItemX = (int)(Items[iItemId].Object.Position[0] / TERRAIN_SCALE);
            int iItemY = (int)(Items[iItemId].Object.Position[1] / TERRAIN_SCALE);

            int iDistance = ComputeDistanceBetween({ Hero->PositionX, Hero->PositionY }, { iItemX, iItemY });
            if (iDistance < iMinDistance)
            {
                iMinDistance = iDistance;
                iClosestItemId = iItemId;
            }
        }

        return iClosestItemId;
    }
}

MuHelper.h

#pragma once

#include <functional>
#include <array>
#include <set>
#include <string>
#include <thread>
#include <atomic>

#include "MuHelperData.h"

namespace MUHelper
{
class CMuHelper
{
public:
CMuHelper() = default;
~CMuHelper() = default;

public:
static void CALLBACK TimerProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime);

ConfigData GetConfig() const;
void Save(const ConfigData& config);
void Load(const ConfigData& config);
void Start();
void Stop();
void Toggle();
void TriggerStart();
void TriggerStop();
bool IsActive() { return m_bActive; }
void AddCost(int iCost) { m_iTotalCost += iCost; }
int GetTotalCost() { return m_iTotalCost; }

void AddTarget(int iTargetId, bool bIsAttacking);
void DeleteTarget(int iTargetId);
void DeleteAllTargets();

void AddItem(int iItemId, POINT posDropped);
void DeleteItem(int iItemId);

private:
void WorkLoop(HWND hWnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime);
void Work();
int ActivatePet();
int Buff();
int BuffTarget(CHARACTER* pTargetChar, int iBuffSkill);
int RecoverHealth();
int Heal();
int HealSelf(int iHealingSkill);
int DrainLife();
int ConsumePotion();
int Attack();
int RepairEquipments();
int Regroup();
int SelectAttackSkill();
int SimulateAttack(int iSkill);
int SimulateSkill(int iSkill, bool bTargetRequired, int iTarget);
int SimulateComboAttack();
int GetNearestTarget();
int GetFarthestAttackingTarget();
void CleanupTargets();
int ComputeDistanceByRange(int iRange);
int ComputeDistanceFromTarget(CHARACTER* pTarget);
int ComputeDistanceBetween(POINT posA, POINT posB);
int SimulateMove(POINT posMove);
int ObtainItem();
int SelectItemToObtain();
bool ShouldObtainItem(int iItemId);
int GetHealingSkill();
int GetDrainLifeSkill();
bool HasAssignedBuffSkill();

private:
ConfigData m_config;
POINT m_posOriginal;
std::thread m_timerThread;
std::atomic<bool> m_bActive;
std::set<int> m_setTargets;
std::set<int> m_setTargetsAttacking;
std::set<int> m_setItems;
int m_iCurrentItem;
int m_iCurrentTarget;
int m_iCurrentBuffIndex;
int m_iCurrentBuffPartyIndex;
int m_iCurrentHealPartyIndex;
int m_iComboState;
int m_iCurrentSkill;
int m_iHuntingDistance;
int m_iObtainingDistance;
int m_iLoopCounter;
int m_iSecondsElapsed;
int m_iSecondsAway;
bool m_bTimerActivatedBuffOngoing;
bool m_bPetActivated;
int m_iTotalCost;
};

extern CMuHelper g_MuHelper;
}




Bon Dia

Dakosmu

MuHelperData.cpp


#include "stdafx.h"
#include "MuHelperData.h"

namespace MUHelper
{

    void ConfigDataSerDe::Serialize(const ConfigData& gameData, PRECEIVE_MUHELPER_DATA& netData)
    {
        memset(&netData, 0, sizeof(netData));

        netData.HuntingRange = static_cast<BYTE>(gameData.iHuntingRange & 0x0F);
        netData.DistanceMin = static_cast<BYTE>(gameData.iMaxSecondsAway & 0x0F);
        netData.LongDistanceAttack = gameData.bLongRangeCounterAttack ? 1 : 0;
        netData.OriginalPosition = gameData.bReturnToOriginalPosition ? 1 : 0;

        netData.BasicSkill1 = static_cast<WORD>(gameData.aiSkill[0] & 0xFFFF);
        netData.ActivationSkill1 = static_cast<WORD>(gameData.aiSkill[1] & 0xFFFF);
        netData.ActivationSkill2 = static_cast<WORD>(gameData.aiSkill[2] & 0xFFFF);

        netData.DelayMinSkill1 = static_cast<WORD>(gameData.aiSkillInterval[1] & 0xFFFF);
        netData.DelayMinSkill2 = static_cast<WORD>(gameData.aiSkillInterval[2] & 0xFFFF);

        if (gameData.aiSkillCondition[1] & ON_TIMER)
        {
            netData.Skill1Delay = 1;
        }
        if (gameData.aiSkillCondition[1] & ON_CONDITION)
        {
            netData.Skill1Con = 1;
        }
        if (gameData.aiSkillCondition[1] & ON_MOBS_NEARBY)
        {
            netData.Skill1PreCon = 0;
        }
        else if (gameData.aiSkillCondition[1] & ON_MOBS_ATTACKING)
        {
            netData.Skill1PreCon = 1;
        }

        if (gameData.aiSkillCondition[1] & ON_MORE_THAN_TWO_MOBS)
        {
            netData.Skill1SubCon = 0;
        }
        else if (gameData.aiSkillCondition[1] & ON_MORE_THAN_THREE_MOBS)
        {
            netData.Skill1SubCon = 1;
        }
        else if (gameData.aiSkillCondition[1] & ON_MORE_THAN_FOUR_MOBS)
        {
            netData.Skill1SubCon = 2;
        }
        else if (gameData.aiSkillCondition[1] & ON_MORE_THAN_FIVE_MOBS)
        {
            netData.Skill1SubCon = 3;
        }

        if (gameData.aiSkillCondition[2] & ON_TIMER)
        {
            netData.Skill2Delay = 1;
        }
        if (gameData.aiSkillCondition[2] & ON_CONDITION)
        {
            netData.Skill2Con = 1;
        }
        if (gameData.aiSkillCondition[2] & ON_MOBS_NEARBY)
        {
            netData.Skill2PreCon = 0;
        }
        else if (gameData.aiSkillCondition[2] & ON_MOBS_ATTACKING)
        {
            netData.Skill2PreCon = 1;
        }

        if (gameData.aiSkillCondition[2] & ON_MORE_THAN_TWO_MOBS)
        {
            netData.Skill2SubCon = 0;
        }
        else if (gameData.aiSkillCondition[2] & ON_MORE_THAN_THREE_MOBS)
        {
            netData.Skill2SubCon = 1;
        }
        else if (gameData.aiSkillCondition[2] & ON_MORE_THAN_FOUR_MOBS)
        {
            netData.Skill2SubCon = 2;
        }
        else if (gameData.aiSkillCondition[2] & ON_MORE_THAN_FIVE_MOBS)
        {
            netData.Skill2SubCon = 3;
        }

        netData.Combo = gameData.bUseCombo ? 1 : 0;

        netData.BuffSkill0NumberID = static_cast<WORD>(gameData.aiBuff[0] & 0xFFFF);
        netData.BuffSkill1NumberID = static_cast<WORD>(gameData.aiBuff[1] & 0xFFFF);
        netData.BuffSkill2NumberID = static_cast<WORD>(gameData.aiBuff[2] & 0xFFFF);

        netData.BuffDuration = gameData.bBuffDuration ? 1 : 0;
        netData.BuffDurationforAllPartyMembers = gameData.bBuffDurationParty ? 1 : 0;
        netData.CastingBuffMin = static_cast<WORD>(gameData.iBuffCastInterval);

        netData.AutoHeal = gameData.bAutoHeal ? 1 : 0;
        netData.HPStatusAutoPotion = static_cast<BYTE>((gameData.iPotionThreshold / 10) & 0x0F);
        netData.HPStatusAutoHeal = static_cast<BYTE>((gameData.iHealThreshold / 10) & 0x0F);
        netData.AutoPotion = gameData.bUseHealPotion ? 1 : 0;
        netData.DrainLife = gameData.bUseDrainLife ? 1 : 0;
        netData.Party = gameData.bSupportParty ? 1 : 0;
        netData.PreferenceOfPartyHeal = gameData.bAutoHealParty ? 1 : 0;

        netData.HPStatusOfPartyMembers = static_cast<BYTE>((gameData.iHealPartyThreshold / 10) & 0x0F);
        netData.HPStatusDrainLife = static_cast<BYTE>((gameData.iHealThreshold / 10) & 0x0F);

        netData.UseDarkSpirits = gameData.bUseDarkRaven ? 1 : 0;
        netData.PetAttack = static_cast<BYTE>(gameData.iDarkRavenMode);

        netData.RepairItem = gameData.bRepairItem ? 1 : 0;
        netData.ObtainRange = static_cast<BYTE>(gameData.iObtainingRange & 0x0F);
        netData.PickAllNearItems = gameData.bPickAllItems ? 1 : 0;
        netData.PickSelectedItems = gameData.bPickSelectItems ? 1 : 0;
        netData.Zen = gameData.bPickZen ? 1 : 0;
        netData.JewelOrGem = gameData.bPickJewel ? 1 : 0;
        netData.ExcellentItem = gameData.bPickExcellent ? 1 : 0;
        netData.SetItem = gameData.bPickAllItems ? 1 : 0;
        netData.AddExtraItem = gameData.bPickExtraItems ? 1 : 0;

        memset(netData.ExtraItems, 0, sizeof(netData.ExtraItems));
        int iItemIndex = 0;
        for (const auto& wsItem : gameData.aExtraItems)
        {
            if (iItemIndex >= 12)
            {
                break;
            }

            size_t n = wcstombs(netData.ExtraItems[iItemIndex], wsItem.c_str(), 15);
            if (n == (size_t)-1 || n == 15)
            {
                memset(netData.ExtraItems[iItemIndex], 0, 15);
            }
            iItemIndex++;
        }
    }

    void ConfigDataSerDe::Deserialize(const PRECEIVE_MUHELPER_DATA& netData, ConfigData& gameData)
    {
        gameData.iHuntingRange = static_cast<int>(netData.HuntingRange);

        gameData.iMaxSecondsAway = static_cast<int>(netData.DistanceMin);
        gameData.bLongRangeCounterAttack = (bool)netData.LongDistanceAttack;
        gameData.bReturnToOriginalPosition = (bool)netData.OriginalPosition;

        gameData.aiSkill.fill(0);
        gameData.aiSkill[0] = static_cast<int>(netData.BasicSkill1);
        gameData.aiSkill[1] = static_cast<int>(netData.ActivationSkill1);
        gameData.aiSkill[2] = static_cast<int>(netData.ActivationSkill2);

        gameData.aiSkillInterval.fill(0);
        gameData.aiSkillInterval[1] = static_cast<int>(netData.DelayMinSkill1);
        gameData.aiSkillInterval[2] = static_cast<int>(netData.DelayMinSkill2);

        gameData.aiSkillCondition.fill(0);
        gameData.aiSkillCondition[1] |= netData.Skill1Delay ? ON_TIMER : 0;
        gameData.aiSkillCondition[1] |= netData.Skill1Con ? ON_CONDITION : 0;
        gameData.aiSkillCondition[1] |= netData.Skill1PreCon == 0 ? ON_MOBS_NEARBY : ON_MOBS_ATTACKING;
        gameData.aiSkillCondition[1] |= netData.Skill1SubCon == 0 ? ON_MORE_THAN_TWO_MOBS :
            netData.Skill1SubCon == 1 ? ON_MORE_THAN_THREE_MOBS :
            netData.Skill1SubCon == 2 ? ON_MORE_THAN_FOUR_MOBS :
            netData.Skill1SubCon == 3 ? ON_MORE_THAN_FIVE_MOBS :
            0;

        gameData.aiSkillCondition[2] |= netData.Skill2Delay ? ON_TIMER : 0;
        gameData.aiSkillCondition[2] |= netData.Skill2Con ? ON_CONDITION : 0;
        gameData.aiSkillCondition[2] |= netData.Skill2PreCon == 0 ? ON_MOBS_NEARBY : ON_MOBS_ATTACKING;
        gameData.aiSkillCondition[2] |= netData.Skill2SubCon == 0 ? ON_MORE_THAN_TWO_MOBS :
            netData.Skill2SubCon == 1 ? ON_MORE_THAN_THREE_MOBS :
            netData.Skill2SubCon == 2 ? ON_MORE_THAN_FOUR_MOBS :
            netData.Skill2SubCon == 3 ? ON_MORE_THAN_FIVE_MOBS :
            0;
        gameData.bUseCombo = (bool)netData.Combo;

        gameData.aiBuff.fill(0);
        gameData.aiBuff[0] = static_cast<int>(netData.BuffSkill0NumberID);
        gameData.aiBuff[1] = static_cast<int>(netData.BuffSkill1NumberID);
        gameData.aiBuff[2] = static_cast<int>(netData.BuffSkill2NumberID);

        gameData.bBuffDuration = (bool)netData.BuffDuration;
        gameData.bBuffDurationParty = (bool)netData.BuffDurationforAllPartyMembers;
        gameData.iBuffCastInterval = static_cast<int>(netData.CastingBuffMin);

        gameData.bAutoHeal = (bool)netData.AutoHeal;
        gameData.iHealThreshold = static_cast<int>(netData.HPStatusAutoHeal) * 10;
        gameData.bUseDrainLife = static_cast<int>(netData.DrainLife);
        gameData.bUseHealPotion = (bool)netData.AutoPotion;
        gameData.iPotionThreshold = static_cast<int>(netData.HPStatusAutoPotion) * 10;
        gameData.bSupportParty = (bool)netData.Party;
        gameData.bAutoHealParty = (bool)netData.PreferenceOfPartyHeal;
        gameData.iHealPartyThreshold = static_cast<int>(netData.HPStatusOfPartyMembers) * 10;

        gameData.bUseDarkRaven = (bool)netData.UseDarkSpirits;
        gameData.iDarkRavenMode = static_cast<int>(netData.PetAttack);
        gameData.bRepairItem = (bool)netData.RepairItem;

        gameData.iObtainingRange = static_cast<int>(netData.ObtainRange);
        gameData.bPickAllItems = (bool)netData.PickAllNearItems;
        gameData.bPickSelectItems = (bool)netData.PickSelectedItems;
        gameData.bPickZen = (bool)netData.Zen;
        gameData.bPickJewel = (bool)netData.JewelOrGem;
        gameData.bPickExcellent = (bool)netData.ExcellentItem;
        gameData.bPickAncient = (bool)netData.SetItem;
        gameData.bPickExtraItems = (bool)netData.AddExtraItem;

        wchar_t wsExtraItemBuffer[15 + 1];
        for (int i = 0; i < sizeof(netData.ExtraItems) / sizeof(netData.ExtraItems[0]); i++)
        {
            memset(wsExtraItemBuffer, 0, sizeof(wsExtraItemBuffer));

            size_t n = std::mbstowcs(wsExtraItemBuffer, &netData.ExtraItems[i][0], 15);
            if (n > 0 && n <= 15)
            {
                wsExtraItemBuffer[n] = L'\0';
                if (wsExtraItemBuffer[0] != L'\0')
                {
                    gameData.aExtraItems.insert(std::wstring(wsExtraItemBuffer));
                }
            }
        }
    }

}


MuHelperData.h


#pragma once

#include <cstdint>
#include <set>
#include <array>
#include <string>
#include "WSclient.h"

namespace MUHelper
{
enum ESkillActivationBase : uint32_t
{
ALWAYS = 0x00000000,
ON_TIMER = 0x00000001,
ON_CONDITION = 0x00000002,
};

enum ESkillActivationPreCon : uint32_t
{
ON_MOBS_NEARBY = 0x00000004,
ON_MOBS_ATTACKING = 0x00000008
};

enum ESkillActivationSubCon : uint32_t
{
ON_MORE_THAN_TWO_MOBS = 0x00000010,
ON_MORE_THAN_THREE_MOBS = 0x00000020,
ON_MORE_THAN_FOUR_MOBS = 0x00000040,
ON_MORE_THAN_FIVE_MOBS = 0x00000080
};

DEFINE_ENUM_FLAG_OPERATORS(ESkillActivationBase);
DEFINE_ENUM_FLAG_OPERATORS(ESkillActivationPreCon);
DEFINE_ENUM_FLAG_OPERATORS(ESkillActivationSubCon);

constexpr uint32_t MUHELPER_SKILL_PRECON_CLEAR =
~(static_cast<uint32_t>(ON_MOBS_NEARBY) |
static_cast<uint32_t>(ON_MOBS_ATTACKING));

constexpr uint32_t MUHELPER_SKILL_SUBCON_CLEAR =
~(static_cast<uint32_t>(ON_MORE_THAN_TWO_MOBS) |
static_cast<uint32_t>(ON_MORE_THAN_THREE_MOBS) |
static_cast<uint32_t>(ON_MORE_THAN_FOUR_MOBS) |
static_cast<uint32_t>(ON_MORE_THAN_FIVE_MOBS));

enum EPetAttackMode : BYTE
{
PET_ATTACK_CEASE = 0x00,
PET_ATTACK_AUTO = 0x01,
PET_ATTACK_TOGETHER = 0x02
};

typedef struct
{
int iHuntingRange = 0;

bool bLongRangeCounterAttack = false;
bool bReturnToOriginalPosition = false;
int iMaxSecondsAway = 0;

std::array<uint32_t, 3> aiSkill = { 0, 0, 0 };
std::array<uint32_t, 3> aiSkillCondition = { 0, 0, 0 };
std::array<uint32_t, 3> aiSkillInterval = { 0, 0, 0 };

bool bUseCombo = false;

std::array<uint32_t, 3> aiBuff = { 0, 0, 0 };

bool bBuffDuration = false;
bool bBuffDurationParty = false;
int iBuffCastInterval = 0;

bool bAutoHeal = false;
int iHealThreshold = 0;
bool bSupportParty = false;
bool bAutoHealParty = false;
int iHealPartyThreshold = 0;

bool bUseHealPotion = false;
int iPotionThreshold = 0;

bool bUseDrainLife = false;
bool bUseDarkRaven = false;
int iDarkRavenMode = 0;

bool bRepairItem = false;

int iObtainingRange = 0;
bool bPickAllItems = false;
bool bPickSelectItems = false;
bool bPickJewel = false;
bool bPickZen = false;
bool bPickAncient = false;
bool bPickExcellent = false;
bool bPickExtraItems = false;
std::set<std::wstring> aExtraItems;

bool bUseSelfDefense = false;
bool bAutoAcceptFriend = false;
bool bAutoAcceptGuild = false;
} ConfigData;

class ConfigDataSerDe {
public:
static void Serialize(const ConfigData& domain, PRECEIVE_MUHELPER_DATA& packet);
static void Deserialize(const PRECEIVE_MUHELPER_DATA& packet, ConfigData& domain);
};
}
Bon Dia

🡱 🡳