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

E Çevrimdışı

emonko

Kayıtlı Üye
16 Mart 2012
60
0
6
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.!

***Hidden content cannot be quoted.***



İyi çalışmalar...
++++++++++++++++++++++++++++++++++
 
L Çevrimdışı

Lessany_17

Kayıtlı Üye
5 Ocak 2023
96
0
6
28
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...
ha bir şeyide tam paylaşın hani başlıkta %100 çözümdü bir halta yaramıyor
 
Üst