Jump to content

Magic Stone & Blessing Scroll - They won´t dissapear after


Go to solution Solved by Mind Rapist,

Recommended Posts

Dear Users,

Blessing Scroll and Magic Metal are not consumed (deleted) after use.
Additionally, when refinement fails, the target item disappears instead of behaving correctly (e.g. downgrade) etc.

char_item.cpp : 

Quote

 

enum enum_RefineScrolls
{
    CHUKBOK_SCROLL = 0,
    HYUNIRON_CHN   = 1, // 중국에서만 사용
    YONGSIN_SCROLL = 2,
    MUSIN_SCROLL   = 3,
    YAGONG_SCROLL  = 4,
    MEMO_SCROLL       = 5,
    BDRAGON_SCROLL    = 6,
};

bool CHARACTER::DoRefineWithScroll(LPITEM item)
{
    if (!CanHandleItem(true))
    {
        ClearRefineMode();
        return false;
    }

    ClearRefineMode();

    //개량 시간제한 : upgrade_refine_scroll.quest 에서 개량후 5분이내에 일반 개량을 
    //진행할수 없음
    if (quest::CQuestManager::instance().GetEventFlag("update_refine_time") != 0)
    {
        if (get_global_time() < quest::CQuestManager::instance().GetEventFlag("update_refine_time") + (60 * 5))
        {
            sys_log(0, "can't refine %d %s", GetPlayerID(), GetName());
            return false;
        }
    }

    const TRefineTable * prt = CRefineManager::instance().GetRefineRecipe(item->GetRefineSet());

    if (!prt)
        return false;

    LPITEM pkItemScroll;

    // 개량서 체크
    if (m_iRefineAdditionalCell < 0)
        return false;

    pkItemScroll = GetInventoryItem(m_iRefineAdditionalCell);

    if (!pkItemScroll)
        return false;

    if (!(pkItemScroll->GetType() == ITEM_USE && pkItemScroll->GetSubType() == USE_TUNING))
        return false;

    if (pkItemScroll->GetVnum() == item->GetVnum())
        return false;

    DWORD result_vnum = item->GetRefinedVnum();
    DWORD result_fail_vnum = item->GetRefineFromVnum();

    if (result_vnum == 0)
    {
        ChatPacket(CHAT_TYPE_INFO, LC_TEXT("더 이상 개량할 수 없습니다."));
        return false;
    }

    // MUSIN_SCROLL
    if (pkItemScroll->GetValue(0) == MUSIN_SCROLL)
    {
        if (item->GetRefineLevel() >= 4)
        {
            ChatPacket(CHAT_TYPE_INFO, LC_TEXT("이 개량서로 더 이상 개량할 수 없습니다."));
            return false;
        }
    }
    // END_OF_MUSIC_SCROLL

    else if (pkItemScroll->GetValue(0) == MEMO_SCROLL)
    {
        if (item->GetRefineLevel() != pkItemScroll->GetValue(1))
        {
            ChatPacket(CHAT_TYPE_INFO, LC_TEXT("이 개량서로 개량할 수 없습니다."));
            return false;
        }
    }
    else if (pkItemScroll->GetValue(0) == BDRAGON_SCROLL)
    {
        if (item->GetType() != ITEM_METIN || item->GetRefineLevel() != 4)
        {
            ChatPacket(CHAT_TYPE_INFO, LC_TEXT("이 아이템으로 개량할 수 없습니다."));
            return false;
        }
    }

    TItemTable * pProto = ITEM_MANAGER::instance().GetTable(item->GetRefinedVnum());

    if (!pProto)
    {
        sys_err("DoRefineWithScroll NOT GET ITEM PROTO %d", item->GetRefinedVnum());
        ChatPacket(CHAT_TYPE_INFO, LC_TEXT("이 아이템은 개량할 수 없습니다."));
        return false;
    }

    // Check level limit in korea only
    if (!g_iUseLocale)
    {
        for (int i = 0; i < ITEM_LIMIT_MAX_NUM; ++i)
        {
            long limit = pProto->aLimits[i].lValue;

            switch (pProto->aLimits[i].bType)
            {
                case LIMIT_LEVEL:
                    if (GetLevel() < limit)
                    {
                        ChatPacket(CHAT_TYPE_INFO, LC_TEXT("개량된 후 아이템의 레벨 제한보다 레벨이 낮습니다."));
                        return false;
                    }
                    break;
            }
        }
    }

    if (GetGold() < prt->cost)
    {
        ChatPacket(CHAT_TYPE_INFO, LC_TEXT("개량을 하기 위한 돈이 부족합니다."));
        return false;
    }

    for (int i = 0; i < prt->material_count; ++i)
    {
        if (CountSpecifyItem(prt->materials[i].vnum) < prt->materials[i].count)
        {
            if (test_server)
            {
                ChatPacket(CHAT_TYPE_INFO, "Find %d, count %d, require %d", prt->materials[i].vnum, CountSpecifyItem(prt->materials[i].vnum), prt->materials[i].count);
            }
            ChatPacket(CHAT_TYPE_INFO, LC_TEXT("개량을 하기 위한 재료가 부족합니다."));
            return false;
        }
    }

    for (int i = 0; i < prt->material_count; ++i)
        RemoveSpecifyItem(prt->materials[i].vnum, prt->materials[i].count);

    int prob = number(1, 100);
    int success_prob = prt->prob;
    bool bDestroyWhenFail = false;

    const char* szRefineType = "SCROLL";

    if (pkItemScroll->GetValue(0) == HYUNIRON_CHN || 
        pkItemScroll->GetValue(0) == YONGSIN_SCROLL || 
        pkItemScroll->GetValue(0) == YAGONG_SCROLL) // 현철, 용신의 축복서, 야공의 비전서  처리
    {
        const char hyuniron_prob[9] = { 100, 75, 65, 55, 45, 40, 35, 25, 20 };
        const char hyuniron_prob_euckr[9] = { 100, 75, 65, 55, 45, 40, 35, 30, 25 };

        const char yagong_prob[9] = { 100, 100, 90, 80, 70, 60, 50, 30, 20 };
        const char yagong_prob_euckr[9] = { 100, 100, 90, 80, 70, 60, 50, 40, 30 };

        if (pkItemScroll->GetValue(0) == YONGSIN_SCROLL)
        {
            if (LC_IsYMIR() == true || LC_IsKorea() == true)
                success_prob = hyuniron_prob_euckr[MINMAX(0, item->GetRefineLevel(), 8)];
            else
                success_prob = hyuniron_prob[MINMAX(0, item->GetRefineLevel(), 8)];
        }
        else if (pkItemScroll->GetValue(0) == YAGONG_SCROLL)
        {
            if (LC_IsYMIR() == true || LC_IsKorea() == true)
                success_prob = yagong_prob_euckr[MINMAX(0, item->GetRefineLevel(), 8)];
            else
                success_prob = yagong_prob[MINMAX(0, item->GetRefineLevel(), 8)];
        }
        else
        {
            sys_err("REFINE : Unknown refine scroll item. Value0: %d", pkItemScroll->GetValue(0));
        }

        if (test_server) 
        {
            ChatPacket(CHAT_TYPE_INFO, "[Only Test] Success_Prob %d, RefineLevel %d ", success_prob, item->GetRefineLevel());
        }
        if (pkItemScroll->GetValue(0) == HYUNIRON_CHN) // 현철은 아이템이 부서져야 한다.
            bDestroyWhenFail = true;

        // DETAIL_REFINE_LOG
        if (pkItemScroll->GetValue(0) == HYUNIRON_CHN)
        {
            szRefineType = "HYUNIRON";
        }
        else if (pkItemScroll->GetValue(0) == YONGSIN_SCROLL)
        {
            szRefineType = "GOD_SCROLL";
        }
        else if (pkItemScroll->GetValue(0) == YAGONG_SCROLL)
        {
            szRefineType = "YAGONG_SCROLL";
        }
        // END_OF_DETAIL_REFINE_LOG
    }

    // DETAIL_REFINE_LOG
    if (pkItemScroll->GetValue(0) == MUSIN_SCROLL) // 무신의 축복서는 100% 성공 (+4까지만)
    {
        success_prob = 100;

        szRefineType = "MUSIN_SCROLL";
    }
    // END_OF_DETAIL_REFINE_LOG
    else if (pkItemScroll->GetValue(0) == MEMO_SCROLL)
    {
        success_prob = 100;
        szRefineType = "MEMO_SCROLL";
    }
    else if (pkItemScroll->GetValue(0) == BDRAGON_SCROLL)
    {
        success_prob = 80;
        szRefineType = "BDRAGON_SCROLL";
    }

    pkItemScroll->SetCount(pkItemScroll->GetCount() - 1);

    if (prob <= success_prob)
    {
        // 성공! 모든 아이템이 사라지고, 같은 속성의 다른 아이템 획득
        LPITEM pkNewItem = ITEM_MANAGER::instance().CreateItem(result_vnum, 1, 0, false);

        if (pkNewItem)
        {
            ITEM_MANAGER::CopyAllAttrTo(item, pkNewItem);
            LogManager::instance().ItemLog(this, pkNewItem, "REFINE SUCCESS", pkNewItem->GetName());

            BYTE bCell = item->GetCell();

            NotifyRefineSuccess(this, item, szRefineType);
            DBManager::instance().SendMoneyLog(MONEY_LOG_REFINE, item->GetVnum(), -prt->cost);
            ITEM_MANAGER::instance().RemoveItem(item, "REMOVE (REFINE SUCCESS)");

            pkNewItem->AddToCharacter(this, TItemPos(INVENTORY, bCell)); 
            ITEM_MANAGER::instance().FlushDelayedSave(pkNewItem);
            pkNewItem->AttrLog();
            //PointChange(POINT_GOLD, -prt->cost);
            PayRefineFee(prt->cost);
        }
        else
        {
            // 아이템 생성에 실패 -> 개량 실패로 간주
            sys_err("cannot create item %u", result_vnum);
            NotifyRefineFail(this, item, szRefineType);
        }
    }
    else if (!bDestroyWhenFail && result_fail_vnum)
    {
        // 실패! 모든 아이템이 사라지고, 같은 속성의 낮은 등급의 아이템 획득
        LPITEM pkNewItem = ITEM_MANAGER::instance().CreateItem(result_fail_vnum, 1, 0, false);

        if (pkNewItem)
        {
            ITEM_MANAGER::CopyAllAttrTo(item, pkNewItem);
            LogManager::instance().ItemLog(this, pkNewItem, "REFINE FAIL", pkNewItem->GetName());

            BYTE bCell = item->GetCell();

            DBManager::instance().SendMoneyLog(MONEY_LOG_REFINE, item->GetVnum(), -prt->cost);
            NotifyRefineFail(this, item, szRefineType, -1);
            ITEM_MANAGER::instance().RemoveItem(item, "REMOVE (REFINE FAIL)");

            pkNewItem->AddToCharacter(this, TItemPos(INVENTORY, bCell)); 
            ITEM_MANAGER::instance().FlushDelayedSave(pkNewItem);

            pkNewItem->AttrLog();

            //PointChange(POINT_GOLD, -prt->cost);
            PayRefineFee(prt->cost);
        }
        else
        {
            // 아이템 생성에 실패 -> 개량 실패로 간주
            sys_err("cannot create item %u", result_fail_vnum);
            NotifyRefineFail(this, item, szRefineType);
        }
    }
    else
    {
        NotifyRefineFail(this, item, szRefineType); // 개량시 아이템 사라지지 않음
        
        PayRefineFee(prt->cost);
    }

    return true;
}

 

 

  • Active+ Member
  • Solution
