Çözüldü P2P Dungeon Hk.

  • Konuyu açan Konuyu açan brave
  • Açılış Tarihi Açılış Tarihi
  • Yanıt Yanıt 9
  • Gösterim Gösterim 89
Bu konu çözüme ulaştırılmıştır. Çözüm için konuya yazılan tüm yorumları okumayı unutmayın. Eğer konudaki yorumlar sorununuzu çözmediyse yeni bir konu açabilirsiniz.
Durum
İçerik kilitlendiği için mesaj gönderimine kapatıldı.

brave

MT Üye
MT Üye
Mesaj
216
Çözümler
7
Beğeni
51
Puan
479
Ticaret Puanı
0
Şuan hali hazırda tapınak haritası (catacomb giriş npc) her ch'nin core2'sinde yer alıyor fakat catacomb haritasını ch99'a aldım. bu nedenle giriş yaparken ışınlamıyor. d.new_jump ve d.new_jump_party ile ışınlamıyor farklı processlerde olduğu için. Bunu p2p olarak nasıl çözebilirim giriş npcsi hangi coreda olursa olsun ch99'daki haritaya gitmesi için? örnek questim bu şekilde tek kat olarak yazdım:

Lua (Quest):
Genişlet Daralt Kopyala
quest catacomb_dungeon begin
    state start begin

        when 20367.chat."Şeytan Katakombu " begin
            local name = pc.get_name()
            local npc_name = "Şeytan Katakombu "
            say_title(npc_name.." - "..name)
            say("Merhaba, zindana gitmek ister misin?")
            local x = select("Tek Başına","Parti ile","İptal")
            if x == 1 then
                say_title(npc_name.." - "..name)
                say("")
                say("Tek başına girmek ister misin?")
                local c = select("Evet","İptal")
                if c == 1 then

                    if pc.get_level() < 75 then
                        say_title(npc_name.." - "..name)
                        say("")
                        say("Min Seviye: 75")
                        return
                    end

                    if pc.getf("catacomb_dungeon","cooldown") > get_global_time() then
                        local r_cooldown = pc.getf("catacomb_dungeon","cooldown") - get_global_time()
                        say_title(npc_name.." - "..name)
                        say("")
                        say("Soğuma Süresi: ")
                        say(r_cooldown.." saniye... ")
                        return
                    end

                    if pc.count_item(30319) < 1 then
                        say_title(npc_name.." - "..name)
                        say("")
                        say("Küçülen kafa yok! ")
                        say_item_vnum(30319,1)
                        return
                    else
                        pc.remove_item(30319,1)
                        d.new_jump(216,3145*100,13188*100)
                        if d.select(d.get_map_index()) then
                            d.setf("first_regen",1)
                            d.setf("DungeonBlock",1)
                        end
                    end
                else
                    return
                end

            elseif x == 2 then
                say_title(npc_name.." - "..name)
                say("")
                say("Parti ile girmek ister misin? ")
                local c = select("Evet","İptal")
                if c == 1 then
                    if not party.is_party() then
                        say_title(npc_name.." - "..name)
                        say("")
                        say("Partin yok!")
                        return
                    end
                    if party.get_near_count() < 2 then
                        say_title(npc_name.." - "..name)
                        say("")
                        say("Parti üyesi yok. Minimum:2 Üye")
                        return
                    end
                    local user_fail_level = {}
                    local user_fail_ticket = {}
                    local user_fail_cooldown = {}
                    local ticketCheck = true
                    local LevelCheck = true
                    local CooldownCheck = true
                    local pids = {party.get_member_pids()}
                    for i, pid in next, pids, nil do
                        q.begin_other_pc_block(pid)
                        if pc.get_level() < 75 then
                            table.insert(user_fail_level, pc.get_name())
                            LevelCheck = false
                        end
                        if pc.count_item(30319) < 1 then
                            table.insert(user_fail_ticket, pc.get_name())
                            ticketCheck = false
                        end
                        if pc.getf("catacomb_dungeon","cooldown") > get_global_time() then
                            table.insert(user_fail_cooldown, pc.get_name())
                            CooldownCheck = false
                        end
                        q.end_other_pc_block()
                    end

                    if ticketCheck == false then
                        say("Bileti olmayan oyuncular: ")
                        local a = 1
                        for i, name in next, user_fail_ticket, nil do
                            say(string.format("%d. %s",a,name))
                            a = a+1
                        end
                        say("")
                        say_item_vnum(30319,1)
                        return
                    end

                    if LevelCheck == false then
                        say("Düşük seviyeli oyuncular: ")
                        local a = 1
                        for i, name in next, user_fail_level, nil do
                            say(string.format("%d. %s",a,name))
                            a = a+1
                        end
                        say("")
                        return
                    end

                    if CooldownCheck == false then
                        say("Soğuma etkisi devam ediyor: ")
                        local a = 1
                        for i, name in next, user_fail_cooldown, nil do
                            say(string.format("%d. %s",a,name))
                            a = a+1
                        end
                        return
                    end

                    if ticketCheck == true and LevelCheck == true and CooldownCheck == true then
                        for i, pid in next, pids, nil do
                            q.begin_other_pc_block(pid)
                            pc.remove_item(30319,1)
                            q.end_other_pc_block()
                        end
                        d.new_jump_party(216,3145,13188)
                        if d.select(d.get_map_index()) then
                            d.setf("first_regen",1)
                            d.setf("DungeonBlock",1)
                        end
                    end
                else
                    return
                end
            end
        end

        when login with pc.get_map_index() >= 2160000 and pc.get_map_index() <= 2169990 begin
            local index = pc.get_map_index()
            if d.select(index) then
                if d.getf("first_regen") == 1 then
                    notice_all("[Zindan Duyurusu] ".. pc.get_name() .." Şeytan Katakombuna giriş yaptı.")
                    d.setf("first_regen",0)
                    d.setf("start_time", get_global_time())
                    d.setf("real_time",get_global_time()+60*60)
                    
                    d.spawn_mob(2598,74,1105)
                    d.mission_notice(d.get_map_index(),"Azrail'i katlet!")
                    
                    server_timer("catacomb_dungeon_timer",60*60,d.get_map_index())
                end
            end
        end

        when catacomb_dungeon_timer.server_timer begin
            if d.select(get_server_timer_arg()) then
                d.setf("DungeonBlock",0)
                d.global_warp_all_to_base(5914*100,992*100,get_server_timer_arg(),65)
            end
        end

        when 2598.kill with pc.get_map_index() >= 2160000 and pc.get_map_index() <= 2169990 begin
            if d.select(pc.get_map_index()) then
                d.mission_notice(d.get_map_index(),"Tebrikler, Azrail'i yendin!")
                d.setqf2("catacomb_dungeon","cooldown",get_global_time()+60*60)
                server_timer("catacomb_dead",10,d.get_map_index())
            end
        end

        when catacomb_dead.server_timer begin
            local index = get_server_timer_arg()
            if d.select(index) then
                if d.getf("DungeonBlock") == 1 then
                    d.mission_notice(index,"Görev tamamlandı. Çıkış yapılıyor.")
                    d.setf("DungeonBlock",0)
                    d.setf("real_time",0)
                    d.setf("first_regen",0)
                    
                    clear_server_timer("catacomb_dungeon_timer",index)

                    d.completed(d.get_map_index())
                    d.increase_completed(2598)
                    d.set_fastest(2598, get_global_time() - d.getf("start_time"))
                    d.update_info()

                    d.global_warp_all_to_base(5914*100,992*100,index,65)
                end
            end
        end

        when logout with pc.get_map_index() >= 2160000 and pc.get_map_index() <= 2169990 begin
            if d.select(pc.get_map_index()) then
                if d.getf("DungeonBlock") == 1 then
                    pc.setf("catacomb_dungeon","map",d.get_map_index())
                    pc.setf("catacomb_dungeon","time",get_global_time()+5*60)
                    pc.setf("catacomb_dungeon","channel",pc.get_channel_id())
                else
                    pc.setf("catacomb_dungeon","map",0)
                    pc.setf("catacomb_dungeon","time",0)
                    pc.setf("catacomb_dungeon","channel",0)
                end
            end
        end

        when 20367.chat."Zindana Geri Dön..." with pc.getf("catacomb_dungeon","map") >= 1 begin
            local channelIndex = pc.getf("catacomb_dungeon","channel")
            if channelIndex == pc.get_channel_id() then
                local dungeonMapIndex = pc.getf("catacomb_dungeon","map")

                if d.select(dungeonMapIndex) then
                    if get_global_time() > pc.getf("catacomb_dungeon","time") then
                        say("Beş dakika boyunca geri dönme hakkını kaybettiniz.")
                        pc.setf("catacomb_dungeon","map",0)
                        pc.setf("catacomb_dungeon","time",0)
                        pc.setf("catacomb_dungeon","channel",0)
                        return
                    end
                    pc.warp(3145*100, 13188*100, dungeonMapIndex)
                else
                    say("Açtığınız zindan yok edildi....")
                    pc.setf("catacomb_dungeon","map",0)
                    pc.setf("catacomb_dungeon","time",0)
                    pc.setf("catacomb_dungeon","channel",0)
                    return
                end
            else
                say("Açtığınız zindan bu kanalda görünmüyor.")
                say(string.format("Bu kanalda açılan zindanınız: %d",channelIndex))
                return
            end
        end
    end
