Kodların arasında sessizce duran Metin2 detayları

Kaptan Yosun

Discord: kaptanyosun
Site yetkilisi
Acemi Moderatör
Premium Üye
Mesaj
667
Çözümler
21
Beğeni
514
Puan
839
Ticaret Puanı
0
Japonca dil desteğini kaldırırken fark ettim,

char_manager.cpp içinde:
    // 왜구 스폰할지말지를 결정할 수 있게함
    {
        if (dwVnum == 5001 && !quest::CQuestManager::instance().GetEventFlag("japan_regen"))
        {
            sys_log(1, "WAEGU[5001] regen disabled.");
            return NULL;
        }
    }

    // 해태를 스폰할지 말지를 결정할 수 있게 함
    {
        if (dwVnum == 5002 && !quest::CQuestManager::instance().GetEventFlag("newyear_mob"))
        {
            sys_log(1, "HAETAE (new-year-mob) [5002] regen disabled.");
            return NULL;
        }
    }

    // 광복절 이벤트
    {
        if (dwVnum == 5004 && !quest::CQuestManager::instance().GetEventFlag("independence_day"))
        {
            sys_log(1, "INDEPENDECE DAY [5004] regen disabled.");
            return NULL;
        }
    }

böyle bir kısım var. Kore'nin bağımsızlık gününde;
Lua (Quest):
japan_regen
EventFlag'ını çalıştırıyorlar ve 5001 Vnum'lu mob yani Korsan Tanaka regen olmuyor.
Fark ettiyseniz Tanaka Korece bir ad değil, Japonca.
Nasıl olsa sadece geliştiriciler okuyabilir diye sys_log içinde Korsan Tanaka'ya Waegu demişler.

"Tochak Waegu ( Hangul: 토착왜구 ; Hanja : 土着倭寇 ; lit. yerli Japon korsanları) veya kısaca To-wae, çoğunlukla Güney Koreli solcular tarafından Japon yanlısı olarak algılanan Güney Koreli muhafazakarlara karşı kullanılan bir Güney Koreli siyasi hakarettir. Tochak Waegu, Maegukno (Hangul: 매국노; Hanja: ihanet eden; Ulusal isyancılar) veya Minjok Banyeokja (Korece: 민족반역자; Hanja: Ulusal isyancılar veya hainler) ile aynı anlama gelir."

Anlayacağınız bu kodu yazan her kimse aşırı solcu, milliyetçi ve anti-Japon ırkçısı imiş.

Detaylı okuma:
Linkleri görebilmek için giriş yap veya kayıt ol.


Sizin de kodlar içinde fark ettiğiniz detaylar varsa yorumlarda konuşalım.
 
o "waegu" o kişi olan "waegu" değil :D asya kültüründe korsanı temsil ediyor.

Linkleri görebilmek için giriş yap veya kayıt ol.



Linkleri görebilmek için giriş yap veya kayıt ol.
Bence aynı şey. Sizin attığınız tarih sayfası, benim attığım modern Korecedeki politik argo olarak kullanımı.

Tochak Waegu (
Linkleri görebilmek için giriş yap veya kayıt ol.
:
Linkleri görebilmek için giriş yap veya kayıt ol.
;
Linkleri görebilmek için giriş yap veya kayıt ol.
: 土着倭寇; lit. indigenous
Linkleri görebilmek için giriş yap veya kayıt ol.
)

Japanese Pirates sayfasına tıklarsanız sizin attığınız sayfaya yönlendiriyor.

Kaynak kodundakini belki hakaret olarak değil de tarihi bir olgu olarak kullandılar diyeceğim de o zaman niye Kore bağımsızlık gününde Waegu'nun regenini kapatsınlar?
 
