[1453 ~ 20xx] %100 NPC & MONSTER HAREKET HIZLARI FİXLEME(ICE&LIGHT). YENİ FONKSİYON | ROK Projects

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

Admin

Knight Lobby
Yönetici
Founder
Katılım
6 Mayıs 2022
Mesajlar
45,967
Merhabalar,



Aranızda ROK Projesini bilenler vardır. Yaratık & npc hızlarını ve yapay zekasını bu proje için geliştirmiştik. ICE ve lighting işlemeleri, sorunsuz takip sistemi vs.. sizlerle paylaşıyorum. %100 ÇÖZÜMDÜR.!

[HIDE-REPLY]

Öncelikle AI Server içerisinde, Npc.h eklemeniz gerekenler;



Kod:
void NpcCalling(float fDis,float fDistance, __Vector3 oPos, __Vector3 cPost);



Unit.h eklemeniz gereken;

Kod:
uint8   m_bSpeedAmount;



Unit.cpp Initialize() içerisinde varsayılan olarak 100 değeri vermeyi unutmayın.

Kod:
m_bSpeedAmount = 100;



AI > Npc.cpp içerisindeki IsNoPathFind fonksiyonunu bununla değişin;

Kod:
void CNpc::IsNoPathFind(float fDistance){     ClearPathFindData();     m_bPathFlag = true;     int nX = 0, nZ = 0;     __Vector3 vStart, vEnd, vDis, vOldDis;     float fDis = 0.0f;     vStart.Set(m_fStartPoint_X, 0, m_fStartPoint_Y);     vEnd.Set(m_fEndPoint_X, 0, m_fEndPoint_Y);     vDis.Set(m_fStartPoint_X, 0, m_fStartPoint_Y);     int count = 0;     int nError = 0;     fDis = GetDistance(vStart, vEnd);     if (fDis > NPC_MAX_MOVE_RANGE) {         ClearPathFindData();         TRACE("#### Npc-IsNoPathFind Fail : NPC_MAX_MOVE_RANGE overflow  .. [nid = %d, name=%s], cur_x=%.2f, z=%.2f, dest_x=%.2f, dest_z=%.2f, fDis=%.2f#####\n",             GetID(), GetName().c_str(), m_fStartPoint_X, m_fStartPoint_Y, m_fEndPoint_X, m_fEndPoint_Y, fDis);         return;     }     if (GetMap() == nullptr)     {         ClearPathFindData();         TRACE("#### Npc-IsNoPathFind No map : [nid=%d, name=%s], zone=%d #####\n", GetID(), GetName().c_str(), GetZoneID());         return;     }     MAP* pMap = GetMap();     vOldDis.Set(vDis.x, 0, vDis.z);     fDis = GetDistance(vOldDis, vEnd);     if (count < 0 || count >= MAX_PATH_LINE) {         count = 0;     }      GetVectorPosition(vDis, vEnd, fDistance, &vDis);     NpcCalling(fDis,fDistance, vOldDis, vDis);           if (count <= 0 || count >= MAX_PATH_LINE) {         ClearPathFindData();         TRACE("#### IsNoPtahfind Fail : nid=%d,%s, count=%d ####\n", GetID(), GetName().c_str(), count);         return;     }     m_iAniFrameIndex = count; }



Eksik fonksiyonumuz bunu da altına ekleyin;

Kod:
void CNpc::NpcCalling(float fDis,float fDistance, __Vector3 oPos, __Vector3 cPost){       float bChamber = TILE_SIZE + 3;     if (m_bSpeedAmount > 0 && m_bSpeedAmount < 100) {         float pTile = (float)(10 - (m_bSpeedAmount / 10) - TILE_SIZE);         bChamber -= (pTile >= 1 ? pTile + 2 : 0);     }     else if (m_bSpeedAmount > 100) {         float pTile = (float)(10 - (m_bSpeedAmount / 10) - TILE_SIZE);         bChamber += (pTile >= 1 ? pTile + 2 : 0);      }           bChamber = fDis / bChamber;      if (bChamber > 15)bChamber = 15;            m_curx = (cPost.x / bChamber) + oPos.x;     m_curz = (cPost.z / bChamber) + oPos.z;     float tempSpeed = m_fSecForRealMoveMetor;     if (tempSpeed == 0)         tempSpeed = m_fSpeed_1;     float nMoveSpeed = (float)(tempSpeed / ((float)m_sSpeed / 1000));           if (nMoveSpeed != 0) {          SendMoveResult(m_curx, m_fPrevY, m_curz, (float)(nMoveSpeed));     } }