end
 
Çözüm
Filesini martysama olarak varsayıyorum.
game/src/packet.h

HEADER_GG_BIG_NOTICE arat yoksa HEADER_GG_CHECK_AWAKENESS arat.
HEADER_GG_DUNGEON_JUMP= 31,
ekle eğer 31 varsa olmayan bir rakam gir.

packet.h en altına gel
#pragma pack()
#endif

üstüne

C++:
Genişlet Daralt Kopyala
typedef struct SPacketGGDungeonJump

{

    BYTE bHeader;

    BYTE bType;

    long lMapIndex;

    long x;

    long y;

    DWORD dwPID;

} TPacketGGDungeonJump;

bunu gir, eğer dwPID falan değiştirildiyse veya diğerleri, kendi filesindeki ile aynısını uygula.

input.h gir

protected veya public'lerden tekinin içerisinde
void DungeonJump(LPDESC d, const char* c_pData);

bunu gir.

input_p2p.cpp gir

case HEADER_GG_CHECK_AWAKENESS: arat.


C++:
Genişlet Daralt Kopyala
case HEADER_GG_DUNGEON_JUMP...
elinde source varsa işlemi source taraflı yapman daha mantıklı veya çift ışınlanma ile core geçirmesi yapmalısın. Fakat en sağlıklısı source üzerinden yapmak.
 
