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 1
  • Gösterim Gösterim 206

Furion99

MT Üye
MT Üye
Mesaj
188
Çözümler
6
Beğeni
78
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:
Versiyon2 ayrıca tavsiye edilen:

item.cpp:
Genişlet Daralt Kopyala
Arat:
void CItem::AlterToSocketItem(int iSocketCount)
{
    if (iSocketCount >= ITEM_SOCKET_MAX_NUM)
    {
        sys_log(0, "Invalid Socket Count %d, set to maximum", ITEM_SOCKET_MAX_NUM);
        iSocketCount = ITEM_SOCKET_MAX_NUM;
    }

    for (int i = 0; i < iSocketCount; ++i)
        SetSocket(i, 1);
}

Değiştir:
void CItem::AlterToSocketItem(int iSocketCount)
{
    if (iSocketCount < 0)
    {
        iSocketCount = 0;
    }

    if (iSocketCount > ITEM_SOCKET_MAX_NUM)
    {
        sys_log(0, "Invalid Socket Count %d, maksimuma ayarlandı (%d)",
            iSocketCount, ITEM_SOCKET_MAX_NUM);
        iSocketCount = ITEM_SOCKET_MAX_NUM;
    }

    for (int i = 0; i < iSocketCount; ++i)
    {
        SetSocket(i, 1);
    }
}

cmd_gm.cpp:
Genişlet Daralt Kopyala
Ekle: #include <vector>

Arat:
// LUA_ADD_GOTO_INFO
struct GotoInfo
{
    std::string     st_name;

    BYTE     empire;
    int     mapIndex;
    DWORD     x, y;

    GotoInfo()
    {
        st_name     = "";
        empire         = 0;
        mapIndex     = 0;

        x = 0;
        y = 0;
    }
    GotoInfo(const GotoInfo& c_src)
    {
        __copy__(c_src);
    }
    void operator = (const GotoInfo& c_src)
    {
        __copy__(c_src);
    }
    void __copy__(const GotoInfo& c_src)
    {
        st_name     = c_src.st_name;
        empire         = c_src.empire;
        mapIndex     = c_src.mapIndex;

        x = c_src.x;
        y = c_src.y;
    }
};

Altına ekle:
// =========================================================
// FULL_SET Inventory Fit Simulation
// =========================================================
static bool FullSet_CanPlaceAt(const std::vector<bool>& occ, int cell, int size)
{
    if (size <= 0)
        size = 1;

    const int kCols = 5;
    const int kRows = INVENTORY_MAX_NUM / kCols;

    const int x = cell % kCols;
    const int y = cell / kCols;

    if (x < 0 || x >= kCols || y < 0 || y >= kRows)
        return false;

    if (y + size > kRows)
        return false;

    for (int dy = 0; dy < size; ++dy)
    {
        const int idx = cell + (dy * kCols);
        if (idx < 0 || idx >= INVENTORY_MAX_NUM)
            return false;
        if (occ[idx])
            return false;
    }

    return true;
}

static void FullSet_MarkAt(std::vector<bool>& occ, int cell, int size)
{
    if (size <= 0)
        size = 1;

    const int kCols = 5;
    for (int dy = 0; dy < size; ++dy)
    {
        const int idx = cell + (dy * kCols);
        if (idx >= 0 && idx < INVENTORY_MAX_NUM)
            occ[idx] = true;
    }
}

static bool FullSet_CanFitUnequippedWearItems(LPCHARACTER ch)
{
    if (!ch)
        return false;

    std::vector<bool> occ(INVENTORY_MAX_NUM, false);

    // Mevcut envanter doluluğunu footprint üzerinden işaretle
    for (int i = 0; i < INVENTORY_MAX_NUM; ++i)
    {
        LPITEM it = ch->GetInventoryItem(i);
        if (!it)
            continue;

        FullSet_MarkAt(occ, i, it->GetSize());
    }

    // Üzerindeki eşyaları envantere yerleştirme simülasyonu
    for (int wear = 0; wear < WEAR_MAX_NUM; ++wear)
    {
        LPITEM w = ch->GetWear(wear);
        if (!w)
            continue;

        const int sz = w->GetSize();
        bool placed = false;

        for (int cell = 0; cell < INVENTORY_MAX_NUM; ++cell)
        {
            if (FullSet_CanPlaceAt(occ, cell, sz))
            {
                FullSet_MarkAt(occ, cell, sz);
                placed = true;
                break;
            }
        }

        if (!placed)
            return false;
    }

    return true;
}

