Çift El Silahlar İçin Ymir Aldatmacasını İyileştirme (Saldırı Hızı)

  • Konuyu açan Konuyu açan Kaiser
  • Açılış Tarihi Açılış Tarihi
  • Yanıt Yanıt 6
  • Gösterim Gösterim 313

Kaiser

Adͥᴍiͣnͫ
Admin
Süper Üye
Geliştirici
Yardımsever Üye
Mesaj
4.630
Çözümler
456
Beğeni
5.713
Puan
5.349
Ticaret Puanı
0
Merhabalar, hastalık sebebiyle bir süredir pek aktif değildim. Hala değilim aslında, pek bir şey yaptığım söylenemez. Kodlara göz gezdiriyorum genellikle.
Bugün fark ettiğim, aslında mantığa uygun fakat eksik ve yanıltıcı bulduğum bir ymir yamasını iyileştirmeyi paylaşmak istedim.

Konumuz şu;
constInfo.py içinde şöyle bir tanım var;
Python:
Genişlet Daralt Kopyala
TWO_HANDED_WEAPON_ATT_SPEED_DECREASE_VALUE = 10
Bunu ilk gördüğümde de amacını merak etmiştim ama üstüne düşmemiştim, anlamak bugüne kısmetmiş.

Bu değerin amacı şu, karakter çift el silah taktığında hem silahın üzerine gelindiğinde, hem de C ekranında yazan saldırı değerini gerçeği yansıtmayacak şekilde -10 olarak düşürüyor. Mesela Yarı İnsan Kılıç +9'un varsayılan saldırı hızı(proto değeri) 25 iken, üzerine gelindiğinde 15 yazıyor ve C ekranında da saldırı hızı kısmı toplam gerçek değerden -10 olarak görünüyor; yani örneğin saldırı hızı 100 yazması gerekiyorsa 90 görünüyor. Bunu yapmalarındaki amaç ise büyük ihtimalle çift el kılıç ile normal kılıçların saldırı animasyonlarının arasındaki hız farkıdır. Biliyorsunuz, normal kılıçlar doğal olarak daha seri ve hızlı sallanıyor ama çift el onun yanında animasyon/hız olarak hantal kalıyor. Bu nedenle böyle bir şey yapmışlar.

Bunu komple kaldırmak yerine sade ve anlaşılır olması açısından c++ tarafına sabitledim ve gereksiz kodları sildim . Çünkü kaldırılması durumunda daha saçma senaryolar ortaya çıkacaktır.

Kısaca anlatıma geçeyim;
game.py bulun ve silin:
Python:
Genişlet Daralt Kopyala
# TWO_HANDED_WEAPON_ATTACK_SPEED_UP
constInfo.SET_TWO_HANDED_WEAPON_ATT_SPEED_DECREASE_VALUE()
# END_OF_TWO_HANDED_WEAPON_ATTACK_SPEED_UP

constInfo.py aşağıdaki bulun ve silin:
Python:
Genişlet Daralt Kopyala
def SET_TWO_HANDED_WEAPON_ATT_SPEED_DECREASE_VALUE():
    global TWO_HANDED_WEAPON_ATT_SPEED_DECREASE_VALUE
    app.SetTwoHandedWeaponAttSpeedDecreaseValue(TWO_HANDED_WEAPON_ATT_SPEED_DECREASE_VALUE)
Python:
Genişlet Daralt Kopyala
TWO_HANDED_WEAPON_ATT_SPEED_DECREASE_VALUE # 2 tane olabilir

PythonApplicationModule.cpp en üstlerde bulun:
C++:
Genişlet Daralt Kopyala
extern int TWOHANDED_WEWAPON_ATT_SPEED_DECREASE_VALUE = 0;
Buradaki 0'ı 10 yapın.

Aynı dosyada bulun:
C++:
Genişlet Daralt Kopyala
[...]
PyModule_AddIntConstant(poModule, "INFO_ITEM",        CPythonApplication::INFO_ITEM);
PyModule_AddIntConstant(poModule, "INFO_ACTOR",        CPythonApplication::INFO_ACTOR);
PyModule_AddIntConstant(poModule, "INFO_EFFECT",    CPythonApplication::INFO_EFFECT);
PyModule_AddIntConstant(poModule, "INFO_TEXTTAIL",    CPythonApplication::INFO_TEXTTAIL);
[...]
Bu kısımlara herhangi bir yere ekleyin(yine de bulunsun):
C++:
Genişlet Daralt Kopyala
PyModule_AddIntConstant(poModule, "TWOHANDED_WEWAPON_ATT_SPEED_DECREASE_VALUE", TWOHANDED_WEWAPON_ATT_SPEED_DECREASE_VALUE);

Yine aynı dosyada şu ikisini bulun ve silin:
C++:
Genişlet Daralt Kopyala
PyObject* SetTwoHandedWeaponAttSpeedDecreaseValue(PyObject* poSelf, PyObject* poArgs)
{
    int iValue;
    if (!PyTuple_GetInteger(poArgs, 0, &iValue))
        return Py_BuildException();

    TWOHANDED_WEWAPON_ATT_SPEED_DECREASE_VALUE = iValue;

    return Py_BuildNone();
}
C++:
Genişlet Daralt Kopyala
{ "SetTwoHandedWeaponAttSpeedDecreaseValue", SetTwoHandedWeaponAttSpeedDecreaseValue, METH_VARARGS },

uiCharacter.py içinden bulun:
Python:
Genişlet Daralt Kopyala
self.GetChild("ASPD_Value").SetText(str(player.GetStatus(player.ATT_SPEED)))
Değiştirin:
Python:
Genişlet Daralt Kopyala
attSpeed = player.GetStatus(player.ATT_SPEED)
self.GetChild("ASPD_Value").SetText(self.__GetAttackSpeed(attSpeed))

Aynı dosyada def RefreshStatus(self): fonksiyonunun üzerine ekleyin:
Python:
Genişlet Daralt Kopyala
    def __GetAttackSpeed(self, speed):
        import item

        weaponIndex = player.GetItemIndex(item.EQUIPMENT_WEAPON)
        if weaponIndex != 0:
            item.SelectItem(weaponIndex)
            if item.GetItemType() == item.ITEM_TYPE_WEAPON and item.GetItemSubType() == item.WEAPON_TWO_HANDED:
                return "~%d" % speed

        return "%d" % speed