elinde source varsa işlemi source taraflı yapman daha mantıklı veya çift ışınlanma ile core geçirmesi yapmalısın. Fakat en sağlıklısı source üzerinden yapmak.
Evet source mevcut fakat source tam olarak ne yapacağım bununla ilgili?
 
Filesini martysama olarak varsayıyorum.
game/src/packet.h

HEADER_GG_BIG_NOTICE arat yoksa HEADER_GG_CHECK_AWAKENESS arat.
HEADER_GG_DUNGEON_JUMP= 31,
ekle eğer 31 varsa olmayan bir rakam gir.

packet.h en altına gel
#pragma pack()
#endif

üstüne

C++:
Genişlet Daralt Kopyala
typedef struct SPacketGGDungeonJump

{

    BYTE bHeader;

    BYTE bType;

    long lMapIndex;

    long x;

    long y;

    DWORD dwPID;

} TPacketGGDungeonJump;

bunu gir, eğer dwPID falan değiştirildiyse veya diğerleri, kendi filesindeki ile aynısını uygula.

input.h gir

protected veya public'lerden tekinin içerisinde
void DungeonJump(LPDESC d, const char* c_pData);

bunu gir.

input_p2p.cpp gir

case HEADER_GG_CHECK_AWAKENESS: arat.


C++:
Genişlet Daralt Kopyala
case HEADER_GG_DUNGEON_JUMP:

        if (iBytesBorne < sizeof(TPacketGGDungeonJump))

            return -1;

        DungeonJump(d, c_pData);

        return sizeof(TPacketGGDungeonJump);

