Item Drop Rates

08/04/2026 04:27 breeland#1
Hello, I have been messing around creating a server that i will just localhost.

I have been trying to find information on some rates for Conquer right around 2.0 release, so between 2004-2005. I haven't had much luck, so I have had to rely mostly on memory. But does anyone know, or have a general idea what the rates were for the following?

Refined Item Drop Rate:
Unique Item Drop Rate:
Elite Item Drop Rate:
Super Item Drop Rate:
1-Socket Weapon Drop Rate:
2-Socket Weapon Drop Rate:
+1 Item Drop Rate:
Meteor Drop Rate:
DragonBall Drop Rate:
Normal Gem Rate:
Refined Gem Rate:
Super Gem Rate:
Socket Chance using a Meteor:
Socket Chance using a Dragonball:

Also,

were there different rates for different different classes?

Were there different rates for weapons/armor/accessories?

-------------------------------

I'm under the impression that it was the following, but any feedback helps.

Item Drop Chance: 12%
Refined Item Drop Rate: 0.05% (1 in 2,000 kills)
Unique Item Drop Rate: 0.02% (1 in 5,000 kills)
Elite Item Drop Rate: .005% (1 in 20,000 kills)
Super Item Drop Rate: .0025% (1 in 40,000 kills)
1-Socket Weapon Drop Rate: 20%
2-Socket Weapon Drop Rate: 2%
+1 Item Drop Rate: 0.01% (1 in 10,000 kills)
Meteor Drop Rate: 0.02% (1 in 5,000 kills)
DragonBall Drop Rate: .0025% (1 in 40,000 kills)
Normal Gem Rate: .1736% (Approximately 10 Gems per 24H of Mining)
Refined Gem Rate: .03472% (Approximately 2 Gems per 24H of Mining)
Super Gem Rate: .0116% (Approximately 1 Gems per 36H of Mining)
Socket Chance using a Meteor: 0.25%.
Socket Chance using a Dragonball: 1%

Also,

were there different rates for different classes?
No

Were there different rates for weapons/armor/accessories?
No

Please know, mine are more so an educated guess, based on what I remember things being like from 20 years ago. And can honestly be so far off.

Either way, I am appreciative of any feedback!

Best,
Bree
08/04/2026 20:19 pintinho12#2
I will share you the code I've got from reversing binaries, but ofc this aint from 2005
Code:
void Monster::DropMedicine(uint32_t idOwner)
{
    int roll = FastRandom::NextInt32(100);
    int count;
    if (roll < 2) count = 8;
    else if (roll < 3) count = 6;
    else if (roll < 5) count = 5;
    else if (roll < 8) count = 4;
    else if (roll < 10) count = 3;
    else if (roll < 25) count = 2;
    else count                = 1;

    for (int i = 0; i < count; ++i)
    {
        uint32_t dropMedicine = FastRandom::ChanceCalc(50) ? m_type->dropHp : m_type->dropMp;
        DropItem(dropMedicine, idOwner);
    }
}