Son düzenleme:
@MT2Dev seversin böyle detayları
Detaydan çok saçmalık var desem daha doğru olur. 😄 Tek tek incelerken o kadar fazla şeye denk geliyorsunuz ki yani bazılarını görünce gerçekten üstümü başımı yırtma aşamasına geldim. Tek tek çok fazla örnek verilebilir ama ben genel olarak metin2 projesinin kaynak kodları hakkında bir yorum yapayım;

Hard-coded bölümlerle dolu (nerdeyse tamamı), yazılım eğitimi alan bir gence okulda gösterecekleri ve "sakın bunu yapma" diyecekleri bütün yanlış teknikleri içeren, projenin başlangıcında yer alan bir iki senior yazılımcının yaptığı işin üstüne ekleme yaparken çalışan hiçbir şeyi değiştirmeyip 20 yıl sonra bile 2004'e uygun yazılan demode her şeyi muhafaza eden (ki o ekipten hala devam edenler var diye biliyorum, onlarda kaçak kat çıkmaya devam ediyor), C++ bir projede C tipi çok fazla referans içeren, null pointer ve overflow kontrollerinin yüzlercesinin eksik olduğu ve bütün bunları göz önünde bulundurup okurken bu oyun bu altyapıyla tüm dünyada nasıl anlık 5 milyon oyuncuya ulaştı diye düşündüren bir proje, hem saygı duyup hem de lanet ettiren cinsten. :LOL:
 
Oyunun kodlarında %2 ihtimalle mobun yerine geri dönmesi yerine kaçmasını sağlayan bir kod var;