altına ekle } içerisinde ekliceksin.

aynı dosyada arat void CInputP2P::BlockChat(const char * c_pData) const


C++:
Genişlet Daralt Kopyala
void CInputP2P::DungeonJump(LPDESC d, const char* c_pData)

{

    TPacketGGDungeonJump* p = (TPacketGGDungeonJump*)c_pData;



    if (!SECTREE_MANAGER::instance().GetMapRegion(p->lMapIndex))

        return;



    if (p->bType == 0)

    {

        LPCHARACTER ch = CHARACTER_MANAGER::instance().FindByPID(p->dwPID);

        if (ch)

        {

            CDungeonManager::instance().Create(p->lMapIndex);

            ch->WarpSet(p->x, p->y, p->lMapIndex);

        }

    }

    else if (p->bType == 1)

    {

        LPCHARACTER leader = CHARACTER_MANAGER::instance().FindByPID(p->dwPID);

        if (leader && leader->GetParty())

        {

            CDungeonManager::instance().Create(p->lMapIndex);

            leader->GetParty()->WarpToDungeon(p->lMapIndex, p->x, p->y);

        }

    }

}

fonksiyonun altına ekle

questlua_dungeon.cpp gir.

ALUA(dungeon_new_jump) arat

alttaki kodla değiştir.


C++:
Genişlet Daralt Kopyala
ALUA(dungeon_new_jump)

    {

        if (lua_gettop(L) < 3)

        {

            sys_err("Yetersiz parametre");

            return 0;

        }



        if (!lua_isnumber(L, 1) || !lua_isnumber(L, 2) || !lua_isnumber(L, 3))

        {

            sys_err("Hatalı parametre");

            return 0;

        }



        const long lMapIndex = (long)lua_tonumber(L,1);



        if (!SECTREE_MANAGER::instance().GetMap(lMapIndex))

        {

            TPacketGGDungeonJump pack;

            pack.bHeader = HEADER_GG_DUNGEON_JUMP;

            pack.bType = 0;

            pack.lMapIndex = lMapIndex;

            pack.x = (int)lua_tonumber(L, 2);

            pack.y = (int)lua_tonumber(L, 3);

        

            const LPCHARACTER ch = CQuestManager::instance().GetCurrentCharacterPtr();

            if (ch)

            {

                pack.dwPID = ch->GetPlayerID();

                P2P_MANAGER::instance().Send(&pack, sizeof(pack));

            }

            return 0;

        }



        const LPDUNGEON pDungeon = CDungeonManager::instance().Create(lMapIndex);



        if (!pDungeon)

        {

            sys_err("Zindan olusturulamadi. Harita indeksi: %d", lMapIndex);

            return 0;

        }



        const LPCHARACTER ch = CQuestManager::instance().GetCurrentCharacterPtr();



        ch->WarpSet((int) lua_tonumber(L, 2), (int)lua_tonumber(L, 3), pDungeon->GetMapIndex());

        return 0;

    }

ALUA(dungeon_new_jump_party) arat

alttaki ile değiştir.


