Modifikace MaNGOSe

Z WoWResource Wiki
Verze z 9. 10. 2008, 19:31, kterou vytvořil BLuma (diskuse | příspěvky) (fix "on kill item" při vyšším počtu itemů bez místa na itemy :))
Přejít na: navigace, hledání

Vytvoření vlastního příkazu

Na vytvoření nového příkazu je nutné definovat ho na několika místech.

  1. Soubor Chat.h musí obsahovat jeho hlavičku ve třídě ChatHandler. Návratová hodnota každého příkazu je bool a vstupními argumenty je const char*. Jako šablonu lze tedy vždy použít: bool Handle<NázevPříkazu>Command(const char *args);
  2. Je nutné vytvořit kód příkazu, vzhledem ke struktuře přístupových práv v MaNGOSu (rozdělených na 0,1,2,3) se příkazy řadí do souborů Level<0-3>.cpp, případně debugcmds.cpp. Návratová hodnota je true pokud vše proběhlo v pořádku, při návratu false je oznámen Syntax error.
  3. Zbývá nastavit na jaký .příkaz bude ve hře tento kód vykonán. Toto se nastavuje v souboru Chat.cpp v poli commandTable (nebo jiném pokud chcete zařadit do nějaké podkategorie příkazů nebo vytvořit vlastní). Řádek pak obsahuje: { "příkazVeHře", SEC_<přístopová práva>, &ChatHandler::Handle<NázevPříkazu>Command, "", <NULL nebo název dalšího pole příkazů> }, Prázdný řetězec slouží jako pole pro nápovědu, která je načtena z databáze. Nový příkaz bude fungovat i bez záznamu v db v tabulce commands, ale nebude obsahovat nápovědu.

Když hráč zabije hráče

Pro možnost přidání peněz nebo předmětu za zabití hráče. Otevřete soubor Unit.cpp a najděte metodu DealDamage(). Poté nalezněte podmínku if (health <= damage) a blok pod touto podmínkou zpracovává zabití nepřítele. Pro ověření, že hráč zabil hráče stačí jednoduchá podmínka if(GetTypeId() == TYPEID_PLAYER && pVictim->GetTypeId() == TYPEID_PLAYER). Pokud chcete ověřit i zda-li hráč byl z druhé frakce přidejte podmínku ((Player*)this)->GetTeam() != ((Player*)pVictim)->GetTeam(), případně přidat vlastní další podmínky (ověření levelu, opakovaného zabíjení,...)

  • Pro udělení pěnez stačí požít funkci Player::ModifyMoney(<o kolik>);
  • Pro přidání itemu lze použít:
#define LOOT_ITEM_ID 9014555 /* entry předmětu */
#define LOOT_ITEM_COUNT 1 /* počet předmětů, které obdrží */

if(GetTypeId() == TYPEID_PLAYER && pVictim->GetTypeId() == TYPEID_PLAYER && ((Player*)this)->GetTeam() != ((Player*)pVictim)->GetTeam())
{
    Player *me = (Player*)this;
    ItemPosCountVec dest;
    uint32 no_space_count = 0, count = LOOT_ITEM_COUNT;
    uint8 msg = me->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, LOOT_ITEM_ID, count, &no_space_count);
    if( msg != EQUIP_ERR_OK )
        count -= no_space_count;
   
    if (count != 0 && !dest.empty())
    {
        Item* item = me->StoreNewItem( dest, LOOT_ITEM_ID, true, Item::GenerateItemRandomPropertyId(LOOT_ITEM_ID));
        if(item)
            me->SendNewItem(item,count,false,false);
    }
}

Příkazy

Připojení do fronty na battleground

Pro MaNGOS bez Arena patche

Hlavička Chat.h:

bool HandleBgCommand(const char* args);

Chat.cpp:

{ "bg",      SEC_PLAYER,  &ChatHandler::HandleBgCommand,       "", NULL },

Level0.cpp:

bool ChatHandler::HandleBgCommand(const char* args)
{
    if (!*args)
        return false;

    uint8 bgTypeId = 0;

    if (stricmp(args, "wsg") == 0) { bgTypeId = 2; }
    else if (stricmp(args, "ab" ) == 0) { bgTypeId = 3; }
    else if (stricmp(args, "eye") == 0) { bgTypeId = 7; }

    if (bgTypeId >= MAX_BATTLEGROUND_TYPES || !bgTypeId)
        return false;

    Player* me = m_session->GetPlayer();

    if (me->InBattleGround() || !me->CanJoinToBattleground())
        return false;

    BattleGround *bg = sBattleGroundMgr.GetBattleGround(bgTypeId);
    if (!bg)
        return false;

    if (me->InBattleGroundQueueForBattleGroundType(bgTypeId))
        return false;

    uint32 queueSlot = me->AddBattleGroundQueueId(bgTypeId);
    if (queueSlot == PLAYER_MAX_BATTLEGROUND_QUEUES)
        return false;

    me->SetBattleGroundEntryPoint(me->GetMapId(), me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), me->GetOrientation());

    WorldPacket data;
    sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, me->GetTeam(), queueSlot, STATUS_WAIT_QUEUE, 0, 0);
    m_session->SendPacket(&data);

    sBattleGroundMgr.m_BattleGroundQueues[bgTypeId].AddPlayer(me, bgTypeId);
    return true;
}

Pouštění hudby všem hráčům

V souboru debugcmds.cpp najděte metodu ChatHandler::HandlePlaySound2Command a uvnitř nahraďte

    m_session->GetPlayer()->PlaySound(soundid, false);

za

    WorldPacket data(SMSG_PLAY_SOUND, 4);
    data << soundid;
    
    sWorld.SendGlobalMessage(&data);

Poté ve hře můžete pustit všem hudbu pomocí příkazu .debug ps <id hudby>


Portnutí všech hráčů za GM

Hráč může portnutí odmítnout, ti kdo přijmou budou portnuti na GM, které příkaz použilo +- 1yard do okolí a 2y nad (aby nedošlo k propadnutí pod zem)

bool ChatHandler::HandlePortAllToMe(const char* args)
{
    HashMapHolder<Player>::MapType map = ObjectAccessor::Instance().GetPlayers();
    Player* me = m_session->GetPlayer();

    float x,y,z;
    me->GetPosition(x, y, z); // resp. GetClosePoint() to, ale nenajde gameobjekty ve vzduchu.
    z += 2.0f;
    WorldPacket data(SMSG_SUMMON_REQUEST, 8+4+4);
    data << uint64(me->GetGUID());                    // summoner guid
    data << uint32(me->GetZoneId());                  // summoner zone
    data << uint32(MAX_PLAYER_SUMMON_DELAY*1000);     // auto decline after msecs

    for(HashMapHolder<Player>::MapType::iterator it = map.begin(); it != map.end(); it++)
    {
        if (it->second == me)
            continue;

        it->second->SetSummonPoint(me->GetMapId(), x + (rand_norm()*2-1), y + (rand_norm()*2-1), z);
        it->second->GetSession()->SendPacket(&data);
    }
    return true;
}