C++:
void CHARACTER::StateBattle()
{
    if (IsStone())
    {
        sys_err("Stone must not use battle state (name %s)", GetName());
        return;
    }

    if (IsPC() || !CanMove() || IsStun())
    {
        return;
    }

    const auto victim = GetVictim();

    if (IsCoward())
    {
        if (IsDead())
        {
            return;
        }

        SetVictim(nullptr);

        if (number(1, 50) != 1) //
        {
            GotoState(m_stateIdle);
            m_dwStateDuration = 1;
        }
        else //
        {
            CowardEscape();
        }

        return;
    }


ayrıca 50000 ve 10000 de bir ihtimalle item düşmesini 10 kat ve 5 kat arttıran bir ihtimal daha var;


C++:
bool ITEM_MANAGER::GetDropPct(const LPCHARACTER pkChr, const LPCHARACTER pkKiller, OUT int32_t& iDeltaPercent, OUT int32_t& iRandRange)
{
    if (!pkChr || !pkKiller) [[unlikely]]
    {
        return false;
    }

    iDeltaPercent = 100;

    if (!pkChr->IsStone() && pkChr->GetMobRank() >= MOB_RANK_BOSS)
    {
        iDeltaPercent = PERCENT_LVDELTA_BOSS(pkKiller->GetLevel(), pkChr->GetLevel());
    }
    else
    {
        iDeltaPercent = PERCENT_LVDELTA(pkKiller->GetLevel(), pkChr->GetLevel());
    }

    if (1 == number(1, 50000)) [[unlikely]]
    {
        iDeltaPercent += 1000;
    }
    else if (1 == number(1, 10000)) [[unlikely]]
    {
        iDeltaPercent += 500;
    }

aynı ihtimal yang düşmesi için de için de var;

C++:
    if (1 == number(1, 50000)) [[unlikely]] // 1/50000 È®·ü·Î µ·ÀÌ 10¹è
    {
        iGoldMultipler *= 10;
    }
    else if (1 == number(1, 10000)) [[unlikely]] // 1/10000 È®·ü·Î µ·ÀÌ 5¹è
    {
        iGoldMultipler *= 5;
    }
 
Oyunun kodlarında %2 ihtimalle mobun yerine geri dönmesi yerine kaçmasını sağlayan bir kod var;


C++:
void CHARACTER::StateBattle()
{
    if (IsStone())
    {
        sys_err("Stone must not use battle state (name %s)", GetName());
        return;
    }

    if (IsPC() || !CanMove() || IsStun())
    {
        return;
    }

    const auto victim = GetVictim();

    if (IsCoward())
    {
        if (IsDead())
        {
            return;
        }

        SetVictim(nullptr);

        if (number(1, 50) != 1) //
        {
            GotoState(m_stateIdle);
            m_dwStateDuration = 1;
        }
        else //
        {
            CowardEscape();
        }

        return;
    }


ayrıca 50000 ve 10000 de bir ihtimalle item düşmesini 10 kat ve 5 kat arttıran bir ihtimal daha var;


C++:
bool ITEM_MANAGER::GetDropPct(const LPCHARACTER pkChr, const LPCHARACTER pkKiller, OUT int32_t& iDeltaPercent, OUT int32_t& iRandRange)
{
    if (!pkChr || !pkKiller) [[unlikely]]
    {
        return false;
    }

    iDeltaPercent = 100;

    if (!pkChr->IsStone() && pkChr->GetMobRank() >= MOB_RANK_BOSS)
    {
        iDeltaPercent = PERCENT_LVDELTA_BOSS(pkKiller->GetLevel(), pkChr->GetLevel());
    }
    else
    {
        iDeltaPercent = PERCENT_LVDELTA(pkKiller->GetLevel(), pkChr->GetLevel());
    }

    if (1 == number(1, 50000)) [[unlikely]]
    {
        iDeltaPercent += 1000;
    }
    else if (1 == number(1, 10000)) [[unlikely]]
    {
        iDeltaPercent += 500;
    }

aynı ihtimal yang düşmesi için de için de var;

C++:
    if (1 == number(1, 50000)) [[unlikely]] // 1/50000 È®·ü·Î µ·ÀÌ 10¹è
    {
        iGoldMultipler *= 10;
    }
    else if (1 == number(1, 10000)) [[unlikely]] // 1/10000 È®·ü·Î µ·ÀÌ 5¹è
    {
        iGoldMultipler *= 5;
    }
50000 ve 10000 oranda patladım
 
Oyunun kodlarında %2 ihtimalle mobun yerine geri dönmesi yerine kaçmasını sağlayan bir kod var;


C++:
void CHARACTER::StateBattle()
{
    if (IsStone())
    {
        sys_err("Stone must not use battle state (name %s)", GetName());
        return;
    }

    if (IsPC() || !CanMove() || IsStun())
    {
        return;
    }

    const auto victim = GetVictim();

    if (IsCoward())
    {
        if (IsDead())
        {
            return;
        }

        SetVictim(nullptr);

        if (number(1, 50) != 1) //
        {
            GotoState(m_stateIdle);
            m_dwStateDuration = 1;
        }
        else //
        {
            CowardEscape();
        }

        return;
    }


ayrıca 50000 ve 10000 de bir ihtimalle item düşmesini 10 kat ve 5 kat arttıran bir ihtimal daha var;


C++:
bool ITEM_MANAGER::GetDropPct(const LPCHARACTER pkChr, const LPCHARACTER pkKiller, OUT int32_t& iDeltaPercent, OUT int32_t& iRandRange)
{
    if (!pkChr || !pkKiller) [[unlikely]]
    {
        return false;
    }

    iDeltaPercent = 100;

    if (!pkChr->IsStone() && pkChr->GetMobRank() >= MOB_RANK_BOSS)
    {
        iDeltaPercent = PERCENT_LVDELTA_BOSS(pkKiller->GetLevel(), pkChr->GetLevel());
    }
    else
    {
        iDeltaPercent = PERCENT_LVDELTA(pkKiller->GetLevel(), pkChr->GetLevel());
    }

    if (1 == number(1, 50000)) [[unlikely]]
    {
        iDeltaPercent += 1000;
    }
    else if (1 == number(1, 10000)) [[unlikely]]
    {
        iDeltaPercent += 500;
    }

aynı ihtimal yang düşmesi için de için de var;

C++:
    if (1 == number(1, 50000)) [[unlikely]] // 1/50000 È®·ü·Î µ·ÀÌ 10¹è
    {
        iGoldMultipler *= 10;
    }
    else if (1 == number(1, 10000)) [[unlikely]] // 1/10000 È®·ü·Î µ·ÀÌ 5¹è
    {
        iGoldMultipler *= 5;
    }
:muha:
 
O zaman bu konuya özel bir şeyler paylaşayım;

Buffer içindeki bir kod bloğunda Türkiye'deki zayıf makinalardan bahseden Ymir devleri;

libthecore/buffer.cpp:
    if (buffer == NULL)
    {
        CREATE (buffer, BUFFER, 1);
        buffer->mem_size = size;
        // Due to frequent calloc failures in buffer_new (mostly on weaker machines in Turkey),
        // if calloc fails, we empty the buffer pool and retry. - [Ymir Dev Note]
        if (!safe_create (&buffer->mem_data, size))
        {
            // Freeing one buffer from a buffer pool larger than the required buffer size. - [Ymir Dev Note]
            if (!buffer_larger_pool_free (pool_index))
            // If all else fails, as a last resort, free all pools. - [Ymir Dev Note]
            {
                buffer_pool_free();
            }
            CREATE (buffer->mem_data, char, size);
            sys_err ("buffer pool free success.");
        }
    }

Düğün etkinliğine katılan 10.Seviye'den düşük misafirlere Ymir'den muhteşem hediye; ( :ROFLMAO: )

game/wedding.cpp:
    void WeddingMap::SetEnded()
    {
        if (m_pEndEvent)
        {
            sys_err ("WeddingMap::SetEnded - ALREADY EndEvent(m_pEndEvent=%x)", get_pointer (m_pEndEvent));
            return;
        }

        wedding_map_info* info = AllocEventInfo<wedding_map_info>();
        info->pWeddingMap = this;
        m_pEndEvent = event_create (wedding_end_event, info, PASSES_PER_SEC (5));

        Notice (LC_TEXT ("<Sistem> Evlilik toreni bitti."));
        Notice (LC_TEXT ("<Sistem> Otomatik olarak cikis yapacaksiniz."));

        for (auto it = m_set_pkChr.begin(); it != m_set_pkChr.end(); ++it)
        {
            LPCHARACTER ch = *it;
            if (ch->GetPlayerID() == dwPID1 || ch->GetPlayerID() == dwPID2)
            {
                continue;
            }

            if (ch->GetLevel() < 10)
            {
                continue;
            }
            ch->AutoGiveItem (27003, 5);
        }
    }

Balıkçılık için ikinci köylerin daha fazla prob vermesi;

game/fishing.cpp:
    int GetProbIndexByMapIndex (int index)
    {
        if (index > 60)
        {
            return -1;
        }

        switch (index)
        {
            case 1:  // Red    - I.Town
            case 21: // Yellow - I.Town
            case 41: // Blue   - I.Town
                return 0;

            case 3:  // Red    - II.Town
            case 23: // Yellow - II.Town
            case 43: // Blue   - II.Town
                return 1;
        }

        return -1;
    }

Grafik ekibinin isteği üzerine, mobların IDLE modunda belli bir şansla yürümesine olanak sağlayan kod;

game/char_state.cpp:
            // NOTE: When monsters wander around in IDLE state, they currently always run. (They never walk)
            // Since the graphic team wants to see the monster walking, temporarily allow walking or running with a certain probability.
            // (This affects the overall feel of the game, so it only works in test mode for now). - [Ymir Dev Note]
            #ifndef DISABLE_STAMINA_WALK
            if (test_server) // Interesting idea from graphic team, idk if i use this on live version or not but i'm gonna try it with %20 chance on test server. - [MT2Dev Note] - 12/04/2024
            {
                if (number (0, 100) < 80) // Also we have another if (test_server) below, that's also set monsters state to run if they chase enemy. - [MT2Dev Note] - 12/04/2024
                {
                    SetNowWalking (false);
                }
                else
                {
                    SetNowWalking (true);
                }
            }
            #endif //DISABLE_STAMINA_WALK

Bir oyuncunun üzerine çektiği mobu başka bir oyuncu çekmeye çalıştığında bunu engelleyen kontrol; (Deaktif şekilde bulunuyor)

game/char_battle.cpp:
    void operator() (LPENTITY ent)
    {
        if (ent->IsType (ENTITY_CHARACTER))
        {
            LPCHARACTER ch = (LPCHARACTER) ent;
            if (ch->IsPC())
            {
                return;
            }

            if (!ch->IsMonster())
            {
                return;
            }

            /* if (ch->GetVictim() && ch->GetVictim() != m_ch) // If other player pull the monster, when you tried to pull same monster, you can't do it. - [MT2Dev Note] - 04/04/2024
            {
                return;
            } */

            float fDist = DISTANCE_APPROX (m_ch->GetX() - ch->GetX(), m_ch->GetY() - ch->GetY());
            if (fDist > 3000 || fDist < 100)
            {
                return;
            }

            float fNewDist = fDist - m_iLength;
            if (fNewDist < 100)
            {
                fNewDist = 100;
            }

            float degree = GetDegreeFromPositionXY (ch->GetX(), ch->GetY(), m_ch->GetX(), m_ch->GetY());
            float fx;
            float fy;

            GetDeltaByDegree (degree, fDist - fNewDist, &fx, &fy);
            long tx = (long) (ch->GetX() + fx);
            long ty = (long) (ch->GetY() + fy);

            ch->Sync (tx, ty);
            ch->Goto (tx, ty);
            ch->CalculateMoveDuration();
            ch->SyncPacket();
        }
    }
};


Ve son olarak bir önceki yorumda bahsettiğim akıl tutulmalarına kısa örnekler...

Yorumsuz...:
1)
    
ACMD (do_socket_item)
{
    char arg1[256], arg2[256];
    two_arguments (argument, arg1, sizeof (arg1), arg2, sizeof (arg2));

    if (*arg1)
    {
        DWORD dwVnum = 0;
        str_to_number (dwVnum, arg1);

        int iSocketCount = 0; // Neden int ?
        str_to_number (iSocketCount, arg2);

        if (!iSocketCount || iSocketCount >= ITEM_SOCKET_MAX_NUM) // <<---
        {
            iSocketCount = 3; // ???? :D
        }

2)

// 특정 용혼석을 장비창에서 제거할 때에 성공 여부를 결정하고, 실패시 부산물을 주는 함수.
bool DSManager::PullOut (LPCHARACTER ch, TItemPos DestCell, LPITEM& pItem, LPITEM pExtractor)
{
    if (NULL == ch || NULL == pItem) // <<<---
    {
        sys_err ("NULL POINTER. ch(%p) or pItem(%p)", ch, pItem); // ?????? :D
        return false;
    }

3)

ACMD (do_shutdown)
{
    if (NULL == ch) // <<<---
    {
        sys_err ("Accept shutdown command from %s.", ch->GetName()); // ????? :DD
    }
    TPacketGGShutdown p;
    p.bHeader = HEADER_GG_SHUTDOWN;
    P2P_MANAGER::instance().Send (&p, sizeof (TPacketGGShutdown));

    Shutdown (10);
}

4)

bool Cube_InformationInitialize()
{
    for (size_t i = 0; i < s_cube_proto.size(); ++i) //Game-DB SRC Warning Fix 68
    {
        CUBE_DATA* cubeData = s_cube_proto[i];
        const std::vector<CUBE_VALUE>& rewards = cubeData->reward;

        // Hardcoding sucks. - [Ymir Dev Note]   ---   I agree but it was funny when "you" said that lol. - [MT2Dev Note]
        if (1 != rewards.size())
        {
            sys_err ("[CubeInfo] WARNING! Does not support multiple rewards (count: %d)", rewards.size());
            continue;
        }
 
mainlinenin bu yazıları çevirilip stand up gösterisi gibi forumda yayınlanmalı
 
Senior devin packet yorumu

Korece:
//NOTE : 이런 개XXX 정말 이거 Packet설계한 사람은 누구냐. 이렇게 코딩하고 밥이 넘어가나.
//enum을 별도로 구별을 하던가. 아님 namepsace로 구별을 하던가..
//정말 packet generator까지는 바라지도 않는다. 이런 씨XX
//이러다가 숫자 겹치면 누가 책임지는데???

İngilizce:
//NOTE: Holy shit XXX, who really designed this Packet? I wonder if I can get away with coding like this.
//Do you distinguish the enum separately? Or do you distinguish it with namepsace?
//I really don't even want a packet generator. Holy crap
//If the numbers overlap, who is responsible???

Türkçe:
//Has*ktir XXX bu b*ktan paketi kim tasarladı? Bu şekil kodlamayla paçayı sıyırabilecek miyiz?
//Enumları ayrıca ayırıyor musunuz? Yoksa onları namespace ile mi ayırıyorsunuz?
//Gerçekten bir paket oluşturucu istemiyorum. S**eyim.
//Sayılar çakışırsa kim hesap verecek?
 
Bir tane de benden olsun çoğunuz filesınızda Altın Kurbağa isimli mobu görmüştür, ymir bunu ilk tasarlarken kale savaşı, ellenmemiş dosyalarda castle.cpp ve header dosyalarını incelerseniz anlarsınız nasıl bir event olduğunu, kabaca krallıklar kendi kale haritalarına ışınlanıyorlar orada koruyan ve rakip krallık oyuncularına saldıran npcler var ve 8012,8013,8014,8024,8025,8026,8027 metinleri spawn oluyor ve sanırım krallıklar bu metinleri keserek(??) belirli sayıya ulaşınca şampiyon(???) krallığa altın kurbağalar kendi kale mapinde ortaya çıkıyor ve
ödül olarak ne kazanılıyor derseniz işte o muhteşem kod:
Altın Gurbağa:
void castle_frog_die(LPCHARACTER ch, LPCHARACTER killer)
{
    if (NULL == ch || NULL == killer)
        return;

    int    empire = ch->GetEmpire();

    DO_ALL_FROG(i)
    {
        if (ch == GET_FROG(empire, i))
        {
            GET_FROG(empire, i) = NULL;

            killer->PointChange(POINT_GOLD, 10000000 /*1õ¸¸*/, true);
            //CMonarch::instance().SendtoDBAddMoney(30000000/*3õ¸¸*/, killer->GetEmpire(), killer);
            castle_save();
            return;
        }
    }
}
 
Bir tane de benden olsun çoğunuz filesınızda Altın Kurbağa isimli mobu görmüştür, ymir bunu ilk tasarlarken kale savaşı, ellenmemiş dosyalarda castle.cpp ve header dosyalarını incelerseniz anlarsınız nasıl bir event olduğunu, kabaca krallıklar kendi kale haritalarına ışınlanıyorlar orada koruyan ve rakip krallık oyuncularına saldıran npcler var ve 8012,8013,8014,8024,8025,8026,8027 metinleri spawn oluyor ve sanırım krallıklar bu metinleri keserek(??) belirli sayıya ulaşınca şampiyon(???) krallığa altın kurbağalar kendi kale mapinde ortaya çıkıyor ve
ödül olarak ne kazanılıyor derseniz işte o muhteşem kod:
Altın Gurbağa:
void castle_frog_die(LPCHARACTER ch, LPCHARACTER killer)
{
    if (NULL == ch || NULL == killer)
        return;

    int    empire = ch->GetEmpire();

    DO_ALL_FROG(i)
    {
        if (ch == GET_FROG(empire, i))
        {
            GET_FROG(empire, i) = NULL;

            killer->PointChange(POINT_GOLD, 10000000 /*1õ¸¸*/, true);
            //CMonarch::instance().SendtoDBAddMoney(30000000/*3õ¸¸*/, killer->GetEmpire(), killer);
            castle_save();
            return;
        }
    }
}
1m iyi para o devirde :D
 
Senior devin packet yorumu

Korece:
//NOTE : 이런 개XXX 정말 이거 Packet설계한 사람은 누구냐. 이렇게 코딩하고 밥이 넘어가나.
//enum을 별도로 구별을 하던가. 아님 namepsace로 구별을 하던가..
//정말 packet generator까지는 바라지도 않는다. 이런 씨XX
//이러다가 숫자 겹치면 누가 책임지는데???

İngilizce:
//NOTE: Holy shit XXX, who really designed this Packet? I wonder if I can get away with coding like this.
//Do you distinguish the enum separately? Or do you distinguish it with namepsace?
//I really don't even want a packet generator. Holy crap
//If the numbers overlap, who is responsible???

Türkçe:
//Has*ktir XXX bu b*ktan paketi kim tasarladı?
//Enumları ayrıca ayırıyor musunuz? Yoksa onları namespace ile mi ayırıyorsunuz?
//Gerçekten bir paket oluşturucu istemiyorum. S**eyim.
//Sayılar çakışırsa kim hesap verecek?

Bir sistemin içinde ifdef ile verdikleri sayıyı başka pakete de vermişti değil mi, sadece senior değil kodu gören 3-4 kişi gelip comment bırakmış, bunu yapan arkadaşın akıbeti ne oldu acaba merak ettim. :ROFLMAO: Beni en çok düşüncesiz yada vizyonsuz şekilde kodladıkları yerler delirtti.

Mesela
Linkleri görebilmek için giriş yap veya kayıt ol.
(sürekli İngilizcesini yazıp duruyorum, bizde tam bir karşılığı aslında yok ama sabit kodlama diyorlar genelde, wiki sayfası için üstüne tıklayabilirsiniz) olayının en büyük sorununu bir örnekle vereyim, devin isyan ettiği kod gerçekten socket sayısını arttırdığınızda başınıza bela oluyor, tekrar hard-coded şekilde rakamı değiştirip çözüyorlar genelde;

C++:
// Wow, isn't this insane? What's the point of fussing about it when we extend the socket later on -_-;;; - [Ymir Dev Note]
enum EItemUniqueSockets
{
    ITEM_SOCKET_UNIQUE_SAVE_TIME   = ITEM_SOCKET_MAX_NUM - 2,
    ITEM_SOCKET_UNIQUE_REMAIN_TIME = ITEM_SOCKET_MAX_NUM - 1
};
 
Verilen kodları okuduğumda çalıştığım dönem ilgilenmek zorunda kaldığım eski projeler aklıma getirdi. Bunlar yanında hiçbir şey. :D
Ve stresi azaltmanın en iyi yolu gülüp geçmekti. Mimariyi yanlış yapıp kodu arap saçına çeviren mi dersin 2 satırda yazılacak kodu uzatan mı dersin, fonksiyon kullanmak yerine aynı kodu spamlama mı dersin.

Maalesef bi senior kolay kolay yetişmiyor ancak bu kadar core düşüren hatalara rağmen orijinal metin2 iyi kaldırmış o kadar oyuncuyu.
 
Muhtemelen Avrupa İnsan Hakları sebebiyle (tahmin), Ymir sadece Europe dışındaki sunucularda Whisper loglarını tutuyormuş. (Bir zamanlar, şuan TR'de tuttuklarını biliyorum gerisi meçhul)

game/input_main.cpp:
if (buflen > 0)
            {
                TPacketGCWhisper pack;

                pack.bHeader = HEADER_GC_WHISPER;
                pack.wSize = sizeof (TPacketGCWhisper) + buflen;
                pack.bType = bType;
                strlcpy (pack.szNameFrom, ch->GetName(), sizeof (pack.szNameFrom));

                // desc->BufferedPacket을 하지 않고 버퍼에 써야하는 이유는
                // P2P relay되어 패킷이 캡슐화 될 수 있기 때문이다.
                TEMP_BUFFER tmpbuf;

                tmpbuf.write (&pack, sizeof (pack));
                tmpbuf.write (buf, buflen);

                pkDesc->Packet (tmpbuf.read_peek(), tmpbuf.size());

                if (LC_IsEurope() != true) // Avrupalı değilseniz özel mözel dinlemeyiz konseptli :D
                {
                    sys_log (0, "WHISPER: %s -> %s : %s", ch->GetName(), pinfo->szNameTo, buf);
                }
            }

Ekleme; Kodlara bakarken farklı bir detay dikkatimi çekti, bunu da paylaşayım.

game/item.cpp:
// Return false on error state. - [Ymir Dev Note]
bool CItem::EquipTo (LPCHARACTER ch, BYTE bWearCell)
{
    if (!ch)
    {
        sys_err ("EquipTo: nil character");
        return false;
    }

NULL ifadesi de C dilinden C++'a aktarılmış bir ifade ama yıllar içinde çok fazla kullanıldığı için oldukça popüler ve benimsenmiş durumda. Fakat geçmişte C'den geçiş yapan bir çok dev, bazı durumlarda NULL ifadesi yerine nil, nil pointer kullanırdı, aslında C dilinde aralarında bir anlam farkı var (artık işlev farkı olmasa da) bu alışkanlık yüzünden C++'da da aynısını sürdürüp nil kullanıldığını görüyoruz, bu aslında Metin2'nin server tarafını yazan devlerden birinin ana olarak C diline hakim bir dev olduğu sonucunu çıkartmamızı sağlayabilir, ufak bir detay. 😄
 
Son düzenleme:
DropGold fonksiyonunda bir dev notu;

C++:
            if (LC_IsBrazil() == true)
            {
                if (gold >= 213)
                    LogManager::instance().CharLog(this, gold, "DROP_GOLD", "");
            }
            else
            {
                if (gold > 1000) // õ¿ø ÀÌ»ó¸¸ ±â·ÏÇÑ´Ù.
                    LogManager::instance().CharLog(this, gold, "DROP_GOLD", "");
            }

Korece:
// // 브라질에 돈이 없어진다는 버그가 있는데,
// // 가능한 시나리오 중에 하나는,
// // 메크로나, 핵을 써서 1000원 이하의 돈을 계속 버려 골드를 0으로 만들고,
// // 돈이 없어졌다고 복구 신청하는 것일 수도 있다.
// // 따라서 그런 경우를 잡기 위해 낮은 수치의 골드에 대해서도 로그를 남김.

Türkçe:
// Brezilyada para kaybolma problemi var
// Mümkün bir senaryo şu şekilde;
// makro yada hile kullanarak yere 1000 yangdan küçük paralar atıyorlar
// paralarını sıfırlayıp sonra geri vermemiz için destek talebi açıyorlar
// Bu yüzden düşük miktar paraları bile logluyoruz.

Brezilyalılar makro kullanarak yere 200 yang ata ata paraları sıfırlıyorlar, sonra param kayboldu diye ticket açıp paraları geri alıyorlar. 1000 yang altı da serverda loglanmadığı için YMIR paranın neden kaybolduğunu anlamıyor. Bu yüzden normalde 1000 yang üzeri loglanırken Brezilya için 213 (???) yang üzeri loglanıyor.
 
Geri
Üst