Sonuç:


Bu haliyle en azından çift el silah takıldığında saldırı değeri başına ~ işareti koyularak oyuncuya (değişkenlik gösterebilir...) mesajı verilmesi amaçlanır.
Orjinal halinde durum biraz daha mantığa aykırı oluyor. Mesela dolunay kılıcında da saldırı hızı +15 yazıyor, yarı insan kılıcında da +15 yazıyor. Ama çiftel hantal kaldığından "ulan bu nasıl +15?" (gibi gibi..) algıların önüne geçilebilir.
 
Öncelikle geçmiş olsun değerli gardeşim hasta olmana rağmen vaktini ayırdığın için bizzat teşekkür ederim. Konu hakkındaki fikirlerimi ve naçizane çözüm yöntemimi sunmak isterim.

Bildiğiniz üzere oyunda statü penceresinde görüntülenebilen bir saldırı hızı sayacı var. Eşyaların pasif ve aktif bonuslarından gelen negatif ya da pozitif değerlere göre artıyor yahut azalıyor. Lakin, bazı silahların hardcoded saldırı hızı bonuslarını yansıtmıyor. (Çift el silahların daha yavaş, hançerlerin daha hızlı olması gibi.)

Savaşçı karakterinin giriş seviyesi silahlarını örnek alalım.

Kılıcın saldırı hızı 22.
Geniş mızrağın saldırı hızı ise 36.

Kılıç giyildiğinde varsayılan saldırı hızı (100) + 22 = 122 oluyor.
Geniş mızrak giyildiğinde ise 136 (görünen 126) oluyor.

Daha yüksek saldırı hızı bonusuyla daha hızlı bir atak bekleriz ama kılıcın bir tam tur komboyu tamamlaması yaklaşık 2 saniye, geniş mızrağın ise yaklaşık 2.5 saniye sürüyor.

Daha fazla saldırı hızı bonusu olmasına rağmen animasyonlardaki hardcoded yavaşlatma sebebiyle daha yavaş vuruyor. Çift el silahların saldırı hızını arayüzden decrease eden kod, saldırı hızını %10 düşürüyor ama iki silah arasındaki animasyon hızı farkı yaklaşık %25.

Bu sorunu çözmek için aşağıdaki gibi bir çözüm yolü izlenmesi gerektiğini düşünüyorum.
  1. TWO_HANDED_WEAPON_ATT_SPEED_DECREASE görsel manipülasyon sistemini tamamen kaldırmak.
  2. Server source içerisinde bazı silahlar üzerindeki hardcoded hız çarpanlarını kaldırmak.
  3. Client data içerisindeki hardcoded yazılmış animasyon hızlarını birbirleriyle eşitlemek.
  4. Silahlar arasındaki hız farkını doğrudan item_proto içerisinden düzenlemek.
Bu şekilde her silah kendi hızını saldırı hızı sayacına doğru bir şekilde yansıtacak, saldırı hızı değerlerini maskelemeye yahut manipüle etmeye gerek kalmayacak.

Client data içerisinden tamamen kaldırılması gerekenler aşağıdaki gibidir.

root\constinfo.py:
Genişlet Daralt Kopyala
TWO_HANDED_WEAPON_ATT_SPEED_DECREASE_VALUE = 0

TWO_HANDED_WEAPON_ATT_SPEED_DECREASE_VALUE = 10

def SET_TWO_HANDED_WEAPON_ATT_SPEED_DECREASE_VALUE():
    global TWO_HANDED_WEAPON_ATT_SPEED_DECREASE_VALUE
    app.SetTwoHandedWeaponAttSpeedDecreaseValue(TWO_HANDED_WEAPON_ATT_SPEED_DECREASE_VALUE)

root\game.py:
Genişlet Daralt Kopyala
# TWO_HANDED_WEAPON_ATTACK_SPEED_UP
constInfo.SET_TWO_HANDED_WEAPON_ATT_SPEED_DECREASE_VALUE()
# END_OF_TWO_HANDED_WEAPON_ATTACK_SPEED_UP

Client source içerisinden tamamen kaldırılması gerekenler aşağıdaki gibidir.

UserInterface\PythonApplicationModule.cpp:
Genişlet Daralt Kopyala
extern int TWOHANDED_WEWAPON_ATT_SPEED_DECREASE_VALUE = 0;

PyObject* SetTwoHandedWeaponAttSpeedDecreaseValue(PyObject* poSelf, PyObject* poArgs)
{
    int iValue;
    if (!PyTuple_GetInteger(poArgs, 0, &iValue))
        return Py_BuildException();

    TWOHANDED_WEWAPON_ATT_SPEED_DECREASE_VALUE = iValue;

    return Py_BuildNone();
}

{ "SetTwoHandedWeaponAttSpeedDecreaseValue", SetTwoHandedWeaponAttSpeedDecreaseValue, METH_VARARGS },

UserInterface\PythonItemModule.cpp:
Genişlet Daralt Kopyala
extern int TWOHANDED_WEWAPON_ATT_SPEED_DECREASE_VALUE;

if ((CItemData::APPLY_ATT_SPEED == ItemApply.bType) && (CItemData::ITEM_TYPE_WEAPON == pItemData->GetType()) && (CItemData::WEAPON_TWO_HANDED == pItemData->GetSubType()))
{
    ItemApply.lValue -= TWOHANDED_WEWAPON_ATT_SPEED_DECREASE_VALUE;
}

PythonPlayerModule.cpp:
Genişlet Daralt Kopyala
extern int TWOHANDED_WEWAPON_ATT_SPEED_DECREASE_VALUE;

if (POINT_ATT_SPEED == iType)
{
    CInstanceBase * pInstance = CPythonPlayer::Instance().NEW_GetMainActorPtr();
    if (pInstance && (CItemData::WEAPON_TWO_HANDED == pInstance->GetWeaponType()))
    {
        iValue -= TWOHANDED_WEWAPON_ATT_SPEED_DECREASE_VALUE;
    }
}

Server source tarafında yapılması gereken değişiklikler aşağıdaki gibidir.

game\battle.cpp:
Genişlet Daralt Kopyala
// Aşağıdaki fonksiyonu aratın.

