Görüş Mesafesi Sistemi

  • Konbuyu başlatan Konbuyu başlatan Admin
  • Başlangıç tarihi Başlangıç tarihi
  • Cevaplar Cevaplar 0
  • Görüntüleme Görüntüleme 38

Admin

Metin2Lobby
Yönetici
Founder
Katılım
6 Mayıs 2022
Mesajlar
52,647
Ticaret : 1 / 0 / 0
Serverinizde haritalarda kasma,donma,takılma gibi bir çok problemden şikayetçi olabilirsiniz düşük sistemlerde bu sıkça karşımıza çıkmaktadır bunun için aşağıda bulunan sistemi deneyebilirsiniz :)
Örnek ; Sizin karakterinizin etrafındaki objeler gözükücektir daha uzaktaki objeler siz oraya gittikçe render olacak ve görünücektir bu yüzden kasma takılma vb olma olasılığını düşürücektir..

picture.gif

İlk Olarak Sunucu Dosyalarımızdan : EterBase/Utils.h Giriş Yapın. ( Alta Verilen Kodları Ekleyiniz )
Kod:
template<typename T> constexpr T LinearInterpolation(const T& tMin, const T& tMax, float fRatio) {     return T((1.0f - fRatio) * tMin + fRatio * tMax); } template<typename T> constexpr T HermiteInterpolation(const T& tMin, const T& tMax, float fRatio) {     fRatio = MINMAX(0.0f, fRatio, 1.0f);     fRatio = fRatio * fRatio * (3.0f - 2.0f * fRatio);     return LinearInterpolation(tMin, tMax, fRatio); }

2. GameLib/Area.h Giriş Yapıyoruz. ( BU KODU )
Kod:
void            Update();
2.1. Bu Kod İle Değiştiriyoruz.
Kod:
void            Update(D3DXVECTOR3& v3Player);
2.2. Ardından Yeniliyoruz

Kod:
void            Refresh();
2.3. Ardından Bu Kodu Giriş Yapın
Kod:
void Refresh ( TObjectInstance * pObjectInstance , bool bRemove );
2.4. Altaki kodu aratıyoruz.

Kod:
void            __UpdateAniThingList();
2.5. Alta Bulunan Kodu Ekleyiniz.
Kod:
void            __UpdateLoadedObjectInstances(D3DXVECTOR3& v3Player); void            __UpdateEffectList(D3DXVECTOR3& v3Player); float            GetMaxLoadingDistanceSqr() const;
2.6. Ardından Tekrar Arama Kısmına yazıp Aratıyoruz
Kod:
BOOL                                            m_bPortalEnable;
2.7. Bu Kısmada Bu Kodu Ekleyiniz
Kod:
std::vector<CEffectInstance*>                    m_kVct_pkEftInstSort; // for rendering         int                                                m_iUpdateCount;
2.8. Tekrardan Arama kısmına Alta Bulunan Kodu Yazınız
Kod:
dwEffectInstanceIndex = 0xffffffff;
2.9. Bu Kod İle Değiştiriniz
Kod:
dwEffectInstanceIndex = 0;