C++:
Genişlet Daralt Kopyala
ALUA(dungeon_new_jump_party)

    {

        if (lua_gettop(L)<3 || !lua_isnumber(L,1) || !lua_isnumber(L, 2) || !lua_isnumber(L,3))

        {

            sys_err("Yetersiz parametre");

            return 0;

        }



        const long lMapIndex = (long)lua_tonumber(L,1);



        if (!SECTREE_MANAGER::instance().GetMap(lMapIndex))

        {

            TPacketGGDungeonJump pack;

            pack.bHeader = HEADER_GG_DUNGEON_JUMP;

            pack.bType = 1;

            pack.lMapIndex = lMapIndex;

            pack.x = (int)lua_tonumber(L, 2);

            pack.y = (int)lua_tonumber(L, 3);



            const LPCHARACTER ch = CQuestManager::instance().GetCurrentCharacterPtr();

            if (ch && ch->GetParty())

            {

                pack.dwPID = ch->GetPlayerID();

                P2P_MANAGER::instance().Send(&pack, sizeof(pack));

            }

            return 0;

        }



        const LPDUNGEON pDungeon = CDungeonManager::instance().Create(lMapIndex);



        if (!pDungeon)

        {

            sys_err("Zindan olusturulamadi. Harita indeksi: %d", lMapIndex);

            return 0;

        }



        const LPCHARACTER ch = CQuestManager::instance().GetCurrentCharacterPtr();



        if (ch->GetParty() == nullptr)

        {

            sys_err ("Grup olmadan zindana girilemez.");

            return 0;

        }

        pDungeon->JumpParty(ch->GetParty(), ch->GetMapIndex(), (int)lua_tonumber(L, 2), (int)lua_tonumber(L, 3));



        return 0;

    }


NOT: Elimdeki marty sürümünden yola çıkarak tarif ettim, gerekli testleri yapmayı unutma. TAB ayarını kendi dosya düzenine göre yap.
Quest tarafına dokunmana gerek yok, source tarafında bu işlemleri yapman yeterli olur, kodları çok düzenli editör kullanarak yapmadım idare et.
Herhangi test yapmadım hatalar alırsan paylaş çözümüne bakalım.
Yeni fonksiyon yerine olağan yapıyı p2p'ye taşıdık, dungeon_new_jump_party ve dungeon_new_jump p2p odaklı çalışır işlem sadece 2sine yapıldı.
 
Çözüm
Anladım source üzerinde düzenleme diyince tam oturmamıştı kafamda o an ama direkt yeni quest fonksiyonu oluşturup bununla gg paket yollayarak ışınlama mantığını değiştirdik. aslında komple bu tek kat dungeonları c++ tarafına mı geçirsem acaba cdungeonı referans alarak
 
Anladım source üzerinde düzenleme diyince tam oturmamıştı kafamda o an ama direkt yeni quest fonksiyonu oluşturup bununla gg paket yollayarak ışınlama mantığını değiştirdik. aslında komple bu tek kat dungeonları c++ tarafına mı geçirsem acaba cdungeonı referans alarak
aslında bu yaptığımız 2 adet quest fonksiyonunu p2p'ye geçirmek oldu. Zindanı geçirmedik, tabi zindanıda komple src tarafına geçirebilirsin, quest tarafına sadece girişi verebilir veya zindan bilgi gibi sistem varsa butona atama yaparak direkt zindana alabilirsin questsiz. Offical tarafta artık zindanların bir çok olayı src tarafında yapılıyor, şahsi düşüncem daha mantıklı ve daha sağlıklı fakat tek tek zindanları src tarafına geçirmek biraz uğraştırır ve testlerinin yapılması gerekir.

Çok yüksek online düşünmüyorsanız p2p taraflı kullanacağınız fonksiyonları geçirip, quest lua taraflı ilerlemeniz daha mantıklı fakat mükemmeliyetçi düşünüyorsanız src geçirebilirsiniz. Fakat zindanda yapacağınız her değişiklik için build almanız gerekir.