DWORD GET_ATTACK_SPEED(LPCHARACTER ch)
{
    if (NULL == ch)
        return 1000;

    LPITEM item = ch->GetWear(WEAR_WEAPON); 
    DWORD default_bonus = SPEEDHACK_LIMIT_BONUS * 3;    // 유두리 공속(기본 80) (일반 유저가 speed hack 에 걸리는 것을 막기 위해 *3 추가. 2013.09.11 CYH)
    DWORD riding_bonus = 0;

    if (ch->IsRiding())
    {
        // 뭔가를 탔으면 추가공속 50
        riding_bonus = 50;
    }

    DWORD ani_speed = ani_attack_speed(ch);
    DWORD real_speed = (ani_speed * 100) / (default_bonus + ch->GetPoint(POINT_ATT_SPEED) + riding_bonus);

    // 단검의 경우 공속 2배
    if (item && item->GetSubType() == WEAPON_DAGGER)
        real_speed /= 2;

    return real_speed;
}

// Aşağıdaki gibi değiştirin.

DWORD GET_ATTACK_SPEED(LPCHARACTER ch)
{
    if (NULL == ch)
        return 1000;

    DWORD base_ani_speed = 1000;

    DWORD default_bonus = SPEEDHACK_LIMIT_BONUS * 3;
    DWORD riding_bonus = 0;

    if (ch->IsRiding())
    {
        riding_bonus = 50;
    }

    DWORD real_speed = (base_ani_speed * 100) / (default_bonus + ch->GetPoint(POINT_ATT_SPEED) + riding_bonus);

    return real_speed;
}

Artık data tarafındaki görsel manipülasyon ve server source tarafındaki hardcoded saldırı hızı çarpanları kaldırıldı. Şimdi ise tüm silahların animasyon sürelerinin birbirlerine eşitlenmesi gerekiyor ki ortak bir değer üzerinden eşit bir şekilde hızlandırılıp yavaşlatılabilsin.

Tüm silahlar için savaşçı karakterinin tek el kılıç animasyon sürelerini referans alacağım ve örnek teşkil etmesi için yalnızca çift el silahların animasyonlarını tek el ile eşitleyeceğim.

d:\ymir work\pc\warrior\onehand_sword\combo_01.msa:
Genişlet Daralt Kopyala
ScriptType               MotionData

MotionFileName           "d:/ymir work/pc/warrior/onehand_sword/combo_01.gr2"
MotionDuration           1.000000
Accumulation             0.00    -131.76    0.00

Group ComboInputData
{
    PreInputTime             0.167094
    DirectInputTime          0.533333
    InputLimitTime           0.602564
    LinkTime                 0.058889
}

Group AttackingData
{
    AttackingType        2
    HittingType          2
    StiffenTime          0.000000
    InvisibleTime        0.100000
    ExternalForce        8.000000
    AttackingStartTime   0.192308
    AttackingEndTime     0.315385
    AttackingBone        "equip_right_hand"
    WeaponLength         130.000000
    List HitPosition
    {
        0.192308 -46.995506 -13.970522 146.683151 -54.275871 108.740379 188.980042
        0.200641 -49.442307 -25.598104 141.231308 -80.328575 90.381035 191.179962
        0.208974 -48.925102 -38.902138 134.697052 -105.301872 63.412235 191.735825
        0.217308 -44.242638 -53.100536 127.147919 -125.523422 26.525454 190.021835
        0.225641 -34.685852 -66.419044 118.826851 -136.515366 -20.171759 185.098465
        0.233974 -20.840315 -76.604248 110.151329 -133.426102 -74.215721 175.103012
        0.242308 -3.741836 -82.217232 101.608017 -110.580467 -129.217331 158.848587
        0.250641 15.000633 -82.307358 93.761009 -65.658401 -174.888580 136.455551
        0.258974 33.687275 -76.053665 87.207222 -3.946468 -198.501450 109.348328
        0.267308 50.077217 -62.869793 82.230972 64.521782 -192.043655 79.893646
        0.275641 61.129086 -43.337482 79.102303 127.195580 -151.762283 51.187031
        0.283974 63.680622 -20.114931 78.190094 166.941925 -80.819633 27.672403
        0.292308 59.220440 -2.608357 78.978828 172.536926 -13.844470 16.264215
        0.300641 53.796860 7.225286 80.086380 162.709244 29.123053 12.569182
        0.308974 51.045780 11.248337 80.831078 154.982773 48.077656 11.978332
    }
}

ComboInputData

Oyuncunun vuruş yaparken bir sonraki vuruş için ekrana ne zaman tıklayabileceğini belirler.
Eğer bu süreleri animasyon hızıyla birlikte küçültmezsek, kombo ritmi tamamen bozulur.

PreInputTime

Vuruş penceresinin başladığı anı belirler.

DirectInputTime

Vuruş için tam zamanında basılması gereken ideal anı belirler.

InputLimitTime

Vurma tuşunu kabul etmeyi bıraktığı son anı belirler.

LinkTime

İki animasyonun birbirine yumuşakça bağlanması için gereken geçiş süresini belirler.

AttackingData

Burası silahın düşmana fiziksel olarak çarptığı ve sunucuya "hasar gönder" paketinin tetiklendiği yerdir.

InvisibleTime

Karakter vuruş yaparken hile koruması veya animasyon gereği ne kadar süre boyunca bazı etkileşimlerden
muaf kalacağını belirler.

AttackingStartTime

Silahın havada savrulup düşmana değdiği ilk milisaniyeyi belirler. Doğru ayarlanmazsa karakter silahı savurur
ama hasar çok geç düşer.

AttackingEndTime

Silahın düşmanın içinden geçip hitbox'ı terk ettiği anı belirler.

onehand_sword için combo_01-07.msa arası referans MotionDuration değerlerini alıyorum.
  1. MotionDuration 1.000000
  2. MotionDuration 0.933333
  3. MotionDuration 1.066667
  4. MotionDuration 1.266667
  5. MotionDuration 1.166667
  6. MotionDuration 1.333333
  7. MotionDuration 1.266667
Şimdi sırasıyla twohand_sword içerisindeki combo_01-07.msa ve wait-wait_1.msa dosyalarını ortak referans kabul ettiğimiz kılıç sürelerine eşitlememiz gerekiyor. Çok fazla değere matematiksel olarak doğrusal oranlama uygulanması gerektiği için işin bundan sonrasını yapay zeka ile halledebilirsiniz. Savaşçı karakteri çift el silahlar için oranlanmış dosyalar ektedir.

