Expanded Reload Commands

Metin2Hub Bot
M2Hub Bot
Feb
Threads
65
2,005
2
842
113
HubMoney
1,213

Hidden content
You need to reply to this thread in order to see this content.


Hi there devs,



I made some new reload commands about 2 weeks ago and published a tutorial about it on our Hungarian forum (you may saw them in the samurai core) and today I had some time to make the translation.

What can I reload now?

  • refine_proto (this is the only one which is not mine, its @xP3NG3Rx's, and already public here, but I added it, because I think this package has to contain it
    ;)
    ) command: /reload p
  • shop_item table (npc's shops) command: /reload p
  • item_attr && item_attr_rare table; command: /reload p
  • etc_drop_item.txt, mob_drop_item.txt, special_item_group.txt; command: /reload drop
  • group.txt, group_group.txt; command: /reload group
  • regen.txt, npc.txt, boss.txt, stone.txt (only on the current map) command: /reload regen
  • because of the new "reload regen" command, I had to write a new purge command that destroys all mobs, npcs, stones (and so on...) on the current map, so I added a new /p map command to the "/p" commands that are already exists (no, the "/p all" only destroys the mobs on the current sectree (current block))
  • also I had to create a new command that stops all the regens (and ofc. deletes them from the memory) on the current map, so I added a new "/free_regens" command (because why not
    B)
    ) Its only deletes the loaded regens, and prevents the mobs from respawning (its not necessary to use this before the /reload regen)