bool Monster::GetDropItem(DropItemRecord& itemRecord, uint32_t valueBase, int qualityOverride)
{
    if (valueBase < 1)
    {
        return false;
    }

    int quality;
    if (qualityOverride > -1)
    {
        quality = qualityOverride;
    }
    else
    {
        int random = FastRandom::NextInt32(100);
        if (random < 30)
        {
            quality = 5;
        }
        else if (random < 70)
        {
            quality = 4;
        }
        else
        {
            quality = 3;
        }
    }

    int32_t  itemSubTypeRng = FastRandom::NextInt32(1200);
    uint32_t itemSubType;
    uint32_t itemLev;
    uint8_t  itemColor = 3;
    if (itemSubTypeRng < 20)
    {
        // shoes and talismans
        static constexpr uint32_t specialType[] = {160, 201, 202};
        if (m_type->dropShoes == 99)
        {
            return false;
        }

        itemSubType = specialType[FastRandom::NextInt32(_countof(specialType) - 1)]; // max inclusive
        itemLev     = m_type->dropShoes;
        if (itemSubType == 201 || itemSubType == 202)
        {
            itemLev = 0;
        }
    }
    else if (itemSubTypeRng < 50)
    {
        // necklace and bag
        static constexpr uint32_t dropTypes[] = {120, 121};
        if (m_type->dropNecklace == 99)
        {
            return false;
        }

        itemSubType = dropTypes[FastRandom::NextInt32(_countof(dropTypes) - 1)];
        itemLev     = m_type->dropNecklace;
    }
    else if (itemSubTypeRng < 100)
    {
        // ring, heavy ring and bracelet
        static constexpr uint32_t dropTypes[] = {150, 151, 152};
        if (m_type->dropRing == 99)
        {
            return false;
        }

        itemSubType = dropTypes[FastRandom::NextInt32(_countof(dropTypes) - 1)];
        itemLev     = m_type->dropRing;
    }
    else if (itemSubTypeRng < 400)
    {
        // helmets
        static constexpr uint32_t dropTypes[] = {111, 112, 113, 114, 117, 118, 123, 141, 142};
        if (m_type->dropArmet == 99)
        {
            return false;
        }

        itemSubType = dropTypes[FastRandom::NextInt32(_countof(dropTypes) - 1)];
        itemLev     = m_type->dropArmet;
        itemColor   = static_cast<uint8_t>(FastRandom::NextUInt32(3, 9));
    }
    else if (itemSubTypeRng < 700)
    {
        // armors
        static constexpr uint32_t dropTypes[] = {130, 131, 132, 133, 134, 135};
        if (m_type->dropArmor == 99)
        {
            return false;
        }

        itemSubType = dropTypes[FastRandom::NextInt32(_countof(dropTypes) - 1)];
        itemLev     = m_type->dropArmor;
        itemColor   = static_cast<uint8_t>(FastRandom::NextUInt32(3, 9));
    }
    else
    {
        if (m_type->dropWeapon == 99)
        {
            return false;
        }

        // drop weapons
        int dropRng = FastRandom::NextInt32(100);
        if (dropRng < 20)
        {
            // drop backsword
            itemSubType = 421;
            itemLev     = m_type->dropWeapon;
        }
        else if (dropRng < 40)
        {
            // drop nothing
            return false;
        }
        else if (dropRng < 80)
        {
            // single hand weapons and bow
            static constexpr uint32_t dropTypes[] = {410, 420, 430, 440, 450, 460, 480, 481, 490, 500, 601};
            itemSubType                           = dropTypes[FastRandom::NextInt32(_countof(dropTypes) - 1)];
            itemLev                               = m_type->dropWeapon;
        }
        else
        {
            // double hand and shield
            static constexpr uint32_t dropTypes[] = {510, 530, 560, 580, 900};
            itemSubType                           = dropTypes[FastRandom::NextInt32(_countof(dropTypes) - 1)];
            itemLev                               = m_type->dropWeapon;
        }

        itemColor = static_cast<uint8_t>(FastRandom::NextUInt32(3, 9));
    }

    if (itemLev == 99)
    {
        return false;
    }

    int levelAdustment = FastRandom::NextInt32(100);
    if (levelAdustment < 50)
    {
        int adjusted = (int)itemLev / 3 + FastRandom::NextInt32((int)itemLev / 2);
        itemLev      = adjusted > 0 ? adjusted - 1 : 0;
    }
    else if (levelAdustment < 80)
    {
        // keep level
    }
    else
    {
        bool isLowTier = (itemSubType >= 110 && itemSubType <= 114)
                         || (itemSubType >= 130 && itemSubType <= 134)
                         || (itemSubType >= 900 && itemSubType <= 999);
        uint32_t cap = isLowTier ? 9 : 23;
        itemLev      = __min(itemLev + 1, cap);
    }

    uint32_t           itemTypeId = itemSubType * 1000 + itemLev * 10 + quality;
    const ItemTypeStr* itemType   = ItemManager().GetItemType(itemTypeId);
    if (!itemType)
    {
        return false;
    }

    memset(&itemRecord, 0, sizeof(DropItemRecord));

    itemRecord.type           = itemTypeId;
    float   amountLimit       = (float)itemType->amountLimit;
    int64_t amountLimitScaled = (int64_t)(FastRandom::NextFloat(0.7f, 1.3f) * amountLimit);
    if (amountLimitScaled < 1)
    {
        amountLimitScaled = 1;
    }
    itemRecord.amountLimit = (uint32_t)amountLimitScaled;
    itemRecord.amount      = (uint32_t)amountLimitScaled;

    if (quality <= 5)
    {
        uint32_t price = itemType->price;
        if (price == 0) price = 1;
        uint32_t amount   = 3 * itemType->amount * itemType->amountLimit / price;
        itemRecord.amount = __max(1u, __min(itemRecord.amountLimit, amount));
    }
    else
    {
        itemRecord.amount = itemRecord.amountLimit * (FastRandom::NextUInt32(50) + 50) / 100;
    }

    if (itemTypeId >= 400000 && itemTypeId < 600000)
    {
        int socketChance = FastRandom::NextInt32(100);
        if (socketChance < 5)
        {
            itemRecord.socketNum = 2;
        }
        else if (socketChance < 20)
        {
            itemRecord.socketNum = 1;
        }
    }

    // AddLev 0.33% chance.
    if (FastRandom::NextInt32(300) == 123)
    {
        itemRecord.magic3 = 1;
    }

    if (itemRecord.socketNum == 0)
    {
        int divisor = Item::IsBow(itemTypeId) ? 60 : 300;
        if (FastRandom::NextInt32(divisor) == 13)
        {
            if (FastRandom::ChanceCalc(30))
            {
                itemRecord.bless = 5;
            }
            else
            {
                itemRecord.bless = 3;
            }
        }
    }

    itemRecord.color = itemColor;

    if (itemSubType == 201 || itemSubType == 202)
    {
        itemRecord.bless = 0;
    }
    return true;
}