Şimdi item_proto üzerinden ister pozitif ister negatif bir değer olarak silaha saldırı hızı değeri veriyoruz ve saldırı hızı sayacımız gerçek saldırı hızı değerini yansıtıyor.

Negatif bonuslarda +%- gibi biçimsiz görünümleri değiştirmek için,

locale/tr/locale_game.txt:
Genişlet Daralt Kopyala
// Aşağıdaki tanım,

TOOLTIP_ATT_SPEED    Saldırı Hızı +%%%d    SA

// Aşağıdaki gibi değiştirilebilir.

TOOLTIP_ATT_SPEED    Saldırı Hızı +%%%d    SA

uitooltip.py içerisine dinamik bir sistem de yazılabilir, tercih meselesidir.

bdx1M.gif
 

Dosya Eklentileri

Son düzenleme:
Daha fazla saldırı hızı bonusu olmasına rağmen animasyonlardaki hardcoded yavaşlatma sebebiyle daha yavaş vuruyor. Çift el silahların saldırı hızını arayüzden decrease eden kod, saldırı hızını %10 düşürüyor ama iki silah arasındaki animasyon hızı farkı yaklaşık %25.

Bu sorunu çözmek için aşağıdaki gibi bir çözüm yolü izlenmesi gerektiğini düşünüyorum.
  1. TWO_HANDED_WEAPON_ATT_SPEED_DECREASE görsel manipülasyon sistemini tamamen kaldırmak.
  2. Server source içerisinde bazı silahlar üzerindeki hardcoded hız çarpanlarını kaldırmak.
  3. Client data içerisindeki hardcoded yazılmış animasyon hızlarını birbirleriyle eşitlemek.
  4. Silahlar arasındaki hız farkını doğrudan item_proto içerisinden düzenlemek.
Bu şekilde her silah kendi hızını saldırı hızı sayacına doğru bir şekilde yansıtacak, saldırı hızı değerlerini maskelemeye yahut manipüle etmeye gerek kalmayacak.

Tek el ile çift el saldırı hızını eşitlemek ne kadar doğru? Çift el bildiğim kadarıyla daha fazla saldırı değeri içeriyor ve son combodaki push değerleri daha yüksek. Böyle avantajları varken saldırı hızı eksiğinide giderince tek el kullanmanın bir anlamı kalmaz diye düşünüyorum.

Oyunda her silah sınıfının (tamamen olmasada çoğunun) kendine göre avantajları var. birisi ortalama zarar sağlıyor, diğeri saldırı hızı sağlıyor, 65lerde çift tier sistemi var vs. Bence herşeyi tek düze yapmak yerine mevcuttaki farklılıklar değerlendirilmeli.
 
Tek el ile çift el saldırı hızını eşitlemek ne kadar doğru? Çift el bildiğim kadarıyla daha fazla saldırı değeri içeriyor ve son combodaki push değerleri daha yüksek. Böyle avantajları varken saldırı hızı eksiğinide giderince tek el kullanmanın bir anlamı kalmaz diye düşünüyorum.

Oyunda her silah sınıfının (tamamen olmasada çoğunun) kendine göre avantajları var. birisi ortalama zarar sağlıyor, diğeri saldırı hızı sağlıyor, 65lerde çift tier sistemi var vs. Bence herşeyi tek düze yapmak yerine mevcuttaki farklılıklar değerlendirilmeli.
Tek el ile çift el silahların saldırı hızını eşitlemiyoruz. Animasyonlarının hızını eşitliyoruz ki, ortak bir saldırı hızı bonus değeri üzerinden hızlandırılıp yavaşlatılabilsinler. Çift el silahı daha yavaş vursun istiyorsanız yapmanız gereken tek şey item_proto üzerinden saldırı hızını düşürmek. Eğer animasyonların hızı eşitlenmezse saldırı hızları eşit bile olsa animasyon hızları farklı olduğu için farklı hızlarda vuracaklar.
 
Öncelikle geçmiş olsun değerli gardeşim hasta olmana rağmen vaktini ayırdığın için bizzat teşekkür ederim. Konu hakkındaki fikirlerimi ve naçizane çözüm yöntemimi sunmak isterim.

Bildiğiniz üzere oyunda statü penceresinde görüntülenebilen bir saldırı hızı sayacı var. Eşyaların pasif ve aktif bonuslarından gelen negatif ya da pozitif değerlere göre artıyor yahut azalıyor. Lakin, bazı silahların hardcoded saldırı hızı bonuslarını yansıtmıyor. (Çift el silahların daha yavaş, hançerlerin daha hızlı olması gibi.)

Savaşçı karakterinin giriş seviyesi silahlarını örnek alalım.

Kılıcın saldırı hızı 22.
Geniş mızrağın saldırı hızı ise 36.

Kılıç giyildiğinde varsayılan saldırı hızı (100) + 22 = 122 oluyor.
Geniş mızrak giyildiğinde ise 136 (görünen 126) oluyor.

Daha yüksek saldırı hızı bonusuyla daha hızlı bir atak bekleriz ama kılıcın bir tam tur komboyu tamamlaması yaklaşık 2 saniye, geniş mızrağın ise yaklaşık 2.5 saniye sürüyor.

Daha fazla saldırı hızı bonusu olmasına rağmen animasyonlardaki hardcoded yavaşlatma sebebiyle daha yavaş vuruyor. Çift el silahların saldırı hızını arayüzden decrease eden kod, saldırı hızını %10 düşürüyor ama iki silah arasındaki animasyon hızı farkı yaklaşık %25.

Bu sorunu çözmek için aşağıdaki gibi bir çözüm yolü izlenmesi gerektiğini düşünüyorum.
  1. TWO_HANDED_WEAPON_ATT_SPEED_DECREASE görsel manipülasyon sistemini tamamen kaldırmak.
  2. Server source içerisinde bazı silahlar üzerindeki hardcoded hız çarpanlarını kaldırmak.
  3. Client data içerisindeki hardcoded yazılmış animasyon hızlarını birbirleriyle eşitlemek.
  4. Silahlar arasındaki hız farkını doğrudan item_proto içerisinden düzenlemek.