Known bug

  • Well its not a serious problem, but for some unknown reason, when I'm debugging the core on windows server (no, not debug mode, but vs 13's debugger) and I try to do /reload regen, the core starts to consume ~40% cpu, and doesn't want to do anything (so stops working, but doesn't crash). It has no affect on FreeBSD and release or debug mode (without visual studio's debugger) on windows.



Spoiler

If you get fcked up codes like me, try to remove the pagestyle in your browser.
mz7XE.jpg



Code:
game/src



cmd.cpp



Spoiler



Add this to the top of the file (where you can find more ACMDs)









ACMD(do_free_regen);



Then above this:









    { "who",        do_who,            0,            POS_DEAD,    GM_IMPLEMENTOR    },



Add this:









    { "free_regens", do_free_regen,    0,            POS_DEAD,    GM_IMPLEMENTOR    },



 





cmd_gm.cpp



Spoiler



Add this to the end of the file:









ACMD(do_free_regen)

{

    ch->ChatPacket(CHAT_TYPE_INFO, "freeing regens on mapindex %ld", ch->GetMapIndex());

    regen_free_map(ch->GetMapIndex());

    ch->ChatPacket(CHAT_TYPE_INFO, "the regens now FREEEE! :)");

}



Replace the ACMD(do_purge) with this:









ACMD(do_purge)

{

    char arg1[256];

    one_argument(argument, arg1, sizeof(arg1));



    FuncPurge func(ch);



    if (*arg1 && !strcmp(arg1, "map"))

    {

        CHARACTER_MANAGER::instance().DestroyCharacterInMap(ch->GetMapIndex());

    }

    else

    {

        if (*arg1 && !strcmp(arg1, "all"))

            func.m_bAll = true;

        LPSECTREE sectree = ch->GetSectree();

        if (sectree) // #431

            sectree->ForEachAround(func);

        else

            sys_err("PURGE_ERROR.NULL_SECTREE(mapIndex=%d, pos=(%d, %d)", ch->GetMapIndex(), ch->GetX(), ch->GetY());

    }

}



In the ACMD(do_reload) function under this:









            case 'c':    // cube

                // ·ÎÄĂ ÇÁ·ÎĽĽ˝ş¸¸ °»»ęÇŃ´Ů.

                Cube_init ();

                break;



Insert this:









            default:

                const int FILE_NAME_LEN = 256;

                if (strstr(arg1, "drop"))

                {

                    char szETCDropItemFileName[FILE_NAME_LEN];

                    char szMOBDropItemFileName[FILE_NAME_LEN];

                    char szSpecialItemGroupFileName[FILE_NAME_LEN];



                    snprintf(szETCDropItemFileName, sizeof(szETCDropItemFileName),

                        "%s/etc_drop_item.txt", LocaleService_GetBasePath().c_str());

                    snprintf(szMOBDropItemFileName, sizeof(szMOBDropItemFileName),

                        "%s/mob_drop_item.txt", LocaleService_GetBasePath().c_str());

                    snprintf(szSpecialItemGroupFileName, sizeof(szSpecialItemGroupFileName),

                        "%s/special_item_group.txt", LocaleService_GetBasePath().c_str());



                    ch->ChatPacket(CHAT_TYPE_INFO, "Reloading: ETCDropItem: %s", szETCDropItemFileName);

                    if (!ITEM_MANAGER::instance().ReadEtcDropItemFile(szETCDropItemFileName, true))

                        ch->ChatPacket(CHAT_TYPE_INFO, "failed to reload ETCDropItem: %s", szETCDropItemFileName);

                    else

                        ch->ChatPacket(CHAT_TYPE_INFO, "reload success: ETCDropItem: %s", szETCDropItemFileName);



                    ch->ChatPacket(CHAT_TYPE_INFO, "Reloading: SpecialItemGroup: %s", szSpecialItemGroupFileName);

                    if (!ITEM_MANAGER::instance().ReadSpecialDropItemFile(szSpecialItemGroupFileName, true))

                        ch->ChatPacket(CHAT_TYPE_INFO, "failed to reload SpecialItemGroup: %s", szSpecialItemGroupFileName);

                    else

                        ch->ChatPacket(CHAT_TYPE_INFO, "reload success: SpecialItemGroup: %s", szSpecialItemGroupFileName);



                    ch->ChatPacket(CHAT_TYPE_INFO, "Reloading: MOBDropItemFile: %s", szMOBDropItemFileName);

                    if (!ITEM_MANAGER::instance().ReadMonsterDropItemGroup(szMOBDropItemFileName, true))

                        ch->ChatPacket(CHAT_TYPE_INFO, "failed to reload MOBDropItemFile: %s", szMOBDropItemFileName);

                    else

                        ch->ChatPacket(CHAT_TYPE_INFO, "reload success: MOBDropItemFile: %s", szMOBDropItemFileName);

                }

                else if (strstr(arg1, "group"))

                {

                    char szGroupFileName[FILE_NAME_LEN];

                    char szGroupGroupFileName[FILE_NAME_LEN];



                    snprintf(szGroupFileName, sizeof(szGroupGroupFileName),

                        "%s/group.txt", LocaleService_GetBasePath().c_str());

                    snprintf(szGroupGroupFileName, sizeof(szGroupGroupFileName),

                        "%s/group_group.txt", LocaleService_GetBasePath().c_str());



                    ch->ChatPacket(CHAT_TYPE_INFO, "Reloading: mob groups: %s", szGroupFileName);

                    if (!CMobManager::instance().LoadGroup(szGroupFileName, true))

                        ch->ChatPacket(CHAT_TYPE_INFO, "failed to reload mob groups: %s", szGroupFileName);



                    ch->ChatPacket(CHAT_TYPE_INFO, "Reloading: mob group group: %s", szGroupGroupFileName);

                    if (!CMobManager::instance().LoadGroupGroup(szGroupGroupFileName, true))

                        ch->ChatPacket(CHAT_TYPE_INFO, "failed to reload mob group group: %s", szGroupGroupFileName);

                }

                else if (strstr(arg1, "regen"))

                {

                    SendNoticeMap("Reloading regens!", ch->GetMapIndex(), false);

                    regen_free_map(ch->GetMapIndex());

                    CHARACTER_MANAGER::instance().DestroyCharacterInMap(ch->GetMapIndex());

                    regen_reload(ch->GetMapIndex());

                    SendNoticeMap("Regens reloaded!", ch->GetMapIndex(), false);

                }

                break;



 





input_db.cpp



Spoiler



void CInputDB::ReloadProto(const char * c_pData)



Above this:









    CMotionManager::instance().Build();



Add this:









    /*

    * SHOP

    */



    wSize = decode_2bytes(c_pData);

    c_pData += sizeof(WORD);

    sys_log(0, "RELOAD: SHOP: %d", wSize);





    if (wSize)

    {

        CShopManager::instance().Initialize((TShopTable *)c_pData, wSize);

        c_pData += wSize * sizeof(TShopTable);

    }



    /*

    * REFINE

    */

    wSize = decode_2bytes(c_pData);

    c_pData += 2;

    sys_log(0, "RELOAD: REFINE: %d", wSize);



    if (wSize)

    {

        CRefineManager::instance().Initialize((TRefineTable *)c_pData, wSize);

        c_pData += wSize * sizeof(TRefineTable);

    }



    /*

    * ATTR

    */

    wSize = decode_2bytes(c_pData);

    c_pData += 2;

    sys_log(0, "RELOAD: ItemAtt: %d", wSize);



    if (wSize)

    {

        TItemAttrTable * p = (TItemAttrTable *)c_pData;

        g_map_itemAttr.clear();

        for (int i = 0; i < wSize; ++i, ++p)

        {

            if (p->dwApplyIndex >= MAX_APPLY_NUM)

                continue;



            g_map_itemAttr[p->dwApplyIndex] = *p;

            sys_log(0, "ITEM_ATTR[%d]: %s %u", p->dwApplyIndex, p->szApply, p->dwProb);

        }

        c_pData += wSize*sizeof(TItemAttrTable);

    }



    /*

    * ATTR_RARE

    */

    wSize = decode_2bytes(c_pData);

    c_pData += 2;

    sys_log(0, "RELOAD: ItemRareAtt: %d", wSize);



    if (wSize)

    {

        TItemAttrTable * p = (TItemAttrTable *)c_pData;

        g_map_itemRare.clear();

        for (int i = 0; i < wSize; ++i, ++p)

        {

            if (p->dwApplyIndex >= MAX_APPLY_NUM)

                continue;



            g_map_itemRare[p->dwApplyIndex] = *p;

            sys_log(0, "ITEM_RARE[%d]: %s %u", p->dwApplyIndex, p->szApply, p->dwProb);

        }

        c_pData += wSize*sizeof(TItemAttrTable);

    }



 





shop_manager.cpp



Spoiler



bool CShopManager::Initialize(TShopTable * table, int size



Replace this:









    if (!m_map_pkShop.empty())

        return false;



With this:









    if (!m_map_pkShop.empty())

    {

        for (TShopMap::iterator it = m_map_pkShop.begin(); it != m_map_pkShop.end(); it++)

        {

            it->second->RemoveAllGuests();

        }

    }



    m_map_pkShop.clear();

    m_map_pkShopByNPCVnum.clear();



 





refine.cpp



Spoiler



Insert this to the top of this function:bool CRefineManager::Initialize(TRefineTable * table, int size)









    m_map_RefineRecipe.clear();



 





char_manager.cpp



Spoiler



Insert this to the end of the file:









void CHARACTER_MANAGER::DestroyCharacterInMap(long lMapIndex)

{

    std::vector<LPCHARACTER> tempVec;

    for (itertype(m_map_pkChrByVID) it = m_map_pkChrByVID.begin(); it != m_map_pkChrByVID.end(); it++)

    {

        LPCHARACTER pkChr = it->second;

        if (pkChr && pkChr->GetMapIndex() == lMapIndex && pkChr->IsNPC() && !pkChr->IsPet() && pkChr->GetRider() == NULL)

        {

            tempVec.push_back(pkChr);

        }

    }

    for (std::vector<LPCHARACTER>::iterator it = tempVec.begin(); it != tempVec.end(); it++)

    {

        DestroyCharacter(*it);

    }

}



 





char_manager.h



Spoiler



Above this:









void            Update(int iPulse);



Insert this:









void DestroyCharacterInMap(long lMapIndex);



 





item_manager.h



Spoiler



Replace this:









        bool            ReadEtcDropItemFile(const char * c_pszFileName);

        bool            ReadMonsterDropItemGroup(const char * c_pszFileName);

        bool            ReadSpecialDropItemFile(const char * c_pszFileName);



With this:









        bool            ReadEtcDropItemFile(const char * c_pszFileName, bool isReloading = false);

        bool            ReadMonsterDropItemGroup(const char * c_pszFileName, bool isReloading = false);

        bool            ReadSpecialDropItemFile(const char * c_pszFileName, bool isReloading = false);



 





item_manager_read_tables.cpp



Spoiler



Firstly replace this:









bool ITEM_MANAGER::ReadEtcDropItemFile(const char * c_pszFileName)



With this:









bool ITEM_MANAGER::ReadEtcDropItemFile(const char * c_pszFileName, bool isReloading)



Now we will work in this function we just edited. Above this:









char buf[512]



Insert this:









    std::map<DWORD, DWORD> tempLoader;

    if (isReloading)

    {

        sys_log(0, "RELOADING EtcDrop");

    }



Then replace this:









m_map_dwEtcItemDropProb[dwItemVnum] = (DWORD) (fProb * 10000.0f);



With this:









        if (isReloading)

            tempLoader[dwItemVnum] = (DWORD)(fProb * 10000.0f);

        else

            m_map_dwEtcItemDropProb[dwItemVnum] = (DWORD) (fProb * 10000.0f);



Add this above the return true; that we can find at the end of the function:









    if (isReloading)

    {

        m_map_dwEtcItemDropProb.clear();

        for (std::map<DWORD, DWORD>::iterator it = tempLoader.begin(); it != tempLoader.end(); it++)

        {

            m_map_dwEtcItemDropProb[it->first] = it->second;

        }

    }



Okay, now we finished this function. Lets search for this:









bool ITEM_MANAGER::ReadSpecialDropItemFile(const char * c_pszFileName)



Then replace with this:









bool ITEM_MANAGER::ReadSpecialDropItemFile(const char * c_pszFileName, bool isReloading)



Okay, we will work in this function. Before the first for loop add this:









    std::map<DWORD, CSpecialAttrGroup*> tempSpecAttr;

    std::map<DWORD, CSpecialItemGroup*> tempSpecItem;

    std::map<DWORD, CSpecialItemGroup*> tempSpecItemQuest;

    if (isReloading)

        sys_log(0, "RELOADING SpecialDrop");



Then replace this:









m_map_pkSpecialAttrGroup.insert(std::make_pair(iVnum, pkGroup));



With this:









            if (isReloading)

                tempSpecAttr.insert(std::make_pair(iVnum, pkGroup));

            else

                m_map_pkSpecialAttrGroup.insert(std::make_pair(iVnum, pkGroup));



Then replace this:









            if (CSpecialItemGroup::QUEST == type)

            {

                m_map_pkQuestItemGroup.insert(std::make_pair(iVnum, pkGroup));

            }

            else

            {

                m_map_pkSpecialItemGroup.insert(std::make_pair(iVnum, pkGroup));

            }



With this:









            if (CSpecialItemGroup::QUEST == type)

            {

                if (isReloading)

                    tempSpecItemQuest.insert(std::make_pair(iVnum, pkGroup));

                else

                    m_map_pkQuestItemGroup.insert(std::make_pair(iVnum, pkGroup));

            }

            else

            {

                if (isReloading)

                    tempSpecItem.insert(std::make_pair(iVnum, pkGroup));

                else

                    m_map_pkSpecialItemGroup.insert(std::make_pair(iVnum, pkGroup));

            }



Again, above the return true; (we can find this at the end of the function) add this:









    if (isReloading)

    {

        m_map_pkQuestItemGroup.clear();

        m_map_pkSpecialItemGroup.clear();

        m_map_pkSpecialAttrGroup.clear();



        for (std::map<DWORD, CSpecialAttrGroup*>::iterator it = tempSpecAttr.begin(); it != tempSpecAttr.end(); it++)

        {

            m_map_pkSpecialAttrGroup[it->first] = it->second;

        }



        for (std::map<DWORD, CSpecialItemGroup*>::iterator it = tempSpecItem.begin(); it != tempSpecItem.end(); it++)

        {

            m_map_pkSpecialItemGroup[it->first] = it->second;

        }



        for (std::map<DWORD, CSpecialItemGroup*>::iterator it = tempSpecItemQuest.begin(); it != tempSpecItemQuest.end(); it++)

        {

            m_map_pkQuestItemGroup[it->first] = it->second;

        }

    }



Lets search for a new function. Replace this:









bool ITEM_MANAGER::ReadMonsterDropItemGroup(const char * c_pszFileName)



With this:









bool ITEM_MANAGER::ReadMonsterDropItemGroup(const char * c_pszFileName, bool isReloading)



Okay, we will work again in the "just edited" function. Before the first for loop add this:









    std::map<DWORD, CMobItemGroup*> temMobItemGr;

    std::map<DWORD, CDropItemGroup*> tempDropItemGr;

    std::map<DWORD, CLevelItemGroup*> tempLevelItemGr;

    std::map<DWORD, CBuyerThiefGlovesItemGroup*> tempThiefGlovesGr;

    if (isReloading)

    {

        sys_log(0, "RELOADING MonsterDrop");

    }



Replace this:









m_map_pkMobItemGroup.insert(std::map<DWORD, CMobItemGroup*>::value_type(iMobVnum, pkGroup));



With this:









            if (isReloading)

                temMobItemGr.insert(std::map<DWORD, CMobItemGroup*>::value_type(iMobVnum, pkGroup));

            else

                m_map_pkMobItemGroup.insert(std::map<DWORD, CMobItemGroup*>::value_type(iMobVnum, pkGroup));



Then this:









                itertype(m_map_pkDropItemGroup) it = m_map_pkDropItemGroup.find(iMobVnum);

                if (it == m_map_pkDropItemGroup.end())

                {

                    pkGroup = M2_NEW CDropItemGroup(0, iMobVnum, stName);

                }

                else

                {

                    bNew = false;

                    CDropItemGroup* pkGroup = it->second;

                }



With this:









            if (isReloading)

            {

                itertype(tempDropItemGr) it = tempDropItemGr.find(iMobVnum);

                if (it == tempDropItemGr.end())

                {

                    pkGroup = M2_NEW CDropItemGroup(0, iMobVnum, stName);

                }

                else

                {

                    bNew = false;

                    CDropItemGroup* pkGroup = it->second;

                }

            }

            else

            {

                itertype(m_map_pkDropItemGroup) it = m_map_pkDropItemGroup.find(iMobVnum);

                if (it == m_map_pkDropItemGroup.end())

                {

                    pkGroup = M2_NEW CDropItemGroup(0, iMobVnum, stName);

                }

                else

                {

                    bNew = false;

                    CDropItemGroup* pkGroup = it->second;

                }

            }



Replace this:









            if (bNew)

                m_map_pkDropItemGroup.insert(std::map<DWORD, CDropItemGroup*>::value_type(iMobVnum, pkGroup));



With this:









            if (bNew)

            {

                if (isReloading)

                    tempDropItemGr.insert(std::map<DWORD, CDropItemGroup*>::value_type(iMobVnum, pkGroup));

                else

                    m_map_pkDropItemGroup.insert(std::map<DWORD, CDropItemGroup*>::value_type(iMobVnum, pkGroup));

            }



This:









m_map_pkLevelItemGroup.insert(std::map<DWORD, CLevelItemGroup*>::value_type(iMobVnum, pkLevelItemGroup));



With this:









            if (isReloading)

                tempLevelItemGr.insert(std::map<DWORD, CLevelItemGroup*>::value_type(iMobVnum, pkLevelItemGroup));

            else

                m_map_pkLevelItemGroup.insert(std::map<DWORD, CLevelItemGroup*>::value_type(iMobVnum, pkLevelItemGroup));



This:









m_map_pkGloveItemGroup.insert(std::map<DWORD, CBuyerThiefGlovesItemGroup*>::value_type(iMobVnum, pkGroup));



With this:









            if (isReloading)

                tempThiefGlovesGr.insert(std::map<DWORD, CBuyerThiefGlovesItemGroup*>::value_type(iMobVnum, pkGroup));

            else

                m_map_pkGloveItemGroup.insert(std::map<DWORD, CBuyerThiefGlovesItemGroup*>::value_type(iMobVnum, pkGroup));



Then add this above the return true; at the end of the function:









    if (isReloading)

    {

        for (std::map<DWORD, CBuyerThiefGlovesItemGroup*>::iterator it = m_map_pkGloveItemGroup.begin(); it != m_map_pkGloveItemGroup.end(); it++)

            M2_DELETE(it->second);

        m_map_pkGloveItemGroup.clear();

        for (std::map<DWORD, CLevelItemGroup*>::iterator it = m_map_pkLevelItemGroup.begin(); it != m_map_pkLevelItemGroup.end(); it++)

            M2_DELETE(it->second);

        m_map_pkLevelItemGroup.clear();

        for (std::map<DWORD, CDropItemGroup*>::iterator it = m_map_pkDropItemGroup.begin(); it != m_map_pkDropItemGroup.end(); it++)

            M2_DELETE(it->second);

        m_map_pkDropItemGroup.clear();

        for (std::map<DWORD, CMobItemGroup*>::iterator it = m_map_pkMobItemGroup.begin(); it != m_map_pkMobItemGroup.end(); it++)

            M2_DELETE(it->second);

        m_map_pkMobItemGroup.clear();



        for (std::map<DWORD, CBuyerThiefGlovesItemGroup*>::iterator it = tempThiefGlovesGr.begin(); it != tempThiefGlovesGr.end(); it++)

        {

            m_map_pkGloveItemGroup[it->first] = it->second;

        }



        for (std::map<DWORD, CLevelItemGroup*>::iterator it = tempLevelItemGr.begin(); it != tempLevelItemGr.end(); it++)

        {

            m_map_pkLevelItemGroup[it->first] = it->second;

        }



        for (std::map<DWORD, CDropItemGroup*>::iterator it = tempDropItemGr.begin(); it != tempDropItemGr.end(); it++)

        {

            m_map_pkDropItemGroup[it->first] = it->second;

        }



        for (std::map<DWORD, CMobItemGroup*>::iterator it = temMobItemGr.begin(); it != temMobItemGr.end(); it++)

        {

            m_map_pkMobItemGroup[it->first] = it->second;

        }

    }



 





mob_manager.h



Spoiler



Replace this:









        bool        LoadGroup(const char * c_pszFileName);

        bool        LoadGroupGroup(const char * c_pszFileName);



With this:









        bool        LoadGroup(const char * c_pszFileName, bool isReloading = false);

        bool        LoadGroupGroup(const char * c_pszFileName, bool isReloading = false);



 





mob_manager.cpp



Spoiler



Replace this:









bool CMobManager::LoadGroupGroup(const char * c_pszFileName)



With this:









bool CMobManager::LoadGroupGroup(const char * c_pszFileName, bool isReloading)



We will work in this function again. Add this above the first for loop:









    std::map<DWORD, CMobGroupGroup *> tempLoader;

    if (isReloading)

        sys_log(0, "RELOADING group group: %s", c_pszFileName);



Then replace this:









m_map_pkMobGroupGroup.insert(std::make_pair((DWORD)iVnum, pkGroup));



With this:









        if (isReloading)

            tempLoader.insert(std::make_pair((DWORD)iVnum, pkGroup));

        else

            m_map_pkMobGroupGroup.insert(std::make_pair((DWORD)iVnum, pkGroup));



Then insert this above the return true; at the end of the function:









    if (isReloading)

    {

        for (std::map<DWORD, CMobGroupGroup *>::iterator it = m_map_pkMobGroupGroup.begin(); it != m_map_pkMobGroupGroup.end(); it++)

            M2_DELETE(it->second);

        m_map_pkMobGroupGroup.clear();

        for (std::map<DWORD, CMobGroupGroup *>::iterator it = tempLoader.begin(); it != tempLoader.end(); it++)

        {

            m_map_pkMobGroupGroup[it->first] = it->second;

        }

    }



Okay we done with the this function, lets search for this:









bool CMobManager::LoadGroup(const char * c_pszFileName)



And replace with this:









bool CMobManager::LoadGroup(const char * c_pszFileName, bool isReloading)



Obliviously we will work in this function. Lets add this again before the first for loop:









    std::map<DWORD, CMobGroup *> tempLoader;

    if (isReloading)

        sys_log(0, "RELOADING groups: %s", c_pszFileName);



Then replace this:









m_map_pkMobGroup.insert(std::map<DWORD, CMobGroup *>::value_type(iVnum, pkGroup));



With this:









        if (isReloading)

            tempLoader.insert(std::map<DWORD, CMobGroup *>::value_type(iVnum, pkGroup));

        else

            m_map_pkMobGroup.insert(std::map<DWORD, CMobGroup *>::value_type(iVnum, pkGroup));



And last but not least lets add this before the return true; at the end of the function:









    if (isReloading)

    {

        for (std::map<DWORD, CMobGroup *>::iterator it = m_map_pkMobGroup.begin(); it != m_map_pkMobGroup.end(); it++)

            M2_DELETE(it->second);

        m_map_pkMobGroup.clear();

        for (std::map<DWORD, CMobGroup *>::iterator it = tempLoader.begin(); it != tempLoader.end(); it++)

        {

            m_map_pkMobGroup[it->first] = it->second;

        }

    }



 





char.cpp



Spoiler



void CHARACTER::Destroy()



Replace this:









    if (m_pkRegen)

    {

        if (m_pkDungeon) {

            // Dungeon regen may not be valid at this point

            if (m_pkDungeon->IsValidRegen(m_pkRegen, regen_id_)) {

                --m_pkRegen->count;

            }

        } else {

            // Is this really safe?

            --m_pkRegen->count;

        }

        m_pkRegen = NULL;

    }



With this:









    if (m_pkRegen)

    {

        if (m_pkDungeon) {

            // Dungeon regen may not be valid at this point

            if (m_pkDungeon->IsValidRegen(m_pkRegen, regen_id_)) {

                --m_pkRegen->count;

            }

        } else {

            // Is this really safe? NO IT ISNT! F*CK THAT SH!T!

            if (is_valid_regen(m_pkRegen))

                --m_pkRegen->count;

        }

        m_pkRegen = NULL;

    }



 





sectree_manager.cpp



Spoiler



int SECTREE_MANAGER::Build(const char * c_pszListFileName, const char* c_pszMapBasePath)



Under this:









            snprintf(szFilename, sizeof(szFilename), "%s/%s/server_attr", c_pszMapBasePath, szMapName);

            LoadAttribute(pkMapSectree, szFilename, setting);



Insert this:









            snprintf(szFilename, sizeof(szFilename), "%s/%s/", c_pszMapBasePath, szMapName);

            regen_register_map(szFilename, setting.iIndex, setting.iBaseX, setting.iBaseY);



 





regen.h



Spoiler



Under this:









extern bool    regen_load(const char *filename, long lMapIndex, int base_x, int base_y);



Insert this:









extern void regen_free_map(long lMapIndex);

extern void regen_reload(long lMapIndex);

extern void regen_register_map(const char * szBaseName, long lMapIndex, int base_x, int base_y);

extern bool is_valid_regen(LPREGEN currRegen);



 





regen.cpp



Spoiler



Under this:









LPREGEN_EXCEPTION regen_exception_list = NULL;



Add this:









typedef struct SMapDataContainer

{

    char szBaseName[256];

    int base_x;

    int base_y;

}TMapDataContainer;



#define mbMapDataCType std::map<DWORD, TMapDataContainer*>

mbMapDataCType mbMapDataContainer;



At the end of the file add this:









bool is_valid_regen(LPREGEN currRegen)

{

    LPREGEN        regen;



    for (regen = regen_list; regen; regen = regen->next)

    {

        if (regen == currRegen)

            return true;

    }

    return false;

}



void regen_free_map(long lMapIndex)

{

    LPREGEN        regen, prev, next;



    for (regen = regen_list; regen; regen = regen->next)

    {

        if (regen->lMapIndex != lMapIndex)

            continue;

        event_cancel(&regen->event);

        REMOVE_FROM_TW_LIST(regen, regen_list, prev, next);

        M2_DELETE(regen);

    }

}



void regen_reload(long lMapIndex)

{

    if (mbMapDataContainer.find(lMapIndex) == mbMapDataContainer.end())

        return;



    char szFilename[256];

 

    snprintf(szFilename, sizeof(szFilename), "%sregen.txt", mbMapDataContainer[lMapIndex]->szBaseName);

    regen_load(szFilename, lMapIndex, mbMapDataContainer[lMapIndex]->base_x, mbMapDataContainer[lMapIndex]->base_y);



    snprintf(szFilename, sizeof(szFilename), "%snpc.txt", mbMapDataContainer[lMapIndex]->szBaseName);

    regen_load(szFilename, lMapIndex, mbMapDataContainer[lMapIndex]->base_x, mbMapDataContainer[lMapIndex]->base_y);



    snprintf(szFilename, sizeof(szFilename), "%sboss.txt", mbMapDataContainer[lMapIndex]->szBaseName);

    regen_load(szFilename, lMapIndex, mbMapDataContainer[lMapIndex]->base_x, mbMapDataContainer[lMapIndex]->base_y);



    snprintf(szFilename, sizeof(szFilename), "%sstone.txt", mbMapDataContainer[lMapIndex]->szBaseName);

    regen_load(szFilename, lMapIndex, mbMapDataContainer[lMapIndex]->base_x, mbMapDataContainer[lMapIndex]->base_y);

}



void regen_register_map(const char * szBaseName, long lMapIndex, int base_x, int base_y)

{

    TMapDataContainer* container = new TMapDataContainer;

    memset(container->szBaseName, 0, sizeof(container->szBaseName));

#ifdef __FreeBSD__

    strlcpy(container->szBaseName, szBaseName, sizeof(container->szBaseName) - 1);

#else

    strncpy(container->szBaseName, szBaseName, sizeof(container->szBaseName) - 1);

#endif

    container->base_x = base_x;

    container->base_y = base_y;

    mbMapDataContainer[lMapIndex] = container;

}



EVENTFUNC(regen_event)



Under this:









    LPREGEN    regen = info->regen;



Insert this:









    if (!is_valid_regen(regen))

        return 0;



 





shop.h



Spoiler



Under this:









        void    RemoveGuest(LPCHARACTER ch);



Insert this:









        void    RemoveAllGuests();



 





shop.cpp



Spoiler



Add this at the end of the file:









void CShop::RemoveAllGuests()

{

    if (m_map_guest.empty())

        return;

    for (GuestMapType::iterator it = m_map_guest.begin(); it != m_map_guest.end(); it++)

    {

        LPCHARACTER ch = it->first;

        if (ch)

        {

            if (ch->GetDesc() && ch->GetShop() == this)

            {

                ch->SetShop(NULL);



                TPacketGCShop pack;



                pack.header = HEADER_GC_SHOP;

                pack.subheader = SHOP_SUBHEADER_GC_END;

                pack.size = sizeof(TPacketGCShop);



                ch->GetDesc()->Packet(&pack, sizeof(pack));

            }

        }

    }

    m_map_guest.clear();

}



 





db/src



ClientManager.cpp



Spoiler



void CClientManager::QUERY_RELOAD_PROTO()



Replace this:









        tmp->EncodeHeader(HEADER_DG_RELOAD_PROTO, 0,

                sizeof(WORD) + sizeof(TSkillTable) * m_vec_skillTable.size() +

                sizeof(WORD) + sizeof(TBanwordTable) * m_vec_banwordTable.size() +

                sizeof(WORD) + sizeof(TItemTable) * m_vec_itemTable.size() +

                sizeof(WORD) + sizeof(TMobTable) * m_vec_mobTable.size());



With this:









        tmp->EncodeHeader(HEADER_DG_RELOAD_PROTO, 0,

                sizeof(WORD) + sizeof(TSkillTable) * m_vec_skillTable.size() +

                sizeof(WORD) + sizeof(TBanwordTable) * m_vec_banwordTable.size() +

                sizeof(WORD) + sizeof(TItemTable) * m_vec_itemTable.size() +

                sizeof(WORD) + sizeof(TMobTable) * m_vec_mobTable.size() +

                sizeof(WORD) + sizeof(TShopTable) * m_iShopTableSize +

                sizeof(WORD) + sizeof(TRefineTable)* m_iRefineTableSize +

                sizeof(WORD) + sizeof(TItemAttrTable)*m_vec_itemAttrTable.size() +

                sizeof(WORD) + sizeof(TItemAttrTable)*m_vec_itemRareTable.size());



Then under this:









        tmp->EncodeWORD(m_vec_mobTable.size());

        tmp->Encode(&m_vec_mobTable[0], sizeof(TMobTable) * m_vec_mobTable.size());



Add this:









        tmp->EncodeWORD(m_iShopTableSize);

        tmp->Encode(m_pShopTable, sizeof(TShopTable) * m_iShopTableSize);



        tmp->EncodeWORD(m_iRefineTableSize);

        tmp->Encode(m_pRefineTable, sizeof(TRefineTable) * m_iRefineTableSize);



        tmp->EncodeWORD(m_vec_itemAttrTable.size());

        tmp->Encode(&m_vec_itemAttrTable[0], sizeof(TItemAttrTable) * m_vec_itemAttrTable.size());



        tmp->EncodeWORD(m_vec_itemRareTable.size());

        tmp->Encode(&m_vec_itemRareTable[0], sizeof(TItemAttrTable) * m_vec_itemRareTable.size());



 





And finally let me wish you all good luck for the setup ;) If you have further question(s), remark(s), or anything that you want to ask or suggest, feel free to post it here, or send it in PM.



If you get error(s) please upload the affected (and edited) file to Pastebin.com - #1 paste tool since 2002! and link it in your post, to make my work easier and probably I will be able to help you only in one post, so please spare me from asking basic requests like "Could you upload...". Thank you ;)



Have a nice day,

~masodikbela
 
Last edited by a moderator:
Metin2Hub Bot
M2Hub Bot
Feb
Threads
65
2,005
2
842
113
HubMoney
1,213

M2 Download Center

( Internal )


Hi there devs,



I made some new reload commands about 2 weeks ago and published a tutorial about it on our Hungarian forum (you may saw them in the ) and today I had some time to make the translation.

What can I reload now?

  • refine_proto (this is the only one which is not mine, its 's, and already public , but I added it, because I think this package has to contain it
    ;)
    ) command: /reload p
  • shop_item table (npc's shops) command: /reload p
  • item_attr && item_attr_rare table; command: /reload p
  • etc_drop_item.txt, mob_drop_item.txt, special_item_group.txt; command: /reload drop
  • group.txt, group_group.txt; command: /reload group
  • regen.txt, npc.txt, boss.txt, stone.txt (only on the current map) command: /reload regen
  • because of the new "reload regen" command, I had to write a new purge command that destroys all mobs, npcs, stones (and so on...) on the current map, so I added a new /p map command to the "/p" commands that are already exists (no, the "/p all" only destroys the mobs on the current sectree (current block))
  • also I had to create a new command that stops all the regens (and ofc. deletes them from the memory) on the current map, so I added a new "/free_regens" command (because why not
    B)
    ) Its only deletes the loaded regens, and prevents the mobs from respawning (its not necessary to use this before the /reload regen)