17 hours ago, Edem said:

Dear Users,

Blessing Scroll and Magic Metal are not consumed (deleted) after use.
Additionally, when refinement fails, the target item disappears instead of behaving correctly (e.g. downgrade) etc.

char_item.cpp : 

 

Your issue is either in char_item.cpp inside bool CHARACTER::RefineInformation(BYTE bCell, BYTE bType, int iAdditionalCell).

Make sure you are sending the REFINE_INFORMATION_NEW packet and not the REFINE_INFORMATION.

 

Also in your UserInterface/PythonNetworkStreamPhaseGame.cpp (client source) make sure you are exporting everything correctly.

The client's equivalent of your server's REFINE_INFORMATION_NEW must be calling this function from inside the packet handling switch statement: bool CPythonNetworkStream::RecvRefineInformationPacketNew().

And finally unless you have modifications regarding Python exposure, your RecvRefineInformationPacketNew() should be calling this:

PyCallClassMemberFunc(m_apoPhaseWnd[PHASE_WINDOW_GAME], "OpenRefineDialog", Py_BuildValue("(iiiii)", kRefineInfoPacket.pos, kRefineInfoPacket.refine_table.result_vnum, rkRefineTable.cost, rkRefineTable.prob, kRefineInfoPacket.type));

Edited by Mind Rapist
made a little mistake in the instructions
  • muscle 1
  • Active+ Member
2 hours ago, Edem said:

@ Mind Rapist Thank you so much for your answer, it helped me. I had to code it to my source, but now it works. 🙂 

Coincidense I fixed that same exact issue 1 or 2 days ago so it was fresh in memory 😂 keep it up brother!

Don't use any images from : imgur, turkmmop, freakgamers, inforge, hizliresim... Or your content will be deleted without notice...
Use : https://metin2.download/media/add/

Please use https://metin2.download/ when uploading files smaller than 100MB, otherwise the approval will take longer due to manual upload.

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
×
×
  • Create New...

Important Information

Terms of Use / Privacy Policy / Guidelines / We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.