CUser::AddApplySkillBuff(user, skill);
	auto charName = args.at(0);  // character name
    auto skillId = std::stoi(args.at(1));
    auto skillLevel = std::stoi(args.at(2));
    auto user = CWorld::FindUser(charName.c_str());
    if (!user) {
        std::stringstream output_format;
        output_format << "Character " << charName << " not found";
        output = output_format.str();
        return 0; // Exit if user is not found
    }
    auto skill = CGameData::GetSkillInfo(skillId, skillLevel);
    if (!skill) {
        std::stringstream output_format;
        output_format << "Skill with ID " << skillId << " and level " << skillLevel << " not found";
        output = output_format.str();
        return 0; // Exit if skill is not found
    }
    // Prepare the SkillUseOutgoing packet
    SkillUseOutgoing outgoing{};
    outgoing.senderId = user->connection.object.id;
    outgoing.targetId = user->connection.object.id;
    outgoing.skillId = skill->skillId;
    outgoing.skillLv = skill->skillLv;
    // Send the skill usage packet to the user
    Helpers::Send(user, &outgoing, sizeof(SkillUseOutgoing));
    // Apply the skill buff
    CUser::AddApplySkillBuff(user, skill);
    EnterCriticalSection(&user->applySkills.cs);
    // Start from the first node after the sentinel tail
    auto node = user->applySkills.sentinel.tail;
    node = node->next;  // Move to the first node
    user->applySkills.sentinel.head = node;
    int index = 0; // Index to track the skill position in the list
    bool skillFound = false;
    while (node && node != user->applySkills.sentinel.tail)
    {
        auto skillIn = reinterpret_cast<CSkill*>(node);
        // Check if the skill matches
        if (skillIn->skillId == skill->skillId && skillIn->skillLv == skill->skillLv)
        {
            skillFound = true;
            // Correctly set the id for addBuff
            SkillApplyOutgoing addBuff{};
            addBuff.id = index; // Send the matching skill's index
            addBuff.skillId = skill->skillId;
            addBuff.skillLv = skill->skillLv;
            Helpers::Send(user, &addBuff, sizeof(SkillApplyOutgoing));
            break;
        }
        node = node->next;  // Move to the next node
        user->applySkills.sentinel.head = node;
        index++; // Increment index
    }
    LeaveCriticalSection(&user->applySkills.cs);
    if (!skillFound)
    {
        std::stringstream output_format;
        output_format << "Skill " << skillId << " (Level " << skillLevel << ") could not be applied for " << charName;
        output = output_format.str();
        return 0; // Exit after reporting error
    }
    // Output a success message
    std::stringstream output_format;
    output_format << "Skill " << skillId << " (Level " << skillLevel << ") triggered for " << charName;
    output = output_format.str();
    return 0;
	Skill 287 (Level 1) could not be applied for Character
	I don't see it sending that packet.Will this sends Packet 0x50D on its own or do I have to do it by myself?
auto charName = args.at(0);  // character name
auto skillId = std::stoi(args.at(1));
auto skillLevel = std::stoi(args.at(2));
auto user = CWorld::FindUser(charName.c_str());
if (!user) {
    std::stringstream output_format;
    output_format << "Character " << charName << " not found";
    output = output_format.str();
    return 0; // Exit if user is not found
}
auto skill = CGameData::GetSkillInfo(skillId, skillLevel);
if (!skill) {
    std::stringstream output_format;
    output_format << "Skill with ID " << skillId << " and level " << skillLevel << " not found";
    output = output_format.str();
    return 0; // Exit if skill is not found
}
if (!CUser::UseItemSkill(user, skill)) {
    std::stringstream output_format;
    output_format << "Skill " << skillId << " (Level " << skillLevel << ") could not be applied for " << charName;
    output = output_format.str();
    return 0; // Exit after reporting error
}
// Output a success message
std::stringstream output_format;
output_format << "Skill " << skillId << " (Level " << skillLevel << ") triggered for " << charName;
output = output_format.str();
return 0;
	
void item_remake_handler(CUser* user, ItemRemakeIncoming* incoming)
{
}
	pushad
push esi // packet
push edi // user
call item_remake_handler
add esp,0x8
popad
jmp u0x47A018
	如何操作?我以为该文件已附加到我的上一条消息中。![]()