Known bug

  • Well its not a serious problem, but for some unknown reason, when I'm debugging the core on windows server (no, not debug mode, but vs 13's debugger) and I try to do /reload regen, the core starts to consume ~40% cpu, and doesn't want to do anything (so stops working, but doesn't crash). It has no affect on FreeBSD and release or debug mode (without visual studio's debugger) on windows.



Spoiler

If you get fcked up codes like me, try to remove the pagestyle in your browser.
mz7XE.jpg



game/src

cmd.cpp

Spoiler

Add this to the top of the file (where you can find more ACMDs)




ACMD(do_free_regen);

Then above this:




{ "who", do_who, 0, POS_DEAD, GM_IMPLEMENTOR },

Add this:




{ "free_regens", do_free_regen, 0, POS_DEAD, GM_IMPLEMENTOR },




cmd_gm.cpp

Spoiler

Add this to the end of the file:




ACMD(do_free_regen)
{
ch->ChatPacket(CHAT_TYPE_INFO, "freeing regens on mapindex %ld", ch->GetMapIndex());
regen_free_map(ch->GetMapIndex());
ch->ChatPacket(CHAT_TYPE_INFO, "the regens now FREEEE! :)");
}

Replace the ACMD(do_purge) with this:




ACMD(do_purge)
{
char arg1[256];
one_argument(argument, arg1, sizeof(arg1));

FuncPurge func(ch);

if (*arg1 && !strcmp(arg1, "map"))
{
CHARACTER_MANAGER::instance().DestroyCharacterInMap(ch->GetMapIndex());
}
else
{
if (*arg1 && !strcmp(arg1, "all"))
func.m_bAll = true;
LPSECTREE sectree = ch->GetSectree();
if (sectree) // #431
sectree->ForEachAround(func);
else
sys_err("PURGE_ERROR.NULL_SECTREE(mapIndex=%d, pos=(%d, %d)", ch->GetMapIndex(), ch->GetX(), ch->GetY());
}
}

In the ACMD(do_reload) function under this:




case 'c': // cube
// ·ÎÄĂ ÇÁ·ÎĽĽ˝ş¸¸ °»»ęÇŃ´Ů.
Cube_init ();
break;

Insert this:




default:
const int FILE_NAME_LEN = 256;
if (strstr(arg1, "drop"))
{
char szETCDropItemFileName[FILE_NAME_LEN];
char szMOBDropItemFileName[FILE_NAME_LEN];
char szSpecialItemGroupFileName[FILE_NAME_LEN];

snprintf(szETCDropItemFileName, sizeof(szETCDropItemFileName),
"%s/etc_drop_item.txt", LocaleService_GetBasePath().c_str());
snprintf(szMOBDropItemFileName, sizeof(szMOBDropItemFileName),
"%s/mob_drop_item.txt", LocaleService_GetBasePath().c_str());
snprintf(szSpecialItemGroupFileName, sizeof(szSpecialItemGroupFileName),
"%s/special_item_group.txt", LocaleService_GetBasePath().c_str());

ch->ChatPacket(CHAT_TYPE_INFO, "Reloading: ETCDropItem: %s", szETCDropItemFileName);
if (!ITEM_MANAGER::instance().ReadEtcDropItemFile(szETCDropItemFileName, true))
ch->ChatPacket(CHAT_TYPE_INFO, "failed to reload ETCDropItem: %s", szETCDropItemFileName);
else
ch->ChatPacket(CHAT_TYPE_INFO, "reload success: ETCDropItem: %s", szETCDropItemFileName);

ch->ChatPacket(CHAT_TYPE_INFO, "Reloading: SpecialItemGroup: %s", szSpecialItemGroupFileName);
if (!ITEM_MANAGER::instance().ReadSpecialDropItemFile(szSpecialItemGroupFileName, true))
ch->ChatPacket(CHAT_TYPE_INFO, "failed to reload SpecialItemGroup: %s", szSpecialItemGroupFileName);
else
ch->ChatPacket(CHAT_TYPE_INFO, "reload success: SpecialItemGroup: %s", szSpecialItemGroupFileName);

ch->ChatPacket(CHAT_TYPE_INFO, "Reloading: MOBDropItemFile: %s", szMOBDropItemFileName);
if (!ITEM_MANAGER::instance().ReadMonsterDropItemGroup(szMOBDropItemFileName, true))
ch->ChatPacket(CHAT_TYPE_INFO, "failed to reload MOBDropItemFile: %s", szMOBDropItemFileName);
else
ch->ChatPacket(CHAT_TYPE_INFO, "reload success: MOBDropItemFile: %s", szMOBDropItemFileName);
}
else if (strstr(arg1, "group"))
{
char szGroupFileName[FILE_NAME_LEN];
char szGroupGroupFileName[FILE_NAME_LEN];

snprintf(szGroupFileName, sizeof(szGroupGroupFileName),
"%s/group.txt", LocaleService_GetBasePath().c_str());
snprintf(szGroupGroupFileName, sizeof(szGroupGroupFileName),
"%s/group_group.txt", LocaleService_GetBasePath().c_str());

ch->ChatPacket(CHAT_TYPE_INFO, "Reloading: mob groups: %s", szGroupFileName);
if (!CMobManager::instance().LoadGroup(szGroupFileName, true))
ch->ChatPacket(CHAT_TYPE_INFO, "failed to reload mob groups: %s", szGroupFileName);

ch->ChatPacket(CHAT_TYPE_INFO, "Reloading: mob group group: %s", szGroupGroupFileName);
if (!CMobManager::instance().LoadGroupGroup(szGroupGroupFileName, true))
ch->ChatPacket(CHAT_TYPE_INFO, "failed to reload mob group group: %s", szGroupGroupFileName);
}
else if (strstr(arg1, "regen"))
{
SendNoticeMap("Reloading regens!", ch->GetMapIndex(), false);
regen_free_map(ch->GetMapIndex());
CHARACTER_MANAGER::instance().DestroyCharacterInMap(ch->GetMapIndex());
regen_reload(ch->GetMapIndex());
SendNoticeMap("Regens reloaded!", ch->GetMapIndex(), false);
}
break;




input_db.cpp

Spoiler

void CInputDB::ReloadProto(const char * c_pData)

Above this:




CMotionManager::instance().Build();

Add this:




/*
* SHOP
*/

wSize = decode_2bytes(c_pData);
c_pData += sizeof(WORD);
sys_log(0, "RELOAD: SHOP: %d", wSize);


if (wSize)
{
CShopManager::instance().Initialize((TShopTable *)c_pData, wSize);
c_pData += wSize * sizeof(TShopTable);
}

/*
* REFINE
*/
wSize = decode_2bytes(c_pData);
c_pData += 2;
sys_log(0, "RELOAD: REFINE: %d", wSize);

if (wSize)
{
CRefineManager::instance().Initialize((TRefineTable *)c_pData, wSize);
c_pData += wSize * sizeof(TRefineTable);
}

/*
* ATTR
*/
wSize = decode_2bytes(c_pData);
c_pData += 2;
sys_log(0, "RELOAD: ItemAtt: %d", wSize);

if (wSize)
{
TItemAttrTable * p = (TItemAttrTable *)c_pData;
g_map_itemAttr.clear();
for (int i = 0; i < wSize; ++i, ++p)
{
if (p->dwApplyIndex >= MAX_APPLY_NUM)
continue;

g_map_itemAttr[p->dwApplyIndex] = *p;
sys_log(0, "ITEM_ATTR[%d]: %s %u", p->dwApplyIndex, p->szApply, p->dwProb);
}
c_pData += wSize*sizeof(TItemAttrTable);
}

/*
* ATTR_RARE
*/
wSize = decode_2bytes(c_pData);
c_pData += 2;
sys_log(0, "RELOAD: ItemRareAtt: %d", wSize);

if (wSize)
{
TItemAttrTable * p = (TItemAttrTable *)c_pData;
g_map_itemRare.clear();
for (int i = 0; i < wSize; ++i, ++p)
{
if (p->dwApplyIndex >= MAX_APPLY_NUM)
continue;

g_map_itemRare[p->dwApplyIndex] = *p;
sys_log(0, "ITEM_RARE[%d]: %s %u", p->dwApplyIndex, p->szApply, p->dwProb);
}
c_pData += wSize*sizeof(TItemAttrTable);
}




shop_manager.cpp

Spoiler

bool CShopManager::Initialize(TShopTable * table, int size

Replace this:




if (!m_map_pkShop.empty())
return false;

With this:




if (!m_map_pkShop.empty())
{
for (TShopMap::iterator it = m_map_pkShop.begin(); it != m_map_pkShop.end(); it++)
{
it->second->RemoveAllGuests();
}
}

m_map_pkShop.clear();
m_map_pkShopByNPCVnum.clear();




refine.cpp

Spoiler

Insert this to the top of this function:bool CRefineManager::Initialize(TRefineTable * table, int size)




m_map_RefineRecipe.clear();




char_manager.cpp

Spoiler

Insert this to the end of the file:




void CHARACTER_MANAGER::DestroyCharacterInMap(long lMapIndex)
{
std::vector<LPCHARACTER> tempVec;
for (itertype(m_map_pkChrByVID) it = m_map_pkChrByVID.begin(); it != m_map_pkChrByVID.end(); it++)
{
LPCHARACTER pkChr = it->second;
if (pkChr && pkChr->GetMapIndex() == lMapIndex && pkChr->IsNPC() && !pkChr->IsPet() && pkChr->GetRider() == NULL)
{
tempVec.push_back(pkChr);
}
}
for (std::vector<LPCHARACTER>::iterator it = tempVec.begin(); it != tempVec.end(); it++)
{
DestroyCharacter(*it);
}
}




char_manager.h

Spoiler

Above this:




void Update(int iPulse);

Insert this:




void DestroyCharacterInMap(long lMapIndex);




item_manager.h

Spoiler

Replace this:




bool ReadEtcDropItemFile(const char * c_pszFileName);
bool ReadMonsterDropItemGroup(const char * c_pszFileName);
bool ReadSpecialDropItemFile(const char * c_pszFileName);

With this:




bool ReadEtcDropItemFile(const char * c_pszFileName, bool isReloading = false);
bool ReadMonsterDropItemGroup(const char * c_pszFileName, bool isReloading = false);
bool ReadSpecialDropItemFile(const char * c_pszFileName, bool isReloading = false);




item_manager_read_tables.cpp

Spoiler

Firstly replace this:




bool ITEM_MANAGER::ReadEtcDropItemFile(const char * c_pszFileName)

With this:




bool ITEM_MANAGER::ReadEtcDropItemFile(const char * c_pszFileName, bool isReloading)

Now we will work in this function we just edited. Above this:




char buf[512]

Insert this:




std::map<DWORD, DWORD> tempLoader;
if (isReloading)
{
sys_log(0, "RELOADING EtcDrop");
}

Then replace this:




m_map_dwEtcItemDropProb[dwItemVnum] = (DWORD) (fProb * 10000.0f);

With this:




if (isReloading)
tempLoader[dwItemVnum] = (DWORD)(fProb * 10000.0f);
else
m_map_dwEtcItemDropProb[dwItemVnum] = (DWORD) (fProb * 10000.0f);

Add this above the return true; that we can find at the end of the function:




if (isReloading)
{
m_map_dwEtcItemDropProb.clear();
for (std::map<DWORD, DWORD>::iterator it = tempLoader.begin(); it != tempLoader.end(); it++)
{
m_map_dwEtcItemDropProb[it->first] = it->second;
}
}

Okay, now we finished this function. Lets search for this:




bool ITEM_MANAGER::ReadSpecialDropItemFile(const char * c_pszFileName)

Then replace with this:




bool ITEM_MANAGER::ReadSpecialDropItemFile(const char * c_pszFileName, bool isReloading)

Okay, we will work in this function. Before the first for loop add this:




std::map<DWORD, CSpecialAttrGroup*> tempSpecAttr;
std::map<DWORD, CSpecialItemGroup*> tempSpecItem;
std::map<DWORD, CSpecialItemGroup*> tempSpecItemQuest;
if (isReloading)
sys_log(0, "RELOADING SpecialDrop");

Then replace this:




m_map_pkSpecialAttrGroup.insert(std::make_pair(iVnum, pkGroup));

With this:




if (isReloading)
tempSpecAttr.insert(std::make_pair(iVnum, pkGroup));
else
m_map_pkSpecialAttrGroup.insert(std::make_pair(iVnum, pkGroup));

Then replace this:




if (CSpecialItemGroup::QUEST == type)
{
m_map_pkQuestItemGroup.insert(std::make_pair(iVnum, pkGroup));
}
else
{
m_map_pkSpecialItemGroup.insert(std::make_pair(iVnum, pkGroup));
}

With this:




if (CSpecialItemGroup::QUEST == type)
{
if (isReloading)
tempSpecItemQuest.insert(std::make_pair(iVnum, pkGroup));
else
m_map_pkQuestItemGroup.insert(std::make_pair(iVnum, pkGroup));
}
else
{
if (isReloading)
tempSpecItem.insert(std::make_pair(iVnum, pkGroup));
else
m_map_pkSpecialItemGroup.insert(std::make_pair(iVnum, pkGroup));
}

Again, above the return true; (we can find this at the end of the function) add this:




if (isReloading)
{
m_map_pkQuestItemGroup.clear();
m_map_pkSpecialItemGroup.clear();
m_map_pkSpecialAttrGroup.clear();

for (std::map<DWORD, CSpecialAttrGroup*>::iterator it = tempSpecAttr.begin(); it != tempSpecAttr.end(); it++)
{
m_map_pkSpecialAttrGroup[it->first] = it->second;
}

for (std::map<DWORD, CSpecialItemGroup*>::iterator it = tempSpecItem.begin(); it != tempSpecItem.end(); it++)
{
m_map_pkSpecialItemGroup[it->first] = it->second;
}

for (std::map<DWORD, CSpecialItemGroup*>::iterator it = tempSpecItemQuest.begin(); it != tempSpecItemQuest.end(); it++)
{
m_map_pkQuestItemGroup[it->first] = it->second;
}
}

Lets search for a new function. Replace this:




bool ITEM_MANAGER::ReadMonsterDropItemGroup(const char * c_pszFileName)

With this:




bool ITEM_MANAGER::ReadMonsterDropItemGroup(const char * c_pszFileName, bool isReloading)

Okay, we will work again in the "just edited" function. Before the first for loop add this:




std::map<DWORD, CMobItemGroup*> temMobItemGr;
std::map<DWORD, CDropItemGroup*> tempDropItemGr;
std::map<DWORD, CLevelItemGroup*> tempLevelItemGr;
std::map<DWORD, CBuyerThiefGlovesItemGroup*> tempThiefGlovesGr;
if (isReloading)
{
sys_log(0, "RELOADING MonsterDrop");
}

Replace this:




m_map_pkMobItemGroup.insert(std::map<DWORD, CMobItemGroup*>::value_type(iMobVnum, pkGroup));

With this:




if (isReloading)
temMobItemGr.insert(std::map<DWORD, CMobItemGroup*>::value_type(iMobVnum, pkGroup));
else
m_map_pkMobItemGroup.insert(std::map<DWORD, CMobItemGroup*>::value_type(iMobVnum, pkGroup));

Then this:




itertype(m_map_pkDropItemGroup) it = m_map_pkDropItemGroup.find(iMobVnum);
if (it == m_map_pkDropItemGroup.end())
{
pkGroup = M2_NEW CDropItemGroup(0, iMobVnum, stName);
}
else
{
bNew = false;
CDropItemGroup* pkGroup = it->second;
}

With this:




if (isReloading)
{
itertype(tempDropItemGr) it = tempDropItemGr.find(iMobVnum);
if (it == tempDropItemGr.end())
{
pkGroup = M2_NEW CDropItemGroup(0, iMobVnum, stName);
}
else
{
bNew = false;
CDropItemGroup* pkGroup = it->second;
}
}
else
{
itertype(m_map_pkDropItemGroup) it = m_map_pkDropItemGroup.find(iMobVnum);
if (it == m_map_pkDropItemGroup.end())
{
pkGroup = M2_NEW CDropItemGroup(0, iMobVnum, stName);
}
else
{
bNew = false;
CDropItemGroup* pkGroup = it->second;
}
}

Replace this:




if (bNew)
m_map_pkDropItemGroup.insert(std::map<DWORD, CDropItemGroup*>::value_type(iMobVnum, pkGroup));

With this:




if (bNew)
{
if (isReloading)
tempDropItemGr.insert(std::map<DWORD, CDropItemGroup*>::value_type(iMobVnum, pkGroup));
else
m_map_pkDropItemGroup.insert(std::map<DWORD, CDropItemGroup*>::value_type(iMobVnum, pkGroup));
}

This:




m_map_pkLevelItemGroup.insert(std::map<DWORD, CLevelItemGroup*>::value_type(iMobVnum, pkLevelItemGroup));

With this:




if (isReloading)
tempLevelItemGr.insert(std::map<DWORD, CLevelItemGroup*>::value_type(iMobVnum, pkLevelItemGroup));
else
m_map_pkLevelItemGroup.insert(std::map<DWORD, CLevelItemGroup*>::value_type(iMobVnum, pkLevelItemGroup));

This:




m_map_pkGloveItemGroup.insert(std::map<DWORD, CBuyerThiefGlovesItemGroup*>::value_type(iMobVnum, pkGroup));

With this:




if (isReloading)
tempThiefGlovesGr.insert(std::map<DWORD, CBuyerThiefGlovesItemGroup*>::value_type(iMobVnum, pkGroup));
else
m_map_pkGloveItemGroup.insert(std::map<DWORD, CBuyerThiefGlovesItemGroup*>::value_type(iMobVnum, pkGroup));

Then add this above the return true; at the end of the function:




if (isReloading)
{
for (std::map<DWORD, CBuyerThiefGlovesItemGroup*>::iterator it = m_map_pkGloveItemGroup.begin(); it != m_map_pkGloveItemGroup.end(); it++)
M2_DELETE(it->second);
m_map_pkGloveItemGroup.clear();
for (std::map<DWORD, CLevelItemGroup*>::iterator it = m_map_pkLevelItemGroup.begin(); it != m_map_pkLevelItemGroup.end(); it++)
M2_DELETE(it->second);
m_map_pkLevelItemGroup.clear();
for (std::map<DWORD, CDropItemGroup*>::iterator it = m_map_pkDropItemGroup.begin(); it != m_map_pkDropItemGroup.end(); it++)
M2_DELETE(it->second);
m_map_pkDropItemGroup.clear();
for (std::map<DWORD, CMobItemGroup*>::iterator it = m_map_pkMobItemGroup.begin(); it != m_map_pkMobItemGroup.end(); it++)
M2_DELETE(it->second);
m_map_pkMobItemGroup.clear();

for (std::map<DWORD, CBuyerThiefGlovesItemGroup*>::iterator it = tempThiefGlovesGr.begin(); it != tempThiefGlovesGr.end(); it++)
{
m_map_pkGloveItemGroup[it->first] = it->second;
}

for (std::map<DWORD, CLevelItemGroup*>::iterator it = tempLevelItemGr.begin(); it != tempLevelItemGr.end(); it++)
{
m_map_pkLevelItemGroup[it->first] = it->second;
}

for (std::map<DWORD, CDropItemGroup*>::iterator it = tempDropItemGr.begin(); it != tempDropItemGr.end(); it++)
{
m_map_pkDropItemGroup[it->first] = it->second;
}

for (std::map<DWORD, CMobItemGroup*>::iterator it = temMobItemGr.begin(); it != temMobItemGr.end(); it++)
{
m_map_pkMobItemGroup[it->first] = it->second;
}
}




mob_manager.h

Spoiler

Replace this:




bool LoadGroup(const char * c_pszFileName);
bool LoadGroupGroup(const char * c_pszFileName);

With this:




bool LoadGroup(const char * c_pszFileName, bool isReloading = false);
bool LoadGroupGroup(const char * c_pszFileName, bool isReloading = false);




mob_manager.cpp

Spoiler

Replace this:




bool CMobManager::LoadGroupGroup(const char * c_pszFileName)

With this:




bool CMobManager::LoadGroupGroup(const char * c_pszFileName, bool isReloading)

We will work in this function again. Add this above the first for loop:




std::map<DWORD, CMobGroupGroup *> tempLoader;
if (isReloading)
sys_log(0, "RELOADING group group: %s", c_pszFileName);

Then replace this:




m_map_pkMobGroupGroup.insert(std::make_pair((DWORD)iVnum, pkGroup));

With this:




if (isReloading)
tempLoader.insert(std::make_pair((DWORD)iVnum, pkGroup));
else
m_map_pkMobGroupGroup.insert(std::make_pair((DWORD)iVnum, pkGroup));

Then insert this above the return true; at the end of the function:




if (isReloading)
{
for (std::map<DWORD, CMobGroupGroup *>::iterator it = m_map_pkMobGroupGroup.begin(); it != m_map_pkMobGroupGroup.end(); it++)
M2_DELETE(it->second);
m_map_pkMobGroupGroup.clear();
for (std::map<DWORD, CMobGroupGroup *>::iterator it = tempLoader.begin(); it != tempLoader.end(); it++)
{
m_map_pkMobGroupGroup[it->first] = it->second;
}
}

Okay we done with the this function, lets search for this:




bool CMobManager::LoadGroup(const char * c_pszFileName)

And replace with this:




bool CMobManager::LoadGroup(const char * c_pszFileName, bool isReloading)

Obliviously we will work in this function. Lets add this again before the first for loop:




std::map<DWORD, CMobGroup *> tempLoader;
if (isReloading)
sys_log(0, "RELOADING groups: %s", c_pszFileName);

Then replace this:




m_map_pkMobGroup.insert(std::map<DWORD, CMobGroup *>::value_type(iVnum, pkGroup));

With this:




if (isReloading)
tempLoader.insert(std::map<DWORD, CMobGroup *>::value_type(iVnum, pkGroup));
else
m_map_pkMobGroup.insert(std::map<DWORD, CMobGroup *>::value_type(iVnum, pkGroup));

And last but not least lets add this before the return true; at the end of the function:




if (isReloading)
{
for (std::map<DWORD, CMobGroup *>::iterator it = m_map_pkMobGroup.begin(); it != m_map_pkMobGroup.end(); it++)
M2_DELETE(it->second);
m_map_pkMobGroup.clear();
for (std::map<DWORD, CMobGroup *>::iterator it = tempLoader.begin(); it != tempLoader.end(); it++)
{
m_map_pkMobGroup[it->first] = it->second;
}
}




char.cpp

Spoiler

void CHARACTER::Destroy()

Replace this:




if (m_pkRegen)
{
if (m_pkDungeon) {
// Dungeon regen may not be valid at this point
if (m_pkDungeon->IsValidRegen(m_pkRegen, regen_id_)) {
--m_pkRegen->count;
}
} else {
// Is this really safe?
--m_pkRegen->count;
}
m_pkRegen = NULL;
}

With this:




if (m_pkRegen)
{
if (m_pkDungeon) {
// Dungeon regen may not be valid at this point
if (m_pkDungeon->IsValidRegen(m_pkRegen, regen_id_)) {
--m_pkRegen->count;
}
} else {
// Is this really safe? NO IT ISNT! F*CK THAT SH!T!
if (is_valid_regen(m_pkRegen))
--m_pkRegen->count;
}
m_pkRegen = NULL;
}




sectree_manager.cpp

Spoiler

int SECTREE_MANAGER::Build(const char * c_pszListFileName, const char* c_pszMapBasePath)

Under this:




snprintf(szFilename, sizeof(szFilename), "%s/%s/server_attr", c_pszMapBasePath, szMapName);
LoadAttribute(pkMapSectree, szFilename, setting);

Insert this:




snprintf(szFilename, sizeof(szFilename), "%s/%s/", c_pszMapBasePath, szMapName);
regen_register_map(szFilename, setting.iIndex, setting.iBaseX, setting.iBaseY);




regen.h

Spoiler

Under this:




extern bool regen_load(const char *filename, long lMapIndex, int base_x, int base_y);

Insert this:




extern void regen_free_map(long lMapIndex);
extern void regen_reload(long lMapIndex);
extern void regen_register_map(const char * szBaseName, long lMapIndex, int base_x, int base_y);
extern bool is_valid_regen(LPREGEN currRegen);




regen.cpp

Spoiler

Under this:




LPREGEN_EXCEPTION regen_exception_list = NULL;

Add this:




typedef struct SMapDataContainer
{
char szBaseName[256];
int base_x;
int base_y;
}TMapDataContainer;

#define mbMapDataCType std::map<DWORD, TMapDataContainer*>
mbMapDataCType mbMapDataContainer;

At the end of the file add this:




bool is_valid_regen(LPREGEN currRegen)
{
LPREGEN regen;

for (regen = regen_list; regen; regen = regen->next)
{
if (regen == currRegen)
return true;
}
return false;
}

void regen_free_map(long lMapIndex)
{
LPREGEN regen, prev, next;

for (regen = regen_list; regen; regen = regen->next)
{
if (regen->lMapIndex != lMapIndex)
continue;
event_cancel(&regen->event);
REMOVE_FROM_TW_LIST(regen, regen_list, prev, next);
M2_DELETE(regen);
}
}

void regen_reload(long lMapIndex)
{
if (mbMapDataContainer.find(lMapIndex) == mbMapDataContainer.end())
return;

char szFilename[256];

snprintf(szFilename, sizeof(szFilename), "%sregen.txt", mbMapDataContainer[lMapIndex]->szBaseName);
regen_load(szFilename, lMapIndex, mbMapDataContainer[lMapIndex]->base_x, mbMapDataContainer[lMapIndex]->base_y);

snprintf(szFilename, sizeof(szFilename), "%snpc.txt", mbMapDataContainer[lMapIndex]->szBaseName);
regen_load(szFilename, lMapIndex, mbMapDataContainer[lMapIndex]->base_x, mbMapDataContainer[lMapIndex]->base_y);

snprintf(szFilename, sizeof(szFilename), "%sboss.txt", mbMapDataContainer[lMapIndex]->szBaseName);
regen_load(szFilename, lMapIndex, mbMapDataContainer[lMapIndex]->base_x, mbMapDataContainer[lMapIndex]->base_y);

snprintf(szFilename, sizeof(szFilename), "%sstone.txt", mbMapDataContainer[lMapIndex]->szBaseName);
regen_load(szFilename, lMapIndex, mbMapDataContainer[lMapIndex]->base_x, mbMapDataContainer[lMapIndex]->base_y);
}

void regen_register_map(const char * szBaseName, long lMapIndex, int base_x, int base_y)
{
TMapDataContainer* container = new TMapDataContainer;
memset(container->szBaseName, 0, sizeof(container->szBaseName));
#ifdef __FreeBSD__
strlcpy(container->szBaseName, szBaseName, sizeof(container->szBaseName) - 1);
#else
strncpy(container->szBaseName, szBaseName, sizeof(container->szBaseName) - 1);
#endif
container->base_x = base_x;
container->base_y = base_y;
mbMapDataContainer[lMapIndex] = container;
}

EVENTFUNC(regen_event)

Under this:




LPREGEN regen = info->regen;

Insert this:




if (!is_valid_regen(regen))
return 0;




shop.h

Spoiler

Under this:




void RemoveGuest(LPCHARACTER ch);

Insert this:




void RemoveAllGuests();




shop.cpp

Spoiler

Add this at the end of the file:




void CShop::RemoveAllGuests()
{
if (m_map_guest.empty())
return;
for (GuestMapType::iterator it = m_map_guest.begin(); it != m_map_guest.end(); it++)
{
LPCHARACTER ch = it->first;
if (ch)
{
if (ch->GetDesc() && ch->GetShop() == this)
{
ch->SetShop(NULL);

TPacketGCShop pack;

pack.header = HEADER_GC_SHOP;
pack.subheader = SHOP_SUBHEADER_GC_END;
pack.size = sizeof(TPacketGCShop);

ch->GetDesc()->Packet(&pack, sizeof(pack));
}
}
}
m_map_guest.clear();
}




db/src

ClientManager.cpp

Spoiler

void CClientManager::QUERY_RELOAD_PROTO()

Replace this:




tmp->EncodeHeader(HEADER_DG_RELOAD_PROTO, 0,
sizeof(WORD) + sizeof(TSkillTable) * m_vec_skillTable.size() +
sizeof(WORD) + sizeof(TBanwordTable) * m_vec_banwordTable.size() +
sizeof(WORD) + sizeof(TItemTable) * m_vec_itemTable.size() +
sizeof(WORD) + sizeof(TMobTable) * m_vec_mobTable.size());

With this:




tmp->EncodeHeader(HEADER_DG_RELOAD_PROTO, 0,
sizeof(WORD) + sizeof(TSkillTable) * m_vec_skillTable.size() +
sizeof(WORD) + sizeof(TBanwordTable) * m_vec_banwordTable.size() +
sizeof(WORD) + sizeof(TItemTable) * m_vec_itemTable.size() +
sizeof(WORD) + sizeof(TMobTable) * m_vec_mobTable.size() +
sizeof(WORD) + sizeof(TShopTable) * m_iShopTableSize +
sizeof(WORD) + sizeof(TRefineTable)* m_iRefineTableSize +
sizeof(WORD) + sizeof(TItemAttrTable)*m_vec_itemAttrTable.size() +
sizeof(WORD) + sizeof(TItemAttrTable)*m_vec_itemRareTable.size());

Then under this:




tmp->EncodeWORD(m_vec_mobTable.size());
tmp->Encode(&m_vec_mobTable[0], sizeof(TMobTable) * m_vec_mobTable.size());

Add this:




tmp->EncodeWORD(m_iShopTableSize);
tmp->Encode(m_pShopTable, sizeof(TShopTable) * m_iShopTableSize);

tmp->EncodeWORD(m_iRefineTableSize);
tmp->Encode(m_pRefineTable, sizeof(TRefineTable) * m_iRefineTableSize);

tmp->EncodeWORD(m_vec_itemAttrTable.size());
tmp->Encode(&m_vec_itemAttrTable[0], sizeof(TItemAttrTable) * m_vec_itemAttrTable.size());

tmp->EncodeWORD(m_vec_itemRareTable.size());
tmp->Encode(&m_vec_itemRareTable[0], sizeof(TItemAttrTable) * m_vec_itemRareTable.size());




And finally let me wish you all good luck for the setup
;)
If you have further question(s), remark(s), or anything that you want to ask or suggest, feel free to post it here, or send it in PM.

If you get error(s) please upload the affected (and edited) file to and link it in your post, to make my work easier and probably I will be able to help you only in one post, so please spare me from asking basic requests like "Could you upload...". Thank you
;)


Have a nice day,
~masodikbela

Hello dear user,

Your post will be under surveillance by bots for the next few hours.

Forum description : Metin2 private server, Metin2 download, Metin2 support, Metin2 Forum, Metin2 Pvp Servers, Errors, Bugs, Requests, Metin2 Pvp Forum, Everything About Metin2.
 
Top