Hareket hızlarımız yazılımsal olarak düzelmiştir. Şimdide takip olayındaki hataları fixleyelim.



Yine Npc.cpp içindeki NpcTracing fonksiyonunda aşağıdaki return değerlerini güncelleyin.



Kod:
if (isNonAttackingObject())    {         InitTarget();         m_NpcState = NPC_STANDING;         return 0;     }

Kod:
if (m_byMoveType == 4)    {         m_NpcState = NPC_FIGHTING;         return 0;     }

Kod:
if (result == CloseTargetInGeneralRange)    {         NpcMoveEnd();         m_NpcState = NPC_FIGHTING;         return 0;     }     else if (result == CloseTargetInvalid)     {         InitTarget();         NpcMoveEnd();         m_NpcState = NPC_STANDING;         return 0;     }     else if (result == CloseTargetInAttackRange && GetProto()->m_byDirectAttack == 2)     {         NpcMoveEnd();         m_NpcState = NPC_FIGHTING;         return 0;     }

Kod:
if (m_bStopFollowingTarget)    {         if (!ResetPath())// && !m_tNpcTraceType)         {              InitTarget();             NpcMoveEnd();              m_NpcState = NPC_STANDING;             return 0;         }     }

Kod:
if (  (!m_bPathFlag && !StepMove())        || (m_bPathFlag && !StepNoPathMove()))     {         m_NpcState = NPC_STANDING;          return 0;     }

Fonksiyonun en son ki return değeri ;

Kod:
return m_sSpeed;



Yine aynı şekilde NpcAttacking fonksiyonun return değerleri aşağıdaki gibi olmalı;

Kod:
if (isNonAttackingObject())    {         m_NpcState = NPC_STANDING;         return 0;     }

Kod:
if (result == CloseTargetInGeneralRange)    {         m_NpcState = NPC_FIGHTING;         return m_sAttackDelay;     }

Kod:
int nValue = GetTargetPath();    if (nValue == -1)     {         if (!RandomMove())         {             InitTarget();             m_NpcState = NPC_STANDING;             return m_sStandTime;         }         InitTarget();         m_NpcState = NPC_MOVING;         return 0;     }     else if (nValue == 0)     {         m_fSecForMetor = m_fSpeed_2;         IsNoPathFind(m_fSecForMetor);     }     m_NpcState = NPC_TRACING;     return m_sStandTime;



Sıradaki fonksiyon : NpcMoving aynı işlemi uygulayın;

Kod:
NpcMoveEnd();            m_NpcState = NPC_ATTACKING;             return 0;

Kod:
if (IsMovingEnd())    {         m_curx = m_fPrevX;                 m_curz = m_fPrevZ;          if (GetX() < 0 || GetZ() < 0)                 TRACE("Npc-NpcMoving-2 : nid=(%d, %s), x=%.2f, z=%.2f\n", GetID(), GetName().c_str(), GetX(), GetZ());           m_NpcState = NPC_STANDING;         return m_sStandTime;     }

Kod:
if (  (!m_bPathFlag && !StepMove())        || (m_bPathFlag && !StepNoPathMove()))     {         m_NpcState = NPC_STANDING;         return 0;     }     SendMoveResult(m_fPrevX, m_fPrevY, m_fPrevZ, (float)((m_fSecForRealMoveMetor) / ((double)m_sSpeed / 1000)));     return m_fSpeed_1;



Sıradaki fonksiyon, NpcStanding aynı işlemi uygulayın;

Kod:
if (pRoom != nullptr         && pRoom->m_byStatus == 1)     {         m_NpcState = NPC_STANDING;         return m_sStandTime;     }

Kod:
if (RandomMove())    {         m_iAniFrameCount = 0;         m_NpcState = NPC_MOVING;         return m_sStandTime;     }

Fonksiyonun en sonki return değeri;

Kod:
return m_sStandTime;



Sıradaki fonksiyon, Attack() aynı işlemi uygulayın; direk tüm fonksiyonu veriyorum. sizdekiyle return değerlerini güncelleyin yeter.

Kod:
try {        if (isDead())             return -1;         int nRandom = 0, nPercent = 1000;         bool bTeleport = false;         if (isNonAttackingObject())         {             m_NpcState = NPC_STANDING;             InitTarget();             return 0;         }         if (GetProto()->m_byDirectAttack == 1)             return LongAndMagicAttack();         int nStandingTime = m_sStandTime;         auto result = IsCloseTarget(m_byAttackRange, AttackTypeMagic);         if (result == CloseTargetNotInRange)         {             m_sStepCount = 0;             m_byActionFlag = ATTACK_TO_TRACE;             m_NpcState = NPC_TRACING;             return m_sAttackDelay;         }         else if (result == CloseTargetInAttackRange)         {             if (GetProto()->m_byDirectAttack == 2)                 return LongAndMagicAttack();             m_sStepCount = 0;             m_byActionFlag = ATTACK_TO_TRACE;             m_NpcState = NPC_TRACING;             return m_sAttackDelay;         }         else if (result == CloseTargetInvalid)         {             m_NpcState = NPC_STANDING;             InitTarget();             return 0;         }         int        nDamage = 0;         uint16 nID = m_Target.id;                    // Target ì„ êµ¬í•œë‹¤.         // Targeting player         if (nID < NPC_BAND)         {             CUser * pUser = g_pMain->GetUserPtr(nID);             if (pUser == nullptr                 || pUser->isDead()                 || pUser->m_bInvisibilityType)             {                 InitTarget();                 m_NpcState = NPC_STANDING;                 return 0;             }             // Don't attack GMs.             if (pUser->isGM())             {                 InitTarget();                 m_NpcState = NPC_MOVING;                 return 0;             }             if (GetProto()->m_byMagicAttack == 4 || GetProto()->m_byMagicAttack == 5)             {                 nRandom = myrand(1, 10000);                 if (nRandom < nPercent)                 {                     CNpcMagicProcess::MagicPacket(MAGIC_EFFECTING, m_proto->m_iMagic1, GetID(), -1, int16(pUser->GetX()), int16(pUser->GetY()), int16(pUser->GetZ()));                     //printf("AreaMagicAttack --- sid=%d, magicid=%d, name=%s\n", GetID(), m_proto->m_iMagic1, m_proto->m_strName.c_str());                     return m_sAttackDelay + 1000;                 }             }             else if (GetProto()->m_byMagicAttack == 2)             {                 nRandom = myrand(1, 10000);                 if (nRandom < nPercent)                 {                     CNpcMagicProcess::MagicPacket(MAGIC_EFFECTING, m_proto->m_iMagic1, GetID(), pUser->GetID());                     //    printf("LongAndMagicAttack --- sid=%d, tid=%d, magicid=%d, name=%s\n", GetID(), pUser->GetID(), m_proto->m_iMagic1, m_proto->m_strName.c_str());                     return m_sAttackDelay;                 }             }             SendAttackRequest(pUser->GetID());         }         else // Targeting NPC         {             CNpc * pNpc = g_pMain->GetNpcPtr(nID);             if (pNpc == nullptr                 || pNpc->isDead())             {                 InitTarget();                 m_NpcState = NPC_STANDING;                 return 0;             }             if (isHealer()                 && !isHostileTo(pNpc))             {                 m_NpcState = NPC_HEALING;                 return 0;             }             SendAttackRequest(pNpc->GetID());         }         return m_sAttackDelay;     }     catch (...) {         GlobalError(__FILE__, __LINE__);         return 0;     } }



Bunlarıda uyguladıktan sonra tıpki 1299 daki gibi hareket olayları çalışacaktır. Slot bozulamaları, donmaları vs durumlar ortadan kalkıyor.



Veritabanı kısmında yapacağınız işlem ise hız ve range olaylarını ayarlamak.

AttackRange : 2 - 5 arası olmalı. yaratığa göre ayarlamalısınız.

TrackingRange: 45 civarı

m_speed : 1300-1600 civarı ayarlarsanız sorun çıkmayacaktır. Bu değerleri sizlere vermiyorum. Kendiniz ayarlayın.



Yapmanız gereken son bir şey ise m_bSpeedAmount değeri Ai server de tutulmamakta. Bu yüzden aisocket aracılığı ile gameserver den m_bSpeedAmount bilgisini ai servere göndermeniz gerekiyor. Yoksa ice & lighting işlemi gerçekleşmez. Bu fonksiyonuda size bırakıyorum. 95% kısmını paylaşmış oldum. Gerisini getirirsiniz.

[/HIDE-REPLY]



İyi çalışmalar...
Rok Projects Tarafından Sunulan [1453 ~ 20xx] NPC & Monster Hareket Hızları Fixleme Modülü
Knight Online özel sunucularında geliştirme yapan geliştiriciler için önemli bir yenilikten bahsetmek istiyoruz. ROK Projects tarafından hazırlanan bu modül, NPC ve Monster hareket hızlarının sabitlenmesini sağlar. Bu sayede oyun içi deneyim daha stabil hale gelir ve sunucu yöneticileri oyun dengelerini daha iyi kontrol edebilirler.

Hareket Hızı Sorunu Nedir?
Knight Online özel sunucularında bazı NPC'ler veya canavarlar zaman zaman beklenmedik şekilde çok hızlı ya da çok yavaş hareket edebiliyor. Bu durum hem oyun deneyimini olumsuz etkiliyor hem de sunucu dengesi üzerinde ciddi etkilere neden olabiliyor. Özellikle bazı özel haritalarda ya da savaş alanlarında bu sorun daha belirgin hale geliyor.

Fixleme Modülünün Özellikleri
ROK Projects’in sunduğu bu modül, hem eski hem de yeni nesil Knight Online sunucularında çalışmaktadır. Modülün adından da anlaşılacağı gibi, 1453 ile başlayıp 20xx sürümlerine kadar geniş bir destek yelpazesi sunar. Modül, NPC ve Monster hareket hızlarını standartlaştırarak oyun içi tutarlılığı artırır.

Nasıl Kurulur?
Modül, kolay entegrasyon sunar. Sadece belirtilen dosyalara küçük değişiklikler yapılarak sistem aktif hale getirilebilir. Geliştiriciler için gerekli tüm açıklamalar ve örnek kodlar paketle birlikte sağlanmaktadır. Bu sayede опыт geliştirici olmayanlar bile modülü kolayca entegre edebilir.

Dikkat Edilmesi Gerekenler
Modülün doğru çalışması için sunucu sürümüne uygun olması önemlidir. Yanlış sürüm kullanıldığında hata oluşabilir. Ayrıca, bazı özel NPC'ler için özel ayarlamalar gerekebilir. Bu nedenle test ortamında denemek her zaman önerilir.

Sunucu Performansı Üzerinde Etkisi[/ColorBrush]Bu fixleme modülü, sunucu performansını artırmakta doğrudan etkilidir. Hareket hızları sabitlendiğinde CPU yükü azalır ve sunucu daha verimli çalışır. Özellikle yoğun oyun alanlarında bu fark net olarak hissedilir.

ROK Projects ve Knight Lobby
ROK Projects, Knight Online özel sunucuları için sürekli yenilikler sunan öncü bir geliştirici grubudur. Knight Lobby ise bu alanda aktif bir topluluk platformudur. Knight Lobby üzerinden birçok kaynak, modül ve destek bulunabilir. Geliştiriciler ve oyuncular için değerli bir platformdur.

Sonuç
NPC ve Monster hareket hızları fixleme modülü, Knight Online özel sunucularında oyun dengesini ve kullanıcı deneyimini artırmak için oldukça faydalıdır. Geliştiricilerin bu modülü kullanarak daha profesyonel ve stabil sunucular oluşturabileceği açıktır.


ROK Projects Presents: [1453 ~ 20xx] NPC & Monster Movement Speed Fix Module
An important update for developers working on Knight Online private servers is here. The module provided by ROK Projects fixes the movement speeds of NPCs and monsters, making the in-game experience more stable and allowing server administrators better control over game balance.

What is the Movement Speed Issue?
In Knight Online private servers, certain NPCs or monsters sometimes move unexpectedly fast or slow. This issue negatively impacts gameplay and can cause serious imbalances on the server. This problem becomes especially noticeable in specific maps or battlefields.

Features of the Fix Module
The module provided by ROK Projects works on both older and newer generations of Knight Online servers. As implied by its name, it offers wide version support from 1453 to 20xx. It standardizes NPC and monster movement speeds, increasing consistency within the game.

How to Install?
The module provides easy integration. By making small modifications to specified files, the system can be activated. All necessary instructions and sample codes are included with the package, enabling even less experienced developers to integrate the module easily.

Important Considerations
It is crucial that the correct server version is used for the module to work properly. Incorrect versions may cause errors. Additionally, special adjustments might be needed for certain NPCs. Therefore, testing in a controlled environment is always recommended.

Impact on Server Performance
This fix module directly improves server performance. When movement speeds are fixed, CPU load decreases, and the server runs more efficiently. This difference is clearly noticeable in heavily populated game areas.

ROK Projects and Knight Lobby
ROK Projects is a leading developer group providing continuous updates for Knight Online private servers. Knight Lobby serves as an active community platform in this field. Many resources, modules, and support options can be found via Knight Lobby. It is a valuable platform for both developers and players.

Conclusion
The NPC and Monster movement speed fix module is highly beneficial for improving game balance and user experience in Knight Online private servers. It is clear that developers can use this module to create more professional and stable servers.
 

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

Geri
Üst Alt