GM Full Set: Güvenli Equip ve Slot Çakışması Önleme

  • Konuyu açan Konuyu açan Furion99
  • Açılış Tarihi Açılış Tarihi
  • Yanıt Yanıt 0
  • Gösterim Gösterim 99

Furion99

MT Üye
MT Üye
Mesaj
187
Çözümler
6
Beğeni
74
Puan
724
Ticaret Puanı
0
Örnek syserr:
Genişlet Daralt Kopyala
SYSERR: Dec 21 08:56:13 :: EquipTo: EquipTo: item already exist (this: #17109 Abanoz Küpe+9 cell: 6 Abanoz Küpe+9)
SYSERR: Dec 21 08:56:20 :: EquipTo: EquipTo: item already exist (this: #17109 Abanoz Küpe+9 cell: 6 Abanoz Küpe+9)

char_item.cpp:
Genişlet Daralt Kopyala
// EKLEME BAŞLANGICI - Double equip kontrolü
if (GetWear(iWearCell))
{
    sys_err("EquipItem: Slot already occupied! Character: %s, Cell: %d, Existing Item: %s (#%u), New Item: %s (#%u)",
        GetName(),
        iWearCell,
        GetWear(iWearCell)->GetName(),
        GetWear(iWearCell)->GetID(),
        item->GetName(),
        item->GetID()
    );
    ChatPacket(CHAT_TYPE_INFO, LC_TEXT("Bu slot zaten dolu. Lütfen tekrar deneyin."));
    return false;
}
// EKLEME SONU

item.cpp:
Genişlet Daralt Kopyala
if (ch->GetWear(bWearCell))
{
    sys_err("EquipTo: Slot already occupied! Character: %s, Cell: %d, Existing Item: %s (#%u), New Item: %s (#%u)",
        ch->GetName(),
        bWearCell,
        ch->GetWear(bWearCell)->GetName(),
        ch->GetWear(bWearCell)->GetID(),
        GetName(),
        GetID()
    );
   
    ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("Ekipman takma hatasi. Lutfen tekrar deneyin."));
   
    return false;
}

cmd_gm.cpp:
Genişlet Daralt Kopyala
ACMD(do_item_full_set)
{
    if (!ch)
        return;

    // =========================
    // 1) Level Gate
    // =========================
    if (ch->GetLevel() < 75)
    {
        ch->ChatPacket(CHAT_TYPE_INFO, "<Full_Set> Bu komutu kullanabilmek için en az 75. seviyede olmanız gerekmektedir.");
        return;
    }

    // =========================
    // 2) Cooldown / Anti-spam
    // =========================
    {
        const int COOLDOWN_SEC = 2;
        const DWORD now  = get_global_time();
        const DWORD next = ch->GetQuestFlag("full_set.next_time");

        if (next > now)
        {
            ch->ChatPacket(CHAT_TYPE_INFO,
                "<Full_Set> Komut çok sık kullanılıyor. Lütfen %u saniye sonra tekrar deneyiniz.",
                next - now);
            return;
        }

        ch->SetQuestFlag("full_set.next_time", now + COOLDOWN_SEC);
    }

    // Komut boyunca: kaç item drop oldu?
    int droppedCount = 0;

    // =========================
    // Helper: Envantere koy, yer yoksa YERE DÜŞÜR (Yeni itemler için)
    // =========================
    auto MoveSpawnToInventoryOrDrop = [&](LPITEM item, int &dropCounter)
    {
        if (!item)
            return;

        int pos = ch->GetEmptyInventory(item->GetSize());
        if (pos != -1)
        {
            item->AddToCharacter(ch, TItemPos(INVENTORY, pos));
            return;
        }

        // Envanter dolu -> yere bırak + ownership + destroy
        PIXEL_POSITION p;
        p.x = ch->GetX();
        p.y = ch->GetY();
        p.z = ch->GetZ();

        if (!item->AddToGround(ch->GetMapIndex(), p))
        {
            // Yere de bırakılamazsa son çare sil (çok nadir: sectree yok vs.)
            ITEM_MANAGER::instance().RemoveItem(item);
            return;
        }

        // Owner koruması + otomatik temizleme (item kaybını minimize)
        item->SetOwnership(ch, 120);
        item->StartDestroyEvent(600);

        ++dropCounter;
    };

    // =========================
    // Helper: Slot doluyken EquipTo çağırma -> syserr kes
    // =========================
    auto SafeEquipSpawnedItem = [&](LPITEM item)
    {
        if (!item)
            return;

        const int cell = item->FindEquipCell(ch);

        // slot yok veya dolu -> envanter / drop
        if (cell < 0 || ch->GetWear(cell) != NULL)
        {
            MoveSpawnToInventoryOrDrop(item, droppedCount);
            return;
        }

        // EquipTo başarısızsa envanter/drop
        if (!item->EquipTo(ch, cell))
            MoveSpawnToInventoryOrDrop(item, droppedCount);
    };

    // =========================
    // 3) Eski itemler: deterministik unequip + rollback (KAYBI MİNİMİZE)
    // =========================
    auto UnequipAllWearSafe = [&]() -> bool
    {
        struct RemovedWear
        {
            int slot;
            LPITEM item;
        };

        std::vector<RemovedWear> removed;
        removed.reserve(WEAR_MAX_NUM);

        // 1) Tüm giyili itemleri sök
        for (int i = 0; i < WEAR_MAX_NUM; ++i)
        {
            LPITEM pItem = ch->GetWear(i);
            if (!pItem)
                continue;

            pItem->RemoveFromCharacter();
            removed.push_back({ i, pItem });
        }

        // 2) Envantere taşı (yer yoksa rollback + iptal)
        for (const auto &r : removed)
        {
            LPITEM item = r.item;
            if (!item)
                continue;

            int pos = ch->GetEmptyInventory(item->GetSize());
            if (pos == -1)
            {
                // Rollback: mümkünse geri tak
                for (const auto &rb : removed)
                {
                    LPITEM it = rb.item;
                    if (!it)
                        continue;

                    if (it->GetOwner() != ch)
                        continue;

                    if (ch->GetWear(rb.slot) == NULL)
                        it->EquipTo(ch, rb.slot);
                }

                sys_log(0, "FULL_SET: Operation aborted. Inventory full (unequip rollback). ch=%s(%u)",
                    ch->GetName(), ch->GetPlayerID());

                ch->ChatPacket(CHAT_TYPE_INFO,
                    "<Full_Set> Envanterinizde yeterli boş alan bulunmamaktadır. Lütfen yer açtıktan sonra tekrar deneyiniz.");
                return false;
            }

            item->AddToCharacter(ch, TItemPos(INVENTORY, pos));
        }

        return true;
    };

    if (!UnequipAllWearSafe())
        return;

    usleep(30000);

    // =========================
    // 4) Orijinal vnum'lar
    // =========================
    switch (ch->GetJob())
    {
        case JOB_SURA:
        {
            SafeEquipSpawnedItem(ITEM_MANAGER::instance().CreateItem(11699)); usleep(30000);
            SafeEquipSpawnedItem(ITEM_MANAGER::instance().CreateItem(13049)); usleep(30000);
            SafeEquipSpawnedItem(ITEM_MANAGER::instance().CreateItem(15189)); usleep(30000);
            SafeEquipSpawnedItem(ITEM_MANAGER::instance().CreateItem(189));   usleep(30000);
            SafeEquipSpawnedItem(ITEM_MANAGER::instance().CreateItem(12529)); usleep(30000);
            SafeEquipSpawnedItem(ITEM_MANAGER::instance().CreateItem(14109)); usleep(30000);
            SafeEquipSpawnedItem(ITEM_MANAGER::instance().CreateItem(17209)); usleep(30000);
            SafeEquipSpawnedItem(ITEM_MANAGER::instance().CreateItem(16209)); usleep(30000);
        }
        break;

        case JOB_WARRIOR:
        {
            SafeEquipSpawnedItem(ITEM_MANAGER::instance().CreateItem(11299)); usleep(30000);
            SafeEquipSpawnedItem(ITEM_MANAGER::instance().CreateItem(13049)); usleep(30000);
            SafeEquipSpawnedItem(ITEM_MANAGER::instance().CreateItem(15189)); usleep(30000);
            SafeEquipSpawnedItem(ITEM_MANAGER::instance().CreateItem(3159));  usleep(30000);
            SafeEquipSpawnedItem(ITEM_MANAGER::instance().CreateItem(12249)); usleep(30000);
            SafeEquipSpawnedItem(ITEM_MANAGER::instance().CreateItem(14109)); usleep(30000);
            SafeEquipSpawnedItem(ITEM_MANAGER::instance().CreateItem(17109)); usleep(30000);
            SafeEquipSpawnedItem(ITEM_MANAGER::instance().CreateItem(16109)); usleep(30000);
        }
        break;

        case JOB_SHAMAN:
        {
            SafeEquipSpawnedItem(ITEM_MANAGER::instance().CreateItem(11899)); usleep(30000);
            SafeEquipSpawnedItem(ITEM_MANAGER::instance().CreateItem(13049)); usleep(30000);
            SafeEquipSpawnedItem(ITEM_MANAGER::instance().CreateItem(15189)); usleep(30000);
            SafeEquipSpawnedItem(ITEM_MANAGER::instance().CreateItem(7159));  usleep(30000);
            SafeEquipSpawnedItem(ITEM_MANAGER::instance().CreateItem(12669)); usleep(30000);
            SafeEquipSpawnedItem(ITEM_MANAGER::instance().CreateItem(14109)); usleep(30000);
            SafeEquipSpawnedItem(ITEM_MANAGER::instance().CreateItem(17209)); usleep(30000);
            SafeEquipSpawnedItem(ITEM_MANAGER::instance().CreateItem(16209)); usleep(30000);
        }
        break;

        case JOB_ASSASSIN:
        {
            SafeEquipSpawnedItem(ITEM_MANAGER::instance().CreateItem(11499)); usleep(30000);
            SafeEquipSpawnedItem(ITEM_MANAGER::instance().CreateItem(13049)); usleep(30000);
            SafeEquipSpawnedItem(ITEM_MANAGER::instance().CreateItem(15189)); usleep(30000);
            SafeEquipSpawnedItem(ITEM_MANAGER::instance().CreateItem(1139));  usleep(30000);
            SafeEquipSpawnedItem(ITEM_MANAGER::instance().CreateItem(12389)); usleep(30000);
            SafeEquipSpawnedItem(ITEM_MANAGER::instance().CreateItem(14109)); usleep(30000);
            SafeEquipSpawnedItem(ITEM_MANAGER::instance().CreateItem(17189)); usleep(30000);
            SafeEquipSpawnedItem(ITEM_MANAGER::instance().CreateItem(16189)); usleep(30000);
        }
        break;

        default:
        {
            ch->ChatPacket(CHAT_TYPE_INFO, "<Full_Set> Mevcut karakter sınıfı bu komut tarafından desteklenmemektedir.");
            sys_log(0, "FULL_SET: Unsupported character class detected. ch=%s(%u) job=%d",
                ch->GetName(), ch->GetPlayerID(), ch->GetJob());
            return;
        }
    }

    // Drop özeti: komut başına tek mesaj
    if (droppedCount > 0)
    {
        ch->ChatPacket(CHAT_TYPE_INFO,
            "<Full_Set> Envanterde yeterli boş alan olmadığı için %d adet eşya yere bırakıldı (korumalı ve süreli).",
            droppedCount);
    }

    ch->ChatPacket(CHAT_TYPE_INFO, "<Full_Set> Ekipman seti başarıyla teslim edilmiştir.");
    sys_log(0, "FULL_SET: Completed successfully. ch=%s(%u) job=%d",
        ch->GetName(), ch->GetPlayerID(), ch->GetJob());
}

Örnek log:
Genişlet Daralt Kopyala
Dec 23 05:55:27 :: COMMAND: Admin: full_set
Dec 23 05:55:28 :: COMMAND: Admin: full_set
Dec 23 05:55:28 :: Invalid Socket Count 3, set to maximum
Dec 23 05:55:28 :: Invalid Socket Count 3, set to maximum
Dec 23 05:55:28 :: FULL_SET: Completed successfully. ch=Admin(22) job=2

Not:
Genişlet Daralt Kopyala
Yere atma kısmı çalışmıyor o'nuda düzeltebilirsiniz. "Mainline"
 
Son düzenleme:
Geri
Üst