Şimdi GameLib/Area.cpp: Giriş Yapalım ve Kodu Ekleyelim
Kod:
#include "../UserInterface/PythonApplication.h"
Kod:
void CArea::__UpdateLoadedObjectInstances(D3DXVECTOR3& v3Player) {     const float fMaxDist = GetMaxLoadingDistanceSqr();     const DWORD dwStartTime = ELTimer_GetMSec();     DWORD i = 0;     for (auto it = m_ObjectInstanceVector.begin(); it != m_ObjectInstanceVector.end(); ++it, ++i)     {         const TObjectData* c_pObjectData;         if (!GetObjectDataPointer(i, &c_pObjectData))             continue;         bool bDidModify = false;         const float fDist = (v3Player.x - c_pObjectData->Position.x) * (v3Player.x - c_pObjectData->Position.x)             + (v3Player.y - c_pObjectData->Position.y) * (v3Player.y - c_pObjectData->Position.y);         if (fMaxDist > fDist)         {             if ((*it) == nullptr)             {                 *it = ms_ObjectInstancePool.Alloc();                 (*it)->Clear();                 __SetObjectInstance(*it, c_pObjectData);                 // ĂÖŔűČżë                 if ((*it)->dwType == prt::PROPERTY_TYPE_BUILDING)                     m_GraphicThingInstanceCRCMap.emplace(TGraphicThingInstanceCRCMap::value_type((*it)->pThingInstance, c_pObjectData->dwCRC));                 Refresh(*it, false);                 bDidModify = true;             }         }         else         {             if ((*it) != nullptr)             {                 if ((*it)->dwType == prt::PROPERTY_TYPE_BUILDING)                     m_GraphicThingInstanceCRCMap.erase((*it)->pThingInstance);                 Refresh(*it, true);                 __Clear_DestroyObjectInstance(*it);                 *it = nullptr;                 bDidModify = true;             }         }         if (bDidModify)         {             const DWORD dwElapsed = ELTimer_GetMSec() - dwStartTime;             if (dwElapsed > 2)                 break;         }     } } void CArea::__UpdateEffectList(D3DXVECTOR3& v3Player) {     m_kVct_pkEftInstSort.clear();     const int iUpdateFPS = MAX(2, CPythonApplication::Instance().GetUpdateFPS());     const float fMaxDist = GetMaxLoadingDistanceSqr();     if (CEffectManager* pEffectManager = CEffectManager::InstancePtr())     {         // Effect         for (auto i = m_EffectInstanceMap.begin(); i != m_EffectInstanceMap.end();)         {             CEffectInstance* pEffectInstance = i->second;             const D3DMATRIX& gMatrix = pEffectInstance->GetGlobalMatrix();             const float fDist = (v3Player.x - gMatrix._41) * (v3Player.x - gMatrix._41) + (v3Player.y - gMatrix._42) * (v3Player.y - gMatrix._42);             const int iDistRatio = HermiteInterpolation(1, iUpdateFPS / 2, fDist / fMaxDist);             if (m_iUpdateCount % iDistRatio == 0)                 pEffectInstance->Update();             if (!pEffectInstance->isAlive())             {                 i = m_EffectInstanceMap.erase(i);                 pEffectManager->DestroyUnsafeEffectInstance(pEffectInstance);                 continue;             }             if (pEffectInstance->isShow())             {                 m_kVct_pkEftInstSort.emplace_back(pEffectInstance);             }             ++i;         }     }     ++m_iUpdateCount;     if (m_iUpdateCount > iUpdateFPS)         m_iUpdateCount = 0; } float CArea::GetMaxLoadingDistanceSqr() const {     int peNum;     float pfStart, pfEnd, pfFarClip;     CPythonBackground::instance().GetDistanceSetInfo(&peNum, &pfStart, &pfEnd, &pfFarClip);     return pfFarClip * pfFarClip; }

CArea::CArea Giriş Yapalım
Kod:
BU KODU m_wX = m_wY = 0xFF; BU KODU EKLEYELİM İÇİNE m_iUpdateCount = 0;

CArea::__SetObjectInstance_SetEffect Kodu Bulun ve Aşağıdaki Kod ile Değiştirelim.
Kod:
pObjectInstance->dwEffectInstanceIndex = m_EffectInstanceMap.size();
Kod:
pObjectInstance->dwEffectInstanceIndex = (DWORD)pEffectInstance;

CArea::__Clear_DestroyObjectInstance Kodunu Bulunuz Değiştiriniz
Kod:
if (pObjectInstance->dwEffectInstanceIndex!=0xffffffff) if (pObjectInstance->dwEffectInstanceIndex!=0) pObjectInstance->dwEffectInstanceIndex = 0xffffffff; pObjectInstance -> dwEffectInstanceIndex = 0 ;

CArea::Update Yükleme İşlevini Bulalım ve Değiştirelim
Kod:
void CArea::Update(D3DXVECTOR3& v3Player) {     __UpdateLoadedObjectInstances(v3Player);     __UpdateAniThingList();     __UpdateEffectList(v3Player); }

CArea::Refresh İşlevini Bulalım ve Değiştirelim
Kod:
void CArea::Refresh(TObjectInstance* pObjectInstance, bool bRemove) {     if (!pObjectInstance)         return;     if (prt::PROPERTY_TYPE_TREE == pObjectInstance->dwType)     {         if (pObjectInstance->pTree)         {             if (bRemove)             {                 auto it = std::find(m_TreeCloneInstaceVector.begin(), m_TreeCloneInstaceVector.end(), pObjectInstance->pTree);                 if (it != m_TreeCloneInstaceVector.end())                     m_TreeCloneInstaceVector.erase(it);             }             else             {                 m_TreeCloneInstaceVector.emplace_back(pObjectInstance->pTree);                 const float* pfPosition;                 pfPosition = pObjectInstance->pTree->GetPosition();                 pObjectInstance->pTree->UpdateBoundingSphere();                 pObjectInstance->pTree->UpdateCollisionData();             }         }     }     else if (prt::PROPERTY_TYPE_BUILDING == pObjectInstance->dwType)     {         if (bRemove)         {             auto it = std::find(m_ThingCloneInstaceVector.begin(), m_ThingCloneInstaceVector.end(), pObjectInstance->pThingInstance);             if (it != m_ThingCloneInstaceVector.end())                 m_ThingCloneInstaceVector.erase(it);             if (pObjectInstance->pThingInstance->IsMotionThing())             {                 auto it = std::find(m_AniThingCloneInstanceVector.begin(), m_AniThingCloneInstanceVector.end(), pObjectInstance->pThingInstance);                 if (it != m_AniThingCloneInstanceVector.end())                     m_AniThingCloneInstanceVector.erase(it);             }             if (pObjectInstance->isShadowFlag)             {                 auto it = std::find(m_ShadowThingCloneInstaceVector.begin(), m_ShadowThingCloneInstaceVector.end(), pObjectInstance->pThingInstance);                 if (it != m_ShadowThingCloneInstaceVector.end())                     m_ShadowThingCloneInstaceVector.erase(it);             }         }         else         {             pObjectInstance->pThingInstance->Update();             pObjectInstance->pThingInstance->Transform();             pObjectInstance->pThingInstance->Show();             pObjectInstance->pThingInstance->DeformAll();             m_ThingCloneInstaceVector.emplace_back(pObjectInstance->pThingInstance);             pObjectInstance->pThingInstance->BuildBoundingSphere();             pObjectInstance->pThingInstance->UpdateBoundingSphere();             if (pObjectInstance->pThingInstance->IsMotionThing())             {                 m_AniThingCloneInstanceVector.emplace_back(pObjectInstance->pThingInstance);                 pObjectInstance->pThingInstance->SetMotion(0);             }             if (pObjectInstance->isShadowFlag)             {                 m_ShadowThingCloneInstaceVector.emplace_back(pObjectInstance->pThingInstance);             }             if (pObjectInstance->pAttributeInstance)             {                 pObjectInstance->pThingInstance->UpdateCollisionData(&pObjectInstance->pAttributeInstance->GetObjectPointer()->GetCollisionDataVector());                 pObjectInstance->pAttributeInstance->RefreshObject(pObjectInstance->pThingInstance->GetTransform());                 pObjectInstance->pThingInstance->UpdateHeightInstance(pObjectInstance->pAttributeInstance);             }         }     }     else if (prt::PROPERTY_TYPE_EFFECT == pObjectInstance->dwType)     {     }     else if (prt::PROPERTY_TYPE_AMBIENCE == pObjectInstance->dwType)     {         if (bRemove)         {             auto it = std::find(m_AmbienceCloneInstanceVector.begin(), m_AmbienceCloneInstanceVector.end(), pObjectInstance->pAmbienceInstance);             if (it != m_AmbienceCloneInstanceVector.end())                 m_AmbienceCloneInstanceVector.erase(it);         }         else         {             m_AmbienceCloneInstanceVector.emplace_back(pObjectInstance->pAmbienceInstance);         }     }     else if (prt::PROPERTY_TYPE_DUNGEON_BLOCK == pObjectInstance->dwType)     {         if (bRemove)         {             auto it = std::find(m_DungeonBlockCloneInstanceVector.begin(), m_DungeonBlockCloneInstanceVector.end(), pObjectInstance->pDungeonBlock);             if (it != m_DungeonBlockCloneInstanceVector.end())                 m_DungeonBlockCloneInstanceVector.erase(it);         }         else         {             pObjectInstance->pDungeonBlock->Update();             pObjectInstance->pDungeonBlock->Deform();             pObjectInstance->pDungeonBlock->UpdateBoundingSphere();             m_DungeonBlockCloneInstanceVector.emplace_back(pObjectInstance->pDungeonBlock);             if (pObjectInstance->pAttributeInstance)             {                 pObjectInstance->pDungeonBlock->UpdateCollisionData(&pObjectInstance->pAttributeInstance->GetObjectPointer()->GetCollisionDataVector());                 pObjectInstance->pAttributeInstance->RefreshObject(pObjectInstance->pDungeonBlock->GetTransform());                 pObjectInstance->pDungeonBlock->UpdateHeightInstance(pObjectInstance->pAttributeInstance);             }         }     } }
CArea::__Load_BuildObjectInstances Bulalım ve Değiştirelim
Kod:
void CArea::__Load_BuildObjectInstances() {     m_ObjectInstanceVector.clear();     m_ObjectInstanceVector.resize(GetObjectDataCount(), nullptr);     m_GraphicThingInstanceCRCMap.clear();      std::sort(m_ObjectDataVector.begin(), m_ObjectDataVector.end(), ObjectDataComp()); }

CArea::GetObjectInstancePointer Arayıp Sonucu Aşağıdaki Kod İle Değiştirelim
Kod:
const bool CArea::GetObjectInstancePointer(const DWORD & dwIndex, const TObjectInstance ** ppObjectInstance) const {     if (dwIndex >= m_ObjectInstanceVector.size())         return false;     *ppObjectInstance = m_ObjectInstanceVector[dwIndex];     return (*ppObjectInstance) != nullptr; }

:2gamer:BİLİYORUM SIKILDINIZ DURMADAN KOD EKLEMEKTEN AMA SABREDİN ÇOK AZ KALDI:) HERŞEY SİZ VE OYUNCULARINIZ İÇİN :cheer2:

CArea::RenderEffect Bulalım ve Değiştirelim
Kod:
void CArea::RenderEffect() {     // Effect     STATEMANAGER.SetTexture(0, NULL);     STATEMANAGER.SetTexture(1, NULL);     std::sort(m_kVct_pkEftInstSort.begin(), m_kVct_pkEftInstSort.end(), CArea_LessEffectInstancePtrRenderOrder());     std::for_each(m_kVct_pkEftInstSort.begin(), m_kVct_pkEftInstSort.end(), CArea_FEffectInstanceRender()); }

CArea::RefreshPortal Giriş Yapalım ve Altaki Kodları Ekleyiniz Sırayla
Kod:
TObjectInstance * pInstance = m_ObjectInstanceVector[i];
Kod:
if (!pInstance)             continue;
Kod:
TObjectInstance * pObjectInstance = *it;
Kod:
if (!pObjectInstance)             continue;

CArea::Clear function Buluyoruz Tekrar ve Değiştiriyoruz
Kod:
for (it = m_ObjectInstanceVector.begin();it!=m_ObjectInstanceVector.end();++it)         __Clear_DestroyObjectInstance(*it);
Kod:
for (it = m_ObjectInstanceVector.begin(); it != m_ObjectInstanceVector.end(); ++it)     {         if ((*it) != nullptr)             __Clear_DestroyObjectInstance(*it);     }
GameLib/MapOutdoor.h Giriş Yapın ve 1 Kodu Bulalım ardından silip 2 ci Kodu Ekleyelim
Kod:
void            __UpdateAroundAreaList();
Kod:
void            __UpdateAroundAreaList(D3DXVECTOR3& v3Player);
GameLib/MapOutdoorUpdate.cpp Giriş Yapalım CMapOutdoor::__Game_UpdateArea Bulalım ve Kaldıralım
1 KALDIRILACAK :
Kod:
__UpdateAroundAreaList
2 EKLENECEK :
Kod:
__UpdateAroundAreaList(v3Player);
3 SONUÇ :
Kod:
__CollectShadowReceiver(v3Player, v3Light);
1659609107007-png.82694

Son Olarak CMapOutdoor::__UpdateAroundAreaList Bulun ve Altaki Kod İle Değiştirelim
Kod:
void CMapOutdoor::__UpdateAroundAreaList(D3DXVECTOR3& v3Player) { #ifdef __PERFORMANCE_CHECKER__     DWORD ft1=timeGetTime(); #endif     DWORD at[AROUND_AREA_NUM];     for (int i = 0; i < AROUND_AREA_NUM; ++i)     {         DWORD t1=timeGetTime();         CArea * pArea;         if (GetAreaPointer(i, &pArea))             pArea->Update(v3Player);         DWORD t2=timeGetTime();         at[i]=t2-t1;     } #ifdef __PERFORMANCE_CHECKER__     DWORD ft2=timeGetTime();     if (ft2-ft1>5)     {         for (int i=0; i<AROUND_AREA_NUM; ++i)             Tracef("Area %d %d\n", i, at[i]);     } #endif }

İyi ForumlarDilerim.
Görüş Mesafesi Sistemi Nedir?

Metin2 özel sunucularında oyun deneyimini artırmak ve stratejik derinlik kazandırmak için geliştirilen sistemlerden biri de Görüş Mesafesi Sistemi'dir. Bu sistem, oyuncuların harita üzerinde belirli bir mesafeden fazla ileriyi görememesini sağlar. Özellikle PvP odaklı sunucularda, bu sistem sayesinde savaş stratejileri daha karmaşık hale gelir ve taktiksel avantajlar doğar. Bu yazıda, Metin2Lobby üzerinden detaylandıracağımız bu sistem, nasıl çalışır, nasıl geliştirilir ve neden önemlidir konularını ele alacağız.

Görüş Mesafesi Sisteminin Temelleri

Görüş Mesafesi Sistemi, oyuncunun karakterinin belli bir alan dışına çıkması durumunda, bu alanı render edilmeyen bir hale getirerek gizlenmesini sağlar. Bu, hem performans hem de strateji açısından büyük faydalar sağlar. Özellikle C++ tabanlı server src üzerinde geliştirilen bu sistemler, game core seviyesinde müdahaleyi gerektirir. Bu sistemlerde genellikle client src tarafında da bazı düzenlemeler yapılır.

Neden Görüş Mesafesi Sistemine İhtiyaç Vardır?

Metin2 gibi açık alan PvP oyunlarında, tüm haritayı serbestçe görebilmek bazı oyuncular için avantaj sağlayabilir. Bu da adil bir oyun ortamı oluşturmada sorun yaratır. Ayrıca, tüm haritanın aynı anda render edilmesi performansı düşürür. Görüş Mesafesi Sistemi ile bu sorunların önüne geçilir. Bu sistem, Martysama veya diğer source edit projeleri ile entegre edilebilir. Geliştiriciler, uiscript veya py gui ile kullanıcı arayüzüne bu özelliği entegre edebilir.

C++ ve Python ile Uygulama Yöntemleri

Görüş Mesafesi sistemi, genellikle C++ dilinde game server programming sırasında geliştirilir. Game ve auth katmanları arasında haberleşmeler sağlanarak, oyuncunun bulunduğu konuma göre render edilecek alan belirlenir. Python tarafında ise, py root üzerindeki modüllerle bu veriler kontrol edilir. Py GUI ile geliştirilen arayüzlerle kullanıcıya bu mesafe ayarı kolayca sunulabilir. DB core üzerinden oyuncu bazlı görüş mesafesi ayarları da saklanabilir.

Sistem Performans ve Geliştirme Zorlukları

Görüş Mesafesi Sistemi geliştirilirken dikkat edilmesi gereken bazı teknik zorluklar vardır. Öncelikle, client ve server senkronizasyonu sağlanmalıdır. Yanlış yapılandırılmış bir sistem, lag veya desync gibi durumlara yol açabilir. Metin2 compile işlemi sırasında bu sistemlerin doğru şekilde entegre edilmesi önemlidir. Core yapılar bozulmadan, sadece ilgili fonksiyonlar üzerinde değişiklik yapılmalıdır. Geliştiriciler, pack dosyalarına da bu sistemi entegre edebilir.

Metin2 Private Server Geliştirme Sürecinde Yeri

Metin2 özel sunucu geliştirme sürecinde, PvP sistem tasarımı büyük önem taşır. Görüş Mesafesi Sistemi, bu süreçte stratejik bir avantaj sunar. Oyuncular, kritik anlarda bu sistemi kullanarak rakip takımları şaşırtabilir. Channel bazlı sunucularda farklı mesafe ayarları da yapılabilir. Bu sayede her kanalda farklı oyun deneyimi sunulabilir. Metin2 development projelerinde bu sistem sıkça tercih edilir. Metin2Dev toplulukları da bu konuda aktif rol oynar.

Sonuç

Görüş Mesafesi Sistemi, Metin2 özel sunucularında stratejik oyun deneyimini artırmanın etkili yollarından biridir. C++ ve Python dillerinde geliştirilebilen bu sistem, hem performans hem de oyun mekaniği açısından büyük faydalar sağlar. Metin2Lobby olarak, bu gibi gelişmiş sistemlerin source kodlarını ve geliştirme süreçlerini paylaşmaya devam edeceğiz.


What is the View Range System?

One of the systems developed to enhance gameplay experience and add strategic depth in Metin2 private servers is the View Range System. This system prevents players from seeing beyond a certain distance on the map. Especially in PvP-focused servers, this system makes combat strategies more complex and creates tactical advantages. In this article, we will explain how this system works, how it can be developed, and why it's important, detailed through Metin2Lobby.

Basics of the View Range System

The View Range System hides areas beyond a specific range around the player's character by preventing them from being rendered. This provides significant benefits both in terms of performance and strategy. This system, typically developed on C++-based server src, requires modifications at the game core level. Certain adjustments may also be made on the client src side for these systems.

Why Is the View Range System Needed?

In open-world PvP games like Metin2, having unrestricted view of the entire map can provide unfair advantages to some players, which disrupts fair play. Moreover, rendering the whole map at once reduces performance. The View Range System addresses these issues. It can be integrated into projects such as Martysama or other source edit efforts. Developers can integrate this feature into user interfaces via uiscript or py gui.

Implementation Methods with C++ and Python

The View Range System is generally developed using C++ during game server programming. Communications between the game and auth layers determine the area to be rendered based on the player's location. On the Python side, modules under py root can be used to control these values. User interfaces built with Py GUI can easily present these view range settings to users. Player-based view range settings can also be stored via the DB core.

System Performance and Development Challenges

There are several technical challenges to consider when developing the View Range System. First, synchronization between client and server must be maintained. Incorrectly configured systems can lead to lag or desync issues. Correct integration of these systems during the Metin2 compile process is essential. Changes should only occur within relevant functions without disrupting core structures. Developers can also integrate this system into pack files.

Its Place in Metin2 Private Server Development

In the Metin2 private server development process, PvP system design holds great importance. The View Range System offers strategic advantages during this process. Players can use this system at critical moments to surprise enemy teams. Different view range settings can be applied per channel in channel-based servers, allowing different gameplay experiences per channel. This system is frequently preferred in Metin2 development projects. Metin2Dev communities also play an active role in this regard.

Conclusion

The View Range System is one of the effective ways to increase strategic gameplay in Metin2 private servers. Implemented in C++ and Python, this system provides significant benefits in terms of both performance and game mechanics. At Metin2Lobby, we will continue sharing source codes and development processes for such advanced systems.​
 

Şuan Bu Konuyu Görüntüleyen Kullanıcılar (Toplam : 0, Üye : 0, Misafir : 0)

Benzer konular

Geri
Üst Alt