static bool FullSet_SafeEquipSpawnedItem(LPCHARACTER ch, LPITEM item)
{
    if (!ch || !item)
        return false;

    const int cell = item->FindEquipCell(ch);
    if (cell < 0)
    {
        sys_err("FULL_SET: FindEquipCell failed. ch=%s(%u) item=%s(#%u)",
            ch->GetName(), ch->GetPlayerID(), item->GetName(), item->GetID());
        M2_DESTROY_ITEM(item);
        return false;
    }

    if (ch->GetWear(cell) != NULL)
    {
        sys_err("FULL_SET: Wear slot already occupied during safe equip. ch=%s(%u) cell=%d existing=%s(#%u) new=%s(#%u)",
            ch->GetName(), ch->GetPlayerID(), cell,
            ch->GetWear(cell)->GetName(), ch->GetWear(cell)->GetID(),
            item->GetName(), item->GetID());
        M2_DESTROY_ITEM(item);
        return false;
    }

    if (!item->EquipTo(ch, cell))
    {
        sys_err("FULL_SET: EquipTo failed. ch=%s(%u) cell=%d item=%s(#%u)",
            ch->GetName(), ch->GetPlayerID(), cell, item->GetName(), item->GetID());
        M2_DESTROY_ITEM(item);
        return false;
    }

    return true;
}

static bool FullSet_UnequipAllWearToInventory(LPCHARACTER ch)
{
    if (!ch)
        return false;

    for (int wear = 0; wear < WEAR_MAX_NUM; ++wear)
    {
        LPITEM pItem = ch->GetWear(wear);
        if (!pItem)
            continue;

        const int pos = ch->GetEmptyInventory(pItem->GetSize());
        if (pos < 0)
        {
            sys_err("FullSet_UnequipAllWearToInventory: FULL_SET: Unexpected inventory full during unequip. ch=%s(%u) wear=%d item=%s(#%u)",
                ch->GetName(),
                ch->GetPlayerID(),
                wear,
                pItem->GetName(),
                pItem->GetID());
            return false;
        }

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

    return true;
}

Arat:
ACMD (do_full_set)

Değiştir:
ACMD (do_full_set)
{
    extern void do_all_skill_master(LPCHARACTER ch, const char *argument, int cmd, int subcmd);
    do_all_skill_master(ch, NULL, 0, 0);

    extern void do_item_full_set(LPCHARACTER ch, const char *argument, int cmd, int subcmd);
    do_item_full_set(ch, NULL, 0, 0);

    extern void do_attr_full_set(LPCHARACTER ch, const char *argument, int cmd, int subcmd);
    do_attr_full_set(ch, NULL, 0, 0);
}

ACMD (do_all_skill_master)
{
    ch->SetHorseLevel(SKILL_MAX_LEVEL);

    for (int i = 0; i < SKILL_MAX_NUM; i++)
    {
        if (true == ch->CanUseSkill(i))
        {
            ch->SetSkillLevel(i, SKILL_MAX_LEVEL);
        }
        else
        {
            switch (i)
            {
                case SKILL_HORSE_WILDATTACK:
                case SKILL_HORSE_CHARGE:
                case SKILL_HORSE_ESCAPE:
                case SKILL_HORSE_WILDATTACK_RANGE:
                    ch->SetSkillLevel(i, SKILL_MAX_LEVEL);
                    break;
            }
        }
    }

    ch->ComputePoints();
    ch->SkillLevelPacket();
}

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) Re-entrancy Guard
    // =========================================================
    if (ch->GetQuestFlag("full_set.is_running") != 0)
    {
        ch->ChatPacket(CHAT_TYPE_INFO, "<FULL_SET> İşlem hâlihazırda devam ediyor. Lütfen işlem tamamlandıktan sonra tekrar deneyiniz.");
        return;
    }

    // =========================================================
    // 3) 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);
    }

    // =========================================================
    // 4) Atomic Pre-check: Envanter yetmezse işlem başlayamaz
    // =========================================================
    int needNewItems = 0;
    switch (ch->GetJob())
    {
        case JOB_SURA:
        case JOB_WARRIOR:
        case JOB_SHAMAN:
        case JOB_ASSASSIN:
            needNewItems = 8;
            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;
    }

    int equippedCount = 0;
    for (int i = 0; i < WEAR_MAX_NUM; ++i)
    {
        if (ch->GetWear(i))
            ++equippedCount;
    }
    // =========================================================
    // 3) Inventory Fit Gate (grid-fit; sadece boş slot sayısı değil)
    // =========================================================
    if (!FullSet_CanFitUnequippedWearItems(ch))
    {
        ch->ChatPacket(CHAT_TYPE_INFO,
            "<FULL_SET> Envanterinizde yeterli alan yok (eşyalar sığmıyor). "
            "Lütfen envanterinizi düzenleyip boşlukları bir araya getirin ve tekrar deneyin.");
        return;
    }