Bu şekilde her silah kendi hızını saldırı hızı sayacına doğru bir şekilde yansıtacak, saldırı hızı değerlerini maskelemeye yahut manipüle etmeye gerek kalmayacak.

Client data içerisinden tamamen kaldırılması gerekenler aşağıdaki gibidir.

root\constinfo.py:
Genişlet Daralt Kopyala
TWO_HANDED_WEAPON_ATT_SPEED_DECREASE_VALUE = 0

TWO_HANDED_WEAPON_ATT_SPEED_DECREASE_VALUE = 10

def SET_TWO_HANDED_WEAPON_ATT_SPEED_DECREASE_VALUE():
    global TWO_HANDED_WEAPON_ATT_SPEED_DECREASE_VALUE
    app.SetTwoHandedWeaponAttSpeedDecreaseValue(TWO_HANDED_WEAPON_ATT_SPEED_DECREASE_VALUE)

root\game.py:
Genişlet Daralt Kopyala
# TWO_HANDED_WEAPON_ATTACK_SPEED_UP
constInfo.SET_TWO_HANDED_WEAPON_ATT_SPEED_DECREASE_VALUE()
# END_OF_TWO_HANDED_WEAPON_ATTACK_SPEED_UP

Client source içerisinden tamamen kaldırılması gerekenler aşağıdaki gibidir.

UserInterface\PythonApplicationModule.cpp:
Genişlet Daralt Kopyala
extern int TWOHANDED_WEWAPON_ATT_SPEED_DECREASE_VALUE = 0;

PyObject* SetTwoHandedWeaponAttSpeedDecreaseValue(PyObject* poSelf, PyObject* poArgs)
{
    int iValue;
    if (!PyTuple_GetInteger(poArgs, 0, &iValue))
        return Py_BuildException();

    TWOHANDED_WEWAPON_ATT_SPEED_DECREASE_VALUE = iValue;

    return Py_BuildNone();
}

{ "SetTwoHandedWeaponAttSpeedDecreaseValue", SetTwoHandedWeaponAttSpeedDecreaseValue, METH_VARARGS },

UserInterface\PythonItemModule.cpp:
Genişlet Daralt Kopyala
extern int TWOHANDED_WEWAPON_ATT_SPEED_DECREASE_VALUE;

if ((CItemData::APPLY_ATT_SPEED == ItemApply.bType) && (CItemData::ITEM_TYPE_WEAPON == pItemData->GetType()) && (CItemData::WEAPON_TWO_HANDED == pItemData->GetSubType()))
{
    ItemApply.lValue -= TWOHANDED_WEWAPON_ATT_SPEED_DECREASE_VALUE;
}

PythonPlayerModule.cpp:
Genişlet Daralt Kopyala
extern int TWOHANDED_WEWAPON_ATT_SPEED_DECREASE_VALUE;

if (POINT_ATT_SPEED == iType)
{
    CInstanceBase * pInstance = CPythonPlayer::Instance().NEW_GetMainActorPtr();
    if (pInstance && (CItemData::WEAPON_TWO_HANDED == pInstance->GetWeaponType()))
    {
        iValue -= TWOHANDED_WEWAPON_ATT_SPEED_DECREASE_VALUE;
    }
}

Server source tarafında yapılması gereken değişiklikler aşağıdaki gibidir.

game\battle.cpp:
Genişlet Daralt Kopyala
// Aşağıdaki fonksiyonu aratın.

DWORD GET_ATTACK_SPEED(LPCHARACTER ch)
{
    if (NULL == ch)
        return 1000;

    LPITEM item = ch->GetWear(WEAR_WEAPON);
    DWORD default_bonus = SPEEDHACK_LIMIT_BONUS * 3;    // 유두리 공속(기본 80) (일반 유저가 speed hack 에 걸리는 것을 막기 위해 *3 추가. 2013.09.11 CYH)
    DWORD riding_bonus = 0;

    if (ch->IsRiding())
    {
        // 뭔가를 탔으면 추가공속 50
        riding_bonus = 50;
    }

    DWORD ani_speed = ani_attack_speed(ch);
    DWORD real_speed = (ani_speed * 100) / (default_bonus + ch->GetPoint(POINT_ATT_SPEED) + riding_bonus);

    // 단검의 경우 공속 2배
    if (item && item->GetSubType() == WEAPON_DAGGER)
        real_speed /= 2;

    return real_speed;
}

// Aşağıdaki gibi değiştirin.

DWORD GET_ATTACK_SPEED(LPCHARACTER ch)
{
    if (NULL == ch)
        return 1000;

    DWORD base_ani_speed = 1000;

    DWORD default_bonus = SPEEDHACK_LIMIT_BONUS * 3;
    DWORD riding_bonus = 0;

    if (ch->IsRiding())
    {
        riding_bonus = 50;
    }

    DWORD real_speed = (base_ani_speed * 100) / (default_bonus + ch->GetPoint(POINT_ATT_SPEED) + riding_bonus);

    return real_speed;
}

Artık data tarafındaki görsel manipülasyon ve server source tarafındaki hardcoded saldırı hızı çarpanları kaldırıldı. Şimdi ise tüm silahların animasyon sürelerinin birbirlerine eşitlenmesi gerekiyor ki ortak bir değer üzerinden eşit bir şekilde hızlandırılıp yavaşlatılabilsin.

Tüm silahlar için savaşçı karakterinin tek el kılıç animasyon sürelerini referans alacağım ve örnek teşkil etmesi için yalnızca çift el silahların animasyonlarını tek el ile eşitleyeceğim.

d:\ymir work\pc\warrior\onehand_sword\combo_01.msa:
Genişlet Daralt Kopyala
ScriptType               MotionData

MotionFileName           "d:/ymir work/pc/warrior/onehand_sword/combo_01.gr2"
MotionDuration           1.000000
Accumulation             0.00    -131.76    0.00

Group ComboInputData
{
    PreInputTime             0.167094
    DirectInputTime          0.533333
    InputLimitTime           0.602564
    LinkTime                 0.058889
}

Group AttackingData
{
    AttackingType        2
    HittingType          2
    StiffenTime          0.000000
    InvisibleTime        0.100000
    ExternalForce        8.000000
    AttackingStartTime   0.192308
    AttackingEndTime     0.315385
    AttackingBone        "equip_right_hand"
    WeaponLength         130.000000
    List HitPosition
    {
        0.192308 -46.995506 -13.970522 146.683151 -54.275871 108.740379 188.980042
        0.200641 -49.442307 -25.598104 141.231308 -80.328575 90.381035 191.179962
        0.208974 -48.925102 -38.902138 134.697052 -105.301872 63.412235 191.735825
        0.217308 -44.242638 -53.100536 127.147919 -125.523422 26.525454 190.021835
        0.225641 -34.685852 -66.419044 118.826851 -136.515366 -20.171759 185.098465
        0.233974 -20.840315 -76.604248 110.151329 -133.426102 -74.215721 175.103012
        0.242308 -3.741836 -82.217232 101.608017 -110.580467 -129.217331 158.848587
        0.250641 15.000633 -82.307358 93.761009 -65.658401 -174.888580 136.455551
        0.258974 33.687275 -76.053665 87.207222 -3.946468 -198.501450 109.348328
        0.267308 50.077217 -62.869793 82.230972 64.521782 -192.043655 79.893646
        0.275641 61.129086 -43.337482 79.102303 127.195580 -151.762283 51.187031
        0.283974 63.680622 -20.114931 78.190094 166.941925 -80.819633 27.672403
        0.292308 59.220440 -2.608357 78.978828 172.536926 -13.844470 16.264215
        0.300641 53.796860 7.225286 80.086380 162.709244 29.123053 12.569182
        0.308974 51.045780 11.248337 80.831078 154.982773 48.077656 11.978332
    }
}

ComboInputData

Oyuncunun vuruş yaparken bir sonraki vuruş için ekrana ne zaman tıklayabileceğini belirler.
Eğer bu süreleri animasyon hızıyla birlikte küçültmezsek, kombo ritmi tamamen bozulur.

PreInputTime

Vuruş penceresinin başladığı anı belirler.

DirectInputTime

Vuruş için tam zamanında basılması gereken ideal anı belirler.

InputLimitTime

Vurma tuşunu kabul etmeyi bıraktığı son anı belirler.

LinkTime

İki animasyonun birbirine yumuşakça bağlanması için gereken geçiş süresini belirler.

AttackingData

Burası silahın düşmana fiziksel olarak çarptığı ve sunucuya "hasar gönder" paketinin tetiklendiği yerdir.

InvisibleTime

Karakter vuruş yaparken hile koruması veya animasyon gereği ne kadar süre boyunca bazı etkileşimlerden
muaf kalacağını belirler.

AttackingStartTime

Silahın havada savrulup düşmana değdiği ilk milisaniyeyi belirler. Doğru ayarlanmazsa karakter silahı savurur
ama hasar çok geç düşer.

AttackingEndTime

Silahın düşmanın içinden geçip hitbox'ı terk ettiği anı belirler.

onehand_sword için combo_01-07.msa arası referans MotionDuration değerlerini alıyorum.
  1. MotionDuration 1.000000
  2. MotionDuration 0.933333
  3. MotionDuration 1.066667
  4. MotionDuration 1.266667
  5. MotionDuration 1.166667
  6. MotionDuration 1.333333
  7. MotionDuration 1.266667
Şimdi sırasıyla twohand_sword içerisindeki combo_01-07.msa ve wait-wait_1.msa dosyalarını ortak referans kabul ettiğimiz kılıç sürelerine eşitlememiz gerekiyor. Çok fazla değere matematiksel olarak doğrusal oranlama uygulanması gerektiği için işin bundan sonrasını yapay zeka ile halledebilirsiniz. Savaşçı karakteri çift el silahlar için oranlanmış dosyalar ektedir.

Şimdi item_proto üzerinden ister pozitif ister negatif bir değer olarak silaha saldırı hızı değeri veriyoruz ve saldırı hızı sayacımız gerçek saldırı hızı değerini yansıtıyor.

Negatif bonuslarda +%- gibi biçimsiz görünümleri değiştirmek için,

locale/tr/locale_game.txt:
Genişlet Daralt Kopyala
// Aşağıdaki tanım,

TOOLTIP_ATT_SPEED    Saldırı Hızı +%%%d    SA

// Aşağıdaki gibi değiştirilebilir.

TOOLTIP_ATT_SPEED    Saldırı Hızı +%%%d    SA

uitooltip.py içerisine dinamik bir sistem de yazılabilir, tercih meselesidir.

bdx1M.gif
Sağolasın Allah razı olsun, iyi olmaya çalışıyorum..

Bu konuda herkes kendi fikrine ve tercihine göre düzenleme yapabilir tabiki. Fakat böylesine küçük bir detay için bu kadar iş yükünün altına girmek şahsen benim tercihim olmazdı. O yüzden orijinal mantığa ufak bir düzenleme yaparak kullanmayı doğru buluyorum kendimce. Eğer komple eşitlemek isteyenler varsa elbette anlattığın şekilde yapabilirler ama ilerleyen dönemlerde bazı pürüz sorunlar çıkarması muhtemel olacaktır.
 
Öncelikle geçmiş olsun değerli gardeşim hasta olmana rağmen vaktini ayırdığın için bizzat teşekkür ederim. Konu hakkındaki fikirlerimi ve naçizane çözüm yöntemimi sunmak isterim.

Bildiğiniz üzere oyunda statü penceresinde görüntülenebilen bir saldırı hızı sayacı var. Eşyaların pasif ve aktif bonuslarından gelen negatif ya da pozitif değerlere göre artıyor yahut azalıyor. Lakin, bazı silahların hardcoded saldırı hızı bonuslarını yansıtmıyor. (Çift el silahların daha yavaş, hançerlerin daha hızlı olması gibi.)

Savaşçı karakterinin giriş seviyesi silahlarını örnek alalım.

Kılıcın saldırı hızı 22.
Geniş mızrağın saldırı hızı ise 36.

Kılıç giyildiğinde varsayılan saldırı hızı (100) + 22 = 122 oluyor.
Geniş mızrak giyildiğinde ise 136 (görünen 126) oluyor.

Daha yüksek saldırı hızı bonusuyla daha hızlı bir atak bekleriz ama kılıcın bir tam tur komboyu tamamlaması yaklaşık 2 saniye, geniş mızrağın ise yaklaşık 2.5 saniye sürüyor.

Daha fazla saldırı hızı bonusu olmasına rağmen animasyonlardaki hardcoded yavaşlatma sebebiyle daha yavaş vuruyor. Çift el silahların saldırı hızını arayüzden decrease eden kod, saldırı hızını %10 düşürüyor ama iki silah arasındaki animasyon hızı farkı yaklaşık %25.

Bu sorunu çözmek için aşağıdaki gibi bir çözüm yolü izlenmesi gerektiğini düşünüyorum.
  1. TWO_HANDED_WEAPON_ATT_SPEED_DECREASE görsel manipülasyon sistemini tamamen kaldırmak.
  2. Server source içerisinde bazı silahlar üzerindeki hardcoded hız çarpanlarını kaldırmak.
  3. Client data içerisindeki hardcoded yazılmış animasyon hızlarını birbirleriyle eşitlemek.
  4. Silahlar arasındaki hız farkını doğrudan item_proto içerisinden düzenlemek.
Bu şekilde her silah kendi hızını saldırı hızı sayacına doğru bir şekilde yansıtacak, saldırı hızı değerlerini maskelemeye yahut manipüle etmeye gerek kalmayacak.

Client data içerisinden tamamen kaldırılması gerekenler aşağıdaki gibidir.

root\constinfo.py:
Genişlet Daralt Kopyala
TWO_HANDED_WEAPON_ATT_SPEED_DECREASE_VALUE = 0

TWO_HANDED_WEAPON_ATT_SPEED_DECREASE_VALUE = 10

def SET_TWO_HANDED_WEAPON_ATT_SPEED_DECREASE_VALUE():
    global TWO_HANDED_WEAPON_ATT_SPEED_DECREASE_VALUE
    app.SetTwoHandedWeaponAttSpeedDecreaseValue(TWO_HANDED_WEAPON_ATT_SPEED_DECREASE_VALUE)

root\game.py:
Genişlet Daralt Kopyala
# TWO_HANDED_WEAPON_ATTACK_SPEED_UP
constInfo.SET_TWO_HANDED_WEAPON_ATT_SPEED_DECREASE_VALUE()
# END_OF_TWO_HANDED_WEAPON_ATTACK_SPEED_UP

Client source içerisinden tamamen kaldırılması gerekenler aşağıdaki gibidir.

UserInterface\PythonApplicationModule.cpp:
Genişlet Daralt Kopyala
extern int TWOHANDED_WEWAPON_ATT_SPEED_DECREASE_VALUE = 0;

PyObject* SetTwoHandedWeaponAttSpeedDecreaseValue(PyObject* poSelf, PyObject* poArgs)
{
    int iValue;
    if (!PyTuple_GetInteger(poArgs, 0, &iValue))
        return Py_BuildException();

    TWOHANDED_WEWAPON_ATT_SPEED_DECREASE_VALUE = iValue;

    return Py_BuildNone();
}

{ "SetTwoHandedWeaponAttSpeedDecreaseValue", SetTwoHandedWeaponAttSpeedDecreaseValue, METH_VARARGS },

UserInterface\PythonItemModule.cpp:
Genişlet Daralt Kopyala
extern int TWOHANDED_WEWAPON_ATT_SPEED_DECREASE_VALUE;

if ((CItemData::APPLY_ATT_SPEED == ItemApply.bType) && (CItemData::ITEM_TYPE_WEAPON == pItemData->GetType()) && (CItemData::WEAPON_TWO_HANDED == pItemData->GetSubType()))
{
    ItemApply.lValue -= TWOHANDED_WEWAPON_ATT_SPEED_DECREASE_VALUE;
}

PythonPlayerModule.cpp:
Genişlet Daralt Kopyala
extern int TWOHANDED_WEWAPON_ATT_SPEED_DECREASE_VALUE;

if (POINT_ATT_SPEED == iType)
{
    CInstanceBase * pInstance = CPythonPlayer::Instance().NEW_GetMainActorPtr();
    if (pInstance && (CItemData::WEAPON_TWO_HANDED == pInstance->GetWeaponType()))
    {
        iValue -= TWOHANDED_WEWAPON_ATT_SPEED_DECREASE_VALUE;
    }
}

Server source tarafında yapılması gereken değişiklikler aşağıdaki gibidir.

game\battle.cpp:
Genişlet Daralt Kopyala
// Aşağıdaki fonksiyonu aratın.

DWORD GET_ATTACK_SPEED(LPCHARACTER ch)
{
    if (NULL == ch)
        return 1000;

    LPITEM item = ch->GetWear(WEAR_WEAPON);
    DWORD default_bonus = SPEEDHACK_LIMIT_BONUS * 3;    // 유두리 공속(기본 80) (일반 유저가 speed hack 에 걸리는 것을 막기 위해 *3 추가. 2013.09.11 CYH)
    DWORD riding_bonus = 0;

    if (ch->IsRiding())
    {
        // 뭔가를 탔으면 추가공속 50
        riding_bonus = 50;
    }

    DWORD ani_speed = ani_attack_speed(ch);
    DWORD real_speed = (ani_speed * 100) / (default_bonus + ch->GetPoint(POINT_ATT_SPEED) + riding_bonus);

    // 단검의 경우 공속 2배
    if (item && item->GetSubType() == WEAPON_DAGGER)
        real_speed /= 2;

    return real_speed;
}

// Aşağıdaki gibi değiştirin.

DWORD GET_ATTACK_SPEED(LPCHARACTER ch)
{
    if (NULL == ch)
        return 1000;

    DWORD base_ani_speed = 1000;

    DWORD default_bonus = SPEEDHACK_LIMIT_BONUS * 3;
    DWORD riding_bonus = 0;

    if (ch->IsRiding())
    {
        riding_bonus = 50;
    }

    DWORD real_speed = (base_ani_speed * 100) / (default_bonus + ch->GetPoint(POINT_ATT_SPEED) + riding_bonus);

    return real_speed;
}

Artık data tarafındaki görsel manipülasyon ve server source tarafındaki hardcoded saldırı hızı çarpanları kaldırıldı. Şimdi ise tüm silahların animasyon sürelerinin birbirlerine eşitlenmesi gerekiyor ki ortak bir değer üzerinden eşit bir şekilde hızlandırılıp yavaşlatılabilsin.

Tüm silahlar için savaşçı karakterinin tek el kılıç animasyon sürelerini referans alacağım ve örnek teşkil etmesi için yalnızca çift el silahların animasyonlarını tek el ile eşitleyeceğim.