Yine kullanım sizin tercihiniz.
Şöyle bir yöntemde izleyebilirsiniz, tek kat zindan kullandığınız için genellikle oyuncu tarafı o tarz durumlarda zindan grafiklerine pek odaklanmaz tek kat olduğu için, bir çok zindan mapı eklemek yerine 1 tane kolezyum tarzında bir map yapıp, orayı kullanabilirsiniz, ister klon mantığı, ister zindan bilgi entegreli boss çağırma sistemi veya daha farklı düşüncelerde olabilir tabiki.
Nihayetinde ucu açık bir kapı bu, hayal gücü ne kadar geniş ve işlevliyse yapılabilecekler de o kadar oluyor.
 
aslında bu yaptığımız 2 adet quest fonksiyonunu p2p'ye geçirmek oldu. Zindanı geçirmedik, tabi zindanıda komple src tarafına geçirebilirsin, quest tarafına sadece girişi verebilir veya zindan bilgi gibi sistem varsa butona atama yaparak direkt zindana alabilirsin questsiz. Offical tarafta artık zindanların bir çok olayı src tarafında yapılıyor, şahsi düşüncem daha mantıklı ve daha sağlıklı fakat tek tek zindanları src tarafına geçirmek biraz uğraştırır ve testlerinin yapılması gerekir.

Çok yüksek online düşünmüyorsanız p2p taraflı kullanacağınız fonksiyonları geçirip, quest lua taraflı ilerlemeniz daha mantıklı fakat mükemmeliyetçi düşünüyorsanız src geçirebilirsiniz. Fakat zindanda yapacağınız her değişiklik için build almanız gerekir.

Yine kullanım sizin tercihiniz.
Şöyle bir yöntemde izleyebilirsiniz, tek kat zindan kullandığınız için genellikle oyuncu tarafı o tarz durumlarda zindan grafiklerine pek odaklanmaz tek kat olduğu için, bir çok zindan mapı eklemek yerine 1 tane kolezyum tarzında bir map yapıp, orayı kullanabilirsiniz, ister klon mantığı, ister zindan bilgi entegreli boss çağırma sistemi veya daha farklı düşüncelerde olabilir tabiki.
Nihayetinde ucu açık bir kapı bu, hayal gücü ne kadar geniş ve işlevliyse yapılabilecekler de o kadar oluyor.
Evet onu düşünerekten zindanların kurallarını ve aşamalarını json tutup full c++ taraflı yazmaya karar verdim. şeytan kulesi hariç diğer hepsi tek kat olacak şimdilik. ilk etapta tek katları geçireceğim daha sonra kuleyi geçireceğim. aşama eklememin sebebi aslında tek kat olanlara tek aşama verip kule gibi çok katlı olanların aşamalarını jsondan kontrol etmeyi planlıyorum her dungeon için c++de aşama yazmak yerine. ufaktan başladım yazmaya hadi hayırlısı :D

Gemini Pro bakalım bizi nereye kadar götürecek bu dungeon sisteminde :D

1783901478921.webp
 
Düşüncen gayet mantıklı, json tabanlı veriyi tutup işletebilirsin, yönetimsel olarak işini baya kolaylaştırır, sonradan zindan eklediğinde vs. rahatlıkla json tarafından tık tık diye ekler geçersin.


Hadi bakalım güzel bir şeyler çıkarırsın diye düşünüyorum. Şimdiden başarılar.
 
Düşüncen gayet mantıklı, json tabanlı veriyi tutup işletebilirsin, yönetimsel olarak işini baya kolaylaştırır, sonradan zindan eklediğinde vs. rahatlıkla json tarafından tık tık diye ekler geçersin.


Hadi bakalım güzel bir şeyler çıkarırsın diye düşünüyorum. Şimdiden başarılar.

Teşekkür ederim
 
Durum
İçerik kilitlendiği için mesaj gönderimine kapatıldı.
Geri
Üst