// =========================================================
    // 5) Lock
    // =========================================================
    ch->SetQuestFlag("full_set.is_running", 1);

    // (A) Üzerindekileri sök
    if (!FullSet_UnequipAllWearToInventory(ch))
    {
        ch->SetQuestFlag("full_set.is_running", 0);
        ch->ChatPacket(CHAT_TYPE_INFO, "<FULL_SET> İşlem teknik bir nedenle tamamlanamadı. Lütfen tekrar deneyiniz.");
        return;
    }

    // (B) Yeni itemleri ret + equip
    bool ok = true;

    switch (ch->GetJob())
    {
        case JOB_SURA:
        {
            ok = ok && FullSet_SafeEquipSpawnedItem(ch, ITEM_MANAGER::instance().CreateItem(11699));
            ok = ok && FullSet_SafeEquipSpawnedItem(ch, ITEM_MANAGER::instance().CreateItem(13049));
            ok = ok && FullSet_SafeEquipSpawnedItem(ch, ITEM_MANAGER::instance().CreateItem(15189));
            ok = ok && FullSet_SafeEquipSpawnedItem(ch, ITEM_MANAGER::instance().CreateItem(189));
            ok = ok && FullSet_SafeEquipSpawnedItem(ch, ITEM_MANAGER::instance().CreateItem(12529));
            ok = ok && FullSet_SafeEquipSpawnedItem(ch, ITEM_MANAGER::instance().CreateItem(14109));
            ok = ok && FullSet_SafeEquipSpawnedItem(ch, ITEM_MANAGER::instance().CreateItem(17209));
            ok = ok && FullSet_SafeEquipSpawnedItem(ch, ITEM_MANAGER::instance().CreateItem(16209));
        }
        break;

        case JOB_WARRIOR:
        {
            ok = ok && FullSet_SafeEquipSpawnedItem(ch, ITEM_MANAGER::instance().CreateItem(11299));
            ok = ok && FullSet_SafeEquipSpawnedItem(ch, ITEM_MANAGER::instance().CreateItem(13049));
            ok = ok && FullSet_SafeEquipSpawnedItem(ch, ITEM_MANAGER::instance().CreateItem(15189));
            ok = ok && FullSet_SafeEquipSpawnedItem(ch, ITEM_MANAGER::instance().CreateItem(3159));
            ok = ok && FullSet_SafeEquipSpawnedItem(ch, ITEM_MANAGER::instance().CreateItem(12249));
            ok = ok && FullSet_SafeEquipSpawnedItem(ch, ITEM_MANAGER::instance().CreateItem(14109));
            ok = ok && FullSet_SafeEquipSpawnedItem(ch, ITEM_MANAGER::instance().CreateItem(17109));
            ok = ok && FullSet_SafeEquipSpawnedItem(ch, ITEM_MANAGER::instance().CreateItem(16109));
        }
        break;

        case JOB_SHAMAN:
        {
            ok = ok && FullSet_SafeEquipSpawnedItem(ch, ITEM_MANAGER::instance().CreateItem(11899));
            ok = ok && FullSet_SafeEquipSpawnedItem(ch, ITEM_MANAGER::instance().CreateItem(13049));
            ok = ok && FullSet_SafeEquipSpawnedItem(ch, ITEM_MANAGER::instance().CreateItem(15189));
            ok = ok && FullSet_SafeEquipSpawnedItem(ch, ITEM_MANAGER::instance().CreateItem(7159));
            ok = ok && FullSet_SafeEquipSpawnedItem(ch, ITEM_MANAGER::instance().CreateItem(12669));
            ok = ok && FullSet_SafeEquipSpawnedItem(ch, ITEM_MANAGER::instance().CreateItem(14109));
            ok = ok && FullSet_SafeEquipSpawnedItem(ch, ITEM_MANAGER::instance().CreateItem(17209));
            ok = ok && FullSet_SafeEquipSpawnedItem(ch, ITEM_MANAGER::instance().CreateItem(16209));
        }
        break;

        case JOB_ASSASSIN:
        {
            ok = ok && FullSet_SafeEquipSpawnedItem(ch, ITEM_MANAGER::instance().CreateItem(11499));
            ok = ok && FullSet_SafeEquipSpawnedItem(ch, ITEM_MANAGER::instance().CreateItem(13049));
            ok = ok && FullSet_SafeEquipSpawnedItem(ch, ITEM_MANAGER::instance().CreateItem(15189));
            ok = ok && FullSet_SafeEquipSpawnedItem(ch, ITEM_MANAGER::instance().CreateItem(1139));
            ok = ok && FullSet_SafeEquipSpawnedItem(ch, ITEM_MANAGER::instance().CreateItem(12389));
            ok = ok && FullSet_SafeEquipSpawnedItem(ch, ITEM_MANAGER::instance().CreateItem(14109));
            ok = ok && FullSet_SafeEquipSpawnedItem(ch, ITEM_MANAGER::instance().CreateItem(17189));
            ok = ok && FullSet_SafeEquipSpawnedItem(ch, ITEM_MANAGER::instance().CreateItem(16189));
        }
        break;
    }

    // (C) Unlock
    ch->SetQuestFlag("full_set.is_running", 0);

    if (!ok)
    {
        ch->ChatPacket(CHAT_TYPE_INFO, "<FULL_SET> İşlem tamamlanamadı. Ekipman tesliminde beklenmeyen bir hata oluştu. Lütfen logları kontrol ediniz.");
        sys_err("FULL_SET: Completed with failures. ch=%s(%u) job=%d", ch->GetName(), ch->GetPlayerID(), ch->GetJob());
        return;
    }

    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());
}