void Monster::DropEquipment(uint32_t itemTypeId, uint32_t idOwner, int quality)
{
    CHECK(itemTypeId != 0);

    if (itemTypeId < 100)
    {
        DropMoney(itemTypeId, idOwner);
        return;
    }

    DropItemRecord itemRecord{};
    if (!GetDropItem(itemRecord, itemTypeId, quality))
    {
        return;
    }

    POINT pos;
    pos.x = GetMapX();
    pos.y = GetMapY();
    if (!GetMap()->FindDropItemCell(2, pos))
    {
        return;
    }

    itemTypeId    = itemRecord.type;
    User* pKiller = (User*)GetMap()->QueryUser(idOwner);
    if (pKiller)
    {
        bool effect = false;
        if (itemTypeId % 10 == 9)
        {
            pKiller->SendSysMsg("STR_LUCK_ULTRA_EQ");
            effect = true;
        }
        else if (itemTypeId == TYPE_DRAGONBALL)
        {
            pKiller->SendSysMsg("STR_LUCK_DRAGON_BALL");
            effect = true;
        }
        else if (itemTypeId == TYPE_DIVOICEITEM)
        {
            pKiller->SendSysMsg("STR_LUCK_SHT_STAR_TEAR");
            effect = true;
        }

        if (effect)
        {
            pKiller->BroadcastEffect(LUCKY_GUY);
        }

        // A looted +N item (magic3 = add-level > 0) credits the looter's
        // mentor(s) with composition/add-level points. The value comes from
        // cq_student_type.Addlevel; magic3 only gates the event.
        if (itemRecord.magic3 > 0)
        {
            if (IGuideProvider* guide = QueryGuideProvider(ModuleManager().GetProvider(ModuleId::Guide)))
                guide->AwardAddLevel(pKiller, itemRecord.magic3);
        }
    }

    uint32_t newId    = RoleManager().GetNextMapItemId();
    MapItem* pMapItem = MapItem::CreateNew();
    if (pMapItem->Create(newId, GetMap(), pos, itemRecord, idOwner))
    {
        return;
    }

    GM_LOG("gmlog/dropitem", "Monster::DropEquipment(): monster_type[%d], item_type[%u]", GetTypeId(), itemTypeId);
    pMapItem->Release();
    RoleManager().RecycleMapItemId(newId);
}