我现在可以把它放进去并使用它吗?我们还需要调试吗?[用户=129]@nurum[/用户]
这是我删除之前 repo 中的源代码。
void item_remake_handler(CUser* user, ItemRemakeIncoming* incoming) {
    // Check items in the specified slots
    auto* item1 = user->inventory[incoming->bag1][incoming->slot1];
    auto* item2 = user->inventory[incoming->bag2][incoming->slot2];
    auto* item3 = user->inventory[incoming->bag3][incoming->slot3];
    // Ensure all items are present
    if (!item1 || !item2 || !item3) {
        Helpers::SendNotice("LOG: One or more items are missing.");
        return;
    }
    // Ensure all items have the same ID
    if (item1->itemInfo->itemId != item2->itemInfo->itemId ||
        item1->itemInfo->itemId != item3->itemInfo->itemId) {
        Helpers::SendNotice("LOG: Items do not match.");
        return;
    }
    // Handle specific item creation
    ItemInfo* resultItem = nullptr;
    if (item1->itemInfo->itemId == 72001) {
        int resultType = 72;
        int resultTypeId = 2;
        resultItem = CGameData::GetItemInfo(resultType, resultTypeId);
        if (resultItem) {
            std::string resultLog = "LOG: Created result item with Type: " +
            std::to_string(resultType) + ", TypeID: " + std::to_string(resultTypeId);
            Helpers::SendNotice(resultLog.c_str());
        }
        else {
            Helpers::SendNotice("LOG: Failed to create result item.");
            return;
        }
    }
    else {
        Helpers::SendNotice("LOG: Item ID does not match special handling conditions.");
        ItemRemakeOutgoing outgoing{};
        outgoing.result = ItemRemakeResult::Failure;
        Helpers::Send(user, &outgoing, sizeof(ItemRemakeOutgoing));
        return;
    }
    
    uint8_t bag = 1; // Result item bag
    uint8_t slot = -1; // Result item slot
    while (bag <= user->bagsUnlocked) {
        slot = Helpers::GetFreeItemSlot(user, bag);
        if (slot != -1) {
            if (CUser::ItemCreate(user, resultItem, 1)) {
                break;
            }
        }
        ++bag;
    }
    // Validate the resulting item placement
    auto* findResult = user->inventory[bag][slot];
    if (!findResult) {
        Helpers::SendNotice("LOG: Result item was not created.");
        return;
    }
    // Transfer the details of the first item to the result
    findResult->gems = item1->gems;
    findResult->craftName = item1->craftName;
    findResult->quality = item1->quality;
    // Assign the findResult back to the inventory
    user->inventory[bag][slot] = findResult;
    //Log the inventory[bag][slot] if already have its gems, craftname and quality
    Helpers::ItemRemove(user, item1->itemInfo->itemId, 1);
    Helpers::ItemRemove(user, item2->itemInfo->itemId, 1);
    Helpers::ItemRemove(user, item3->itemInfo->itemId, 1);
    // Send outgoing packet with result details
    ItemRemakeOutgoing outgoing{};
    outgoing.result = ItemRemakeResult::Success;
    outgoing.bag = bag;
    outgoing.slot = slot;
    outgoing.type = resultItem->type;
    outgoing.typeId = resultItem->typeId;
    outgoing.gems = findResult->gems;
    outgoing.count = findResult->count;
    outgoing.craftName = findResult->craftName;
    Helpers::Send(user, &outgoing, sizeof(ItemRemakeOutgoing));
    GameLogItemRemakeIncoming remakeLog(user, findResult, item1->uniqueId, item2->uniqueId, item3->uniqueId);
    Helpers::SendGameLog(&remakeLog, sizeof(GameLogItemRemakeIncoming));
    Helpers::SendNotice("LOG: Handler completed successfully.");
}
	Can I ask why the item gems, craftname and quality is not persistent?
输入:加我QQ:592372215 加的时候备注下有人卖光环效果吗?
It's a shame it was removed
Any idea on how to handle different item type/typeids for each of the 3 slots ? For example, when I put 3 same items my packet handler is executed but if I put 3 different items nothing happens.You have to send a packet to the dbAgent service.Looks like the remake function sends 0x701. I added it to the library.
Please add range checks for the bags and slots.
Edit: sending 0x711 and 0x717 to the dbAgent service resolved the issue.