ACMD (do_attr_full_set)
{
    BYTE job = ch->GetJob();
    LPITEM item;

    switch (job)
    {
        case JOB_WARRIOR:
        case JOB_ASSASSIN:
        case JOB_SURA:
        case JOB_SHAMAN:
        {
            item = ch->GetWear(WEAR_HEAD);
            if (item != NULL)
            {
                item->ClearAttribute();
                item->SetForceAttribute(0, APPLY_ATT_SPEED, 8);
                item->SetForceAttribute(1, APPLY_HP_REGEN, 30);
                item->SetForceAttribute(2, APPLY_SP_REGEN, 30);
                item->SetForceAttribute(3, APPLY_DODGE, 15);
                item->SetForceAttribute(4, APPLY_STEAL_SP, 10);
            }

            item = ch->GetWear(WEAR_WEAPON);
            if (item != NULL)
            {
                item->ClearAttribute();
                item->SetForceAttribute(0, APPLY_CAST_SPEED, 20);
                item->SetForceAttribute(1, APPLY_CRITICAL_PCT, 10);
                item->SetForceAttribute(2, APPLY_PENETRATE_PCT, 10);
                item->SetForceAttribute(3, APPLY_ATTBONUS_DEVIL, 20);
                item->SetForceAttribute(4, APPLY_STR, 12);
            }

            item = ch->GetWear(WEAR_SHIELD);
            if (item != NULL)
            {
                item->ClearAttribute();
                item->SetForceAttribute(0, APPLY_CON, 12);
                item->SetForceAttribute(1, APPLY_BLOCK, 15);
                item->SetForceAttribute(2, APPLY_REFLECT_MELEE, 10);
                item->SetForceAttribute(3, APPLY_IMMUNE_STUN, 1);
                item->SetForceAttribute(4, APPLY_IMMUNE_SLOW, 1);
            }

            item = ch->GetWear(WEAR_BODY);
            if (item != NULL)
            {
                item->ClearAttribute();
                item->SetForceAttribute(0, APPLY_MAX_HP, 2000);
                item->SetForceAttribute(1, APPLY_CAST_SPEED, 20);
                item->SetForceAttribute(2, APPLY_STEAL_HP, 10);
                item->SetForceAttribute(3, APPLY_REFLECT_MELEE, 10);
                item->SetForceAttribute(4, APPLY_ATT_GRADE_BONUS, 50);
            }

            item = ch->GetWear(WEAR_FOOTS);
            if (item != NULL)
            {
                item->ClearAttribute();
                item->SetForceAttribute(0, APPLY_MAX_HP, 2000);
                item->SetForceAttribute(1, APPLY_MAX_SP, 80);
                item->SetForceAttribute(2, APPLY_MOV_SPEED, 8);
                item->SetForceAttribute(3, APPLY_ATT_SPEED, 8);
                item->SetForceAttribute(4, APPLY_CRITICAL_PCT, 10);
            }

            item = ch->GetWear(WEAR_WRIST);
            if (item != NULL)
            {
                item->ClearAttribute();
                item->SetForceAttribute(0, APPLY_MAX_HP, 2000);
                item->SetForceAttribute(1, APPLY_MAX_SP, 80);
                item->SetForceAttribute(2, APPLY_PENETRATE_PCT, 10);
                item->SetForceAttribute(3, APPLY_STEAL_HP, 10);
                item->SetForceAttribute(4, APPLY_MANA_BURN_PCT, 10);
            }

            item = ch->GetWear(WEAR_NECK);
            if (item != NULL)
            {
                item->ClearAttribute();
                item->SetForceAttribute(0, APPLY_MAX_HP, 2000);
                item->SetForceAttribute(1, APPLY_MAX_SP, 80);
                item->SetForceAttribute(2, APPLY_CRITICAL_PCT, 10);
                item->SetForceAttribute(3, APPLY_PENETRATE_PCT, 10);
                item->SetForceAttribute(4, APPLY_STEAL_SP, 10);
            }

            item = ch->GetWear(WEAR_EAR);
            if (item != NULL)
            {
                item->ClearAttribute();
                item->SetForceAttribute(0, APPLY_MOV_SPEED, 20);
                item->SetForceAttribute(1, APPLY_MANA_BURN_PCT, 10);
                item->SetForceAttribute(2, APPLY_POISON_REDUCE, 5);
                item->SetForceAttribute(3, APPLY_ATTBONUS_DEVIL, 20);
                item->SetForceAttribute(4, APPLY_ATTBONUS_UNDEAD, 20);
            }
        }
        break;
    }
}

NOT2:
Genişlet Daralt Kopyala
Uyumsuzluk yaşarsanız dosyalarınıza entegre edininiz! 
Invalid Socket Count 3, set to maximum hatası giderildi.
Eski yaptığınız char_item.cpp ve item.cpp' deki değişiklikler kalsın.
 
Geri
Üst