void Monster::BeKill(IRole* pAttacker)
{
    if (IsDeleted())
    {
        return;
    }

    if (statusSet_)
    {
        statusSet_->AddKeepEffect1(KEEPEFFECT_FADE | KEEPEFFECT_GHOST);
    }

    uint32_t idOwnerItem = 0;
    GameMap* pMap        = GetMap();
    User*    pUser       = nullptr;
    if (pAttacker->QueryObj(OBJ_USER, IPP_OF(pUser)))
    {
        idOwnerItem = pUser->GetId();
    }

    if (GetId() >= CALLPETID_FIRST && GetId() <= CALLPETID_LAST)
    {
        // call pet bomb logic like my_server
    }

    uint32_t dropMoney = m_type->dropMoney;
    int      seed      = (int)dropMoney * 2;
    if (GetLevel() > 60)
    {
        int r = FastRandom::NextInt32(100);
        if (r < 3)
        {
            uint32_t budget = 1320u * seed / 100u;
            int      splits;
            switch (FastRandom::NextInt32(4))
            {
            case 0: splits = 5;
                break;
            case 1: splits = 6;
                break;
            case 2: splits = 7;
                break;
            default: splits = 8;
                break;
            }
            int perPacket = budget / splits;
            for (int i = 0; i < splits; ++i)
            {
                uint32_t amount = (uint32_t)(FastRandom::NextFloat(0.8f) * perPacket);
                if (FastRandom::NextInt32(100) >= 40)
                {
                    DropMoney(amount, idOwnerItem);
                }
                else
                {
                    DropEquipment(amount, idOwnerItem);
                }
            }
        }
        else if (r < 35)
        {
            uint32_t budget = 180 * seed / 100u;

            int r2 = FastRandom::NextInt32(100);
            int splits;
            if (r2 > 40)
            {
                splits = 1;
            }
            else if (r2 >= 10)
            {
                splits = 2;
            }
            else
            {
                splits = 1;
            }

            int perPacket = budget / splits;
            for (int i = 0; i < splits; ++i)
            {
                uint32_t amount = (uint32_t)(FastRandom::NextFloat(0.8f) * perPacket);
                if (FastRandom::NextInt32(100) >= 40)
                {
                    DropMoney(amount, idOwnerItem);
                }
                else
                {
                    DropEquipment(amount, idOwnerItem);
                }
            }
        }
        // no drop at all
    }
    else
    {
        int r = FastRandom::NextInt32(100);
        if (r < 2)
        {
            uint32_t budget = 2000u * seed / 100u;
            int      splits;
            switch (FastRandom::NextInt32(4))
            {
            case 0: splits = 5;
                break;
            case 1: splits = 6;
                break;
            case 2: splits = 7;
                break;
            default: splits = 8;
                break;
            }
            int perPacket = budget / splits;
            for (int i = 0; i < splits; ++i)
            {
                uint32_t amount = (uint32_t)(FastRandom::NextFloat(0.8f) * perPacket);
                if (FastRandom::NextInt32(100) >= 40)
                {
                    DropMoney(amount, idOwnerItem);
                }
                else
                {
                    DropEquipment(amount, idOwnerItem);
                }
            }
        }
        else if (r < 27)
        {
            uint32_t budget = 240 * seed / 100u;
            int      r2     = FastRandom::NextInt32(100);
            int      splits;
            if (r2 > 40)
            {
                splits = 1;
            }
            else if (r2 >= 10)
            {
                splits = 2;
            }
            else
            {
                splits = 1;
            }

            int perPacket = budget / splits;
            for (int i = 0; i < splits; ++i)
            {
                uint32_t amount = (uint32_t)(FastRandom::NextFloat(0.8f) * perPacket);
                if (FastRandom::NextInt32(100) >= 40)
                {
                    DropMoney(amount, idOwnerItem);
                }
                else
                {
                    DropEquipment(amount, idOwnerItem);
                }
            }
        }
        // no drop at all
    }

    // equipment drop
    int qualityItemRng = FastRandom::NextInt32(50000);
    if (qualityItemRng < 1)
    {
        bool doDrop;
        if (GetLevel() <= 80)
        {
            doDrop = FastRandom::NextInt32(3) == 1;
        }
        else
        {
            doDrop = FastRandom::NextInt32(10) == 7;
        }

        if (doDrop)
        {
            uint32_t amount = 100u * GetLevel();
            DropEquipment(amount, idOwnerItem, ITEMQUALITY_SUPER);
        }
    }
    else if (qualityItemRng < 6)
    {
        if (GetLevel() <= 80
            && FastRandom::NextInt32(5) == 3)
        {
            uint32_t amount = 100u * GetLevel();
            DropEquipment(amount, idOwnerItem, ITEMQUALITY_ELITE);
        }
    }
    else if (qualityItemRng < 31)
    {
        if (GetLevel() <= 80
            && FastRandom::NextInt32(3) == 1)
        {
            uint32_t amount = 50u * GetLevel();
            DropEquipment(amount, idOwnerItem, ITEMQUALITY_UNIQUE);
        }
    }
    else if (qualityItemRng < 131)
    {
        uint32_t amount = 30u * GetLevel();
        DropEquipment(amount, idOwnerItem, ITEMQUALITY_REFINED);
    }

    if (FastRandom::ChanceCalc(3))
    {
        DropMedicine(idOwnerItem);
    }

    if (pMap)
    {
        if (FastRandom::NextInt32(750) == 123)
        {
            DropItem(TYPE_SHOOTINGSTAR, idOwnerItem);
        }

        if (FastRandom::NextInt32(300000) == 123)
        {
            DropItem(TYPE_DRAGONBALL, idOwnerItem);

            if (pUser)
            {
                pUser->BroadcastRoomMsg("STR_DRAGON_BALL_DROP", pUser->GetName());
                GM_LOG("gmlog/emoney_buy", "%u\t%s\t%u\t%u", pUser->GetId(), pUser->GetName(), TYPE_DRAGONBALL, 1);
            }
        }
    }

    int gemRandChance;
    if (GetLevel() < 117)
    {
        if (pUser
            && pUser->GetLevel() <= GetLevel() + 5)
        {
            gemRandChance = 900;
        }
        else
        {
            gemRandChance = 9000;
        }
    }
    else
    {
        gemRandChance = 1400;
    }

    if (FastRandom::NextInt32(gemRandChance) == 13)
    {
        int      gemRoll = FastRandom::NextInt32(1200);
        uint32_t itemType;
        if (gemRoll < 100) itemType = 700011;
        else if (gemRoll < 200) itemType = 700001;
        else if (gemRoll < 300) itemType = 700031;
        else if (gemRoll < 400) itemType = 700101;
        else if (gemRoll < 500) itemType = 700121;
        else if (gemRoll < 675) itemType = 700061;
        else if (gemRoll < 850) itemType = 700051;
        else if (gemRoll < 1025) itemType = 700041;
        else itemType                     = 700021;

        DropItem(itemType, idOwnerItem);
    }

    if (GetId() < CALLPETID_FIRST || GetId() > CALLPETID_LAST)
    {
        DropCommonItem(idOwnerItem);
    }

    if (pUser)
    {
        GameAction::ExecuteAction(m_type->action, pUser, this);
    }

    if (m_type->type == 25) // unsure what this would mean
    {
        User* pOwner = (User*)QueryUser();
        if (pOwner)
        {
            pOwner->SetAttributes(USERATTRIB_LIFE, 0, SYNCHRO_TRUE);
            pOwner->BeKill(pAttacker);
        }
    }

    DelMonster(false);
}
glhf
08/07/2026 15:10 dolhabogdan#3
Quote:
Originally Posted by pintinho12 View Post
I will share you the code I've got from reversing binaries, but ofc this aint from 2005
glhf
By any chance do you have the monster spawns and the PVE damage calculations? :handsdown: