Informatikai Barkács Fórum

WORLD OF WARCRAFT SZERVER => Core/Mag Modifikációk => A témát indította: Shyro Dátum 2013 április 30, 10:15:44 DÉLUTÁN

Cím: [CORE] IsBalanced()
Írta: Shyro Dátum 2013 április 30, 10:15:44 DÉLUTÁN
Sziasztok!

Nézegettem egy két alacsony népességű magyar szervert és azt figyeltem meg, hogy nagy a létszámbeli különbség az Alliance és Horde tábor között online játékosok tekintetében. Egy kezdő szervernél ez szerintem probléma, hiszen kevesebb az esély arra, hogy indul Battleground, és egyéb következményei is lehetnek. Így erre a problémára próbáltam kiötleni valamilyen megoldást.

Terv:
- 50 és 200 online játékos közötti létszámnál vegye figyelembe a külöbség mértékét
- 15% - nál ne legyen nagyobb a két frakció százalékos eltérése
- Túl magas eltérés esetén ne engedélyezze a nagyobb létszámú frakcióba tartozó karakter belépését


Megvalósítás:

Szükséges fájlok:Módosítandó részek:

~World.h
A World.h header fájlban szükségünk lesz két változóra, melyek az aktuális létszámot tárolják az adott frakciókból (a szerver létszáma mellett). Ezeket a World osztály private részében kell definiálni:
uint32 m_PlayerACount;
uint32 m_PlayerHCount;

Gondolkodni kell ezen értékek elérhetőségéről is, így a public részben:
inline uint32 GetPlayerACount() const { return m_PlayerACount; }
inline uint32 GetPlayerHCount() const { return m_PlayerHCount; }

Minden egyes játékos belépésénél az m_PlayerCount változó értéke eggyel nő, ezt a műveletet az IncreasePlayerCount() függvény végzi. Mivel mi szeretnénk növelni ugyanakkor az m_PlayerACount és m_PlayerHCount változók értékét is, kicsit módosítanunk kell a függvényt:
inline void IncreasePlayerCount(uint32 faction)
{
    m_PlayerCount++;
    m_MaxPlayerCount = std::max(m_MaxPlayerCount, m_PlayerCount);

    switch(faction)
    {
        case ALLIANCE:
            m_PlayerACount++;
        break;

        case HORDE:
            m_PlayerHCount++;
        break;
    }
}

Természetesen gondoskodni kell arról, hogy adott játékos kijelentkezése esetében ezek az értékek csökkenjenek:
inline void DecreasePlayerCount(uint32 faction)
{
    m_PlayerCount--;

    switch(faction)
    {
        case ALLIANCE:
            m_PlayerACount--;
        break;

        case HORDE:
            m_PlayerHCount--;
        break;
    }
}


~World.cpp
Nem szabad megfeledkezni az általunk használt változók kezdőértékeinek megadásáról. Ezt a World.cpp fájlban a World osztály konstruktorában tesszük meg, az m_PlayerCount változó kezdőértékének megadásának mintájára:
m_PlayerACount = 0;
m_PlayerHCount = 0;


~Player.cpp
Mikor fognak meghívódni az IncreasePlayerCount() és DecreasePlayerCount() függvényeink? A Player.cpp fájlban a Player osztály konstruktorában és destruktorában, hiszen minden ilyen objektum létrejöttekor növeljük a játékosok számát, és "pusztulásakor" csökkentjük azt. Mivel paramétert adtunk meg a függvények definiálásánál, így használatukkor a függvény egy paramétert vár, amit most meg kell adnunk:

Konstruktorban:
sWorld->IncreasePlayerCount(Player::TeamForRace(getRace()));
Destruktorban:
sWorld->DecreasePlayerCount(Player::TeamForRace(getRace()));
A módosított függvényt a konstruktor esetében a függvény végébe destruktor esetében az elejébe kell helyezni.

Hibalehetőségek:
- Elméletileg a konstruktorban is meghívható a getRace() függvény, ha mégsem, az oka, hogy még nincs érték, melyet visszaadhatna. Nekem azt mondták, hogy rendelkezik ekkor már megfelelő visszatérési értékkel, de a biztonság kedvéért érdemes a végébe tenni a kódrészletet.
- Szerintem ha meg is hívható, akkor maximum a formáva lehet probléma: illene oda egy this a Player helyére (talán)

~WorldSession.h
Már megvannak a megfelelő változóink, melyekkel már kalkulálhatunk, már csak a függvény hiányzik, amely a döntést végzi (beléphet e a játékos, avagy sem). Ezt a függvényt a WorldSession.h header fájlban a WorldSession osztály public részében kell definiálni. Az ok erre csak annyi, hogy a CharacterHandler.cpp majd innen veszi a függvényt.
bool IsBalanced(uint32 _count, uint32 _acount, uint32 _hcount, uint8 _race)
{
uint32 apercent = ((_acount.ToDouble / _count.ToDouble) * 100).ToUInt32;
uint32 hpercent = ((_hcount.ToDouble / _count.ToDouble) * 100).ToUInt32;

if(_count > 50 && _count < 200)
if(apercent > hpercent)
    if((apercent - hpercent) > 15)
        switch(Player::TeamForRace(_race))
        {
            case ALLIANCE:
                return false;
            break;

            case HORDE:
                return true;
            break;
        }
    else if(apercent < hpercent)
    if((hpercent - apercent) > 15)
        switch(Player::TeamForRace(_race))
        {
            case ALLIANCE:
                return true;
            break;

            case HORDE:
                return false;
            break;
        }

    return true;
}