d:\ymir work\pc\warrior\onehand_sword\combo_01.msa:
Genişlet Daralt Kopyala
ScriptType               MotionData

MotionFileName           "d:/ymir work/pc/warrior/onehand_sword/combo_01.gr2"
MotionDuration           1.000000
Accumulation             0.00    -131.76    0.00

Group ComboInputData
{
    PreInputTime             0.167094
    DirectInputTime          0.533333
    InputLimitTime           0.602564
    LinkTime                 0.058889
}

Group AttackingData
{
    AttackingType        2
    HittingType          2
    StiffenTime          0.000000
    InvisibleTime        0.100000
    ExternalForce        8.000000
    AttackingStartTime   0.192308
    AttackingEndTime     0.315385
    AttackingBone        "equip_right_hand"
    WeaponLength         130.000000
    List HitPosition
    {
        0.192308 -46.995506 -13.970522 146.683151 -54.275871 108.740379 188.980042
        0.200641 -49.442307 -25.598104 141.231308 -80.328575 90.381035 191.179962
        0.208974 -48.925102 -38.902138 134.697052 -105.301872 63.412235 191.735825
        0.217308 -44.242638 -53.100536 127.147919 -125.523422 26.525454 190.021835
        0.225641 -34.685852 -66.419044 118.826851 -136.515366 -20.171759 185.098465
        0.233974 -20.840315 -76.604248 110.151329 -133.426102 -74.215721 175.103012
        0.242308 -3.741836 -82.217232 101.608017 -110.580467 -129.217331 158.848587
        0.250641 15.000633 -82.307358 93.761009 -65.658401 -174.888580 136.455551
        0.258974 33.687275 -76.053665 87.207222 -3.946468 -198.501450 109.348328
        0.267308 50.077217 -62.869793 82.230972 64.521782 -192.043655 79.893646
        0.275641 61.129086 -43.337482 79.102303 127.195580 -151.762283 51.187031
        0.283974 63.680622 -20.114931 78.190094 166.941925 -80.819633 27.672403
        0.292308 59.220440 -2.608357 78.978828 172.536926 -13.844470 16.264215
        0.300641 53.796860 7.225286 80.086380 162.709244 29.123053 12.569182
        0.308974 51.045780 11.248337 80.831078 154.982773 48.077656 11.978332
    }
}

ComboInputData

Oyuncunun vuruş yaparken bir sonraki vuruş için ekrana ne zaman tıklayabileceğini belirler.
Eğer bu süreleri animasyon hızıyla birlikte küçültmezsek, kombo ritmi tamamen bozulur.

PreInputTime

Vuruş penceresinin başladığı anı belirler.

DirectInputTime

Vuruş için tam zamanında basılması gereken ideal anı belirler.

InputLimitTime

Vurma tuşunu kabul etmeyi bıraktığı son anı belirler.

LinkTime

İki animasyonun birbirine yumuşakça bağlanması için gereken geçiş süresini belirler.

AttackingData

Burası silahın düşmana fiziksel olarak çarptığı ve sunucuya "hasar gönder" paketinin tetiklendiği yerdir.

InvisibleTime

Karakter vuruş yaparken hile koruması veya animasyon gereği ne kadar süre boyunca bazı etkileşimlerden
muaf kalacağını belirler.

AttackingStartTime

Silahın havada savrulup düşmana değdiği ilk milisaniyeyi belirler. Doğru ayarlanmazsa karakter silahı savurur
ama hasar çok geç düşer.

AttackingEndTime

Silahın düşmanın içinden geçip hitbox'ı terk ettiği anı belirler.

onehand_sword için combo_01-07.msa arası referans MotionDuration değerlerini alıyorum.
  1. MotionDuration 1.000000
  2. MotionDuration 0.933333
  3. MotionDuration 1.066667
  4. MotionDuration 1.266667
  5. MotionDuration 1.166667
  6. MotionDuration 1.333333
  7. MotionDuration 1.266667
Şimdi sırasıyla twohand_sword içerisindeki combo_01-07.msa ve wait-wait_1.msa dosyalarını ortak referans kabul ettiğimiz kılıç sürelerine eşitlememiz gerekiyor. Çok fazla değere matematiksel olarak doğrusal oranlama uygulanması gerektiği için işin bundan sonrasını yapay zeka ile halledebilirsiniz. Savaşçı karakteri çift el silahlar için oranlanmış dosyalar ektedir.

Şimdi item_proto üzerinden ister pozitif ister negatif bir değer olarak silaha saldırı hızı değeri veriyoruz ve saldırı hızı sayacımız gerçek saldırı hızı değerini yansıtıyor.

Negatif bonuslarda +%- gibi biçimsiz görünümleri değiştirmek için,

locale/tr/locale_game.txt:
Genişlet Daralt Kopyala
// Aşağıdaki tanım,

TOOLTIP_ATT_SPEED    Saldırı Hızı +%%%d    SA

// Aşağıdaki gibi değiştirilebilir.

TOOLTIP_ATT_SPEED    Saldırı Hızı +%%%d    SA

uitooltip.py içerisine dinamik bir sistem de yazılabilir, tercih meselesidir.

bdx1M.gif
Paylaşım için Teşekkürler Sadece Erkek Savaşçı içinmi Kadın Mevcutmudur yoksa onuda Aynı tek elden alıp çift ele uyarlamak gerekiyormu
 
Paylaşım için Teşekkürler Sadece Erkek Savaşçı içinmi Kadın Mevcutmudur yoksa onuda Aynı tek elden alıp çift ele uyarlamak gerekiyormu
Her iki cinsiyet de aynı dosyaları kullanıyor sadece dosyalar duplicate edilmiş pc'den kopyalayıp pc2'ye yapıştırabilirsin. Sistemin işleyişini göstermek adına sadece konuda bahsedilen çift el animasyonlarını düzenledim. Çan, yelpaze, hançer, yay animasyonlarının da ortak bir referansta eşitlenmesi gerekiyor. Tek el referansını seçmemin sebebi MotionDuration değerinin tam olarak 1.000000 olmasıydı. Hangi ortak referansı kullanacağınız tercihinize kalmış tüm animasyon hızları eşitlendikten sonra item_proto üzerinden saldırı hızlarını istediğiniz gibi ayarlayabilirsiniz.
 
Geri
Üst