~CharacterHandler.cpp
A függvényünket már csak meg kell hívni a megfelelő helyen a megfelelő paraméterekkel. A CharacterHandler.cpp fájl
void WorldSession::HandlePlayerLoginOpcode(WorldPacket& recvData)
függvényében kell elhelyeznünk a következő sorokat:
uint32 race = 0;
(Alapvetően nem kérdezi le a race értékét, de nekünk szükségünk lesz rá.)
recvData >> race;
(Ezt mindenképpen a recvData >> playerGuid; sor alá kell beszúrnunk, ugyanis a recvData egy adathalmaz, mely esetében a 2. komponens tartalmazza az adott race értéket.)
if(!IsBalanced(GetPlayerCount(), GetPlayerACount(), GetPlayerHCount(), race))
{
    sLog->outError(LOG_FILTER_NETWORKIO, "Account (%u) can't login with that character (%u).", GetAccountId(), GUID_LOPART(playerGuid));
    KickPlayer();
    return;
}

Ha a játékosunk nem a megfelelő frakciójú karakterrel szeretne bejelentkezni, egyszerüen nem fog tudni.

Hibalehetőségek:

- Ha nem a megfelelő helyre szúrtuk be a kódrészleteinket, akkor ki kell találni, hogy mégis hova kellene.

~Vélemény
A TrinityCore borzasztóan rosszul kommentelt, nem megfelelően dokumentált (inkább egyátalán nem). Nagyon nehéz egy olyan kódtömeget megismerni, amit valakik valamikor kitaláltak, lekódoltak és nem biztosítottak hozzá megfelelő leírást, hogy mi micsoda.
Mivel nem ismerem a TrinityCore működését, így egy ilyen kis nyámnyila kód megírása is nehézséget okozott: honnan kapja ez az értéket, hol van az definiálva... stb.
Ez az oka a sok hibalehetőségnek, mert az ember csak tippelni tud. Avagy tesztelni.

~FONTOS
Nem debuggoltam, nem teszteltem. Egyrészt erre nincs is lehetőségem, másrészt nem is szeretném. :) Akinek van módja és kedve tesztelni, az hibák kapcsán írjon, mindenképpen érdekelni fog. Úgy gondolom, kiindulópontnak ez megfelelő.
Cím: Re:[CORE] IsBalanced()
Írta: EroniX Dátum 2013 április 30, 10:31:56 DÉLUTÁN
Nagyon jó ötlet, és micsoda kód!


if(_count > 50 && _count < 200)
if(apercent > hpercent)
    if((apercent - hpercent) > 15)
        switch(Player::TeamForRace(_race))
        {
            case ALLIANCE:
                return false;
            break;

            case HORDE:
                return true;
            break;
        }
    else if(apercent < hpercent)
    if((hpercent - apercent) > 15)
        switch(Player::TeamForRace(_race))
        {
            case ALLIANCE:
                return true;
            break;

            case HORDE:
                return false;
            break;
        }

    return true;
}


Ezt így írtam volna meg:

if(_count > 50 && _count < 200)
{
uint32 biggerTeam = (apercent > hpercent) ? ALLIANCE : HORDE;
if(abs(apercent - hpercent) > 15 && Player::TeamForRace(_race) == biggerTeam)
return false;

return true;
}


De a tiéd is tökéletes, szép munka. :)
Cím: Re:[CORE] IsBalanced()
Írta: Shyro Dátum 2013 április 30, 10:34:54 DÉLUTÁN
Jogos, korrektebb a megoldásod. Nekem is jobban tetszik.  ;D

Sőt, most nézem, hogy nálam kell az a kapcsos! (fixálom) or not
Cím: Re:[CORE] IsBalanced()
Írta: Bluerák Dátum 2013 április 30, 11:19:05 DÉLUTÁN
Szuper ötlet, de például ha én nem csinálhatnék allist, akkor biztos nem játszanék azon a bizonyos szerveren.  :D
De remek kód és a megvalósítás is +1.
Cím: Re:[CORE] IsBalanced()
Írta: Shyro Dátum 2013 május 01, 12:28:32 DÉLELŐTT
Alliance - os karaktert még készíthetsz, csak nem léphetsz be vele. Biztos, hogy menne az idegeskedés. Bár, akkor is megy, ha nincs ellenfél nem?  ;D
Cím: Re:[CORE] IsBalanced()
Írta: Naxon90 Dátum 2013 május 01, 09:28:24 DÉLELŐTT
Ez elképesztő,szép munka! :)
Cím: Re:[CORE] IsBalanced()
Írta: Bluerák Dátum 2013 május 01, 11:39:52 DÉLELŐTT
Idézetet írta: Shyro Dátum 2013 május 01, 12:28:32 DÉLELŐTT
Alliance - os karaktert még készíthetsz, csak nem léphetsz be vele. Biztos, hogy menne az idegeskedés. Bár, akkor is megy, ha nincs ellenfél nem?  ;D
Az még idegesítőbb.  :P