• There is NO official Otland's Discord server and NO official Otland's server list. The Otland's Staff does not manage any Discord server or server list. Moderators or administrator of any Discord server or server lists have NO connection to the Otland's Staff. Do not get scammed!

Store inbox problem

Rycina

Member
Joined
Nov 7, 2024
Messages
59
Solutions
1
Reaction score
8
Hi :)

TFS 1.4.2 otcv8

The question is, which code in the Store can be responsible for where to send purchased items? Currently, everything is sent to Backpack, and I would like it to go to the store inbox :D

I have a store like this, everyone knows who I'm talking about.

Peace, brother ✌️
 
Show the code so we can edit it

"I have a store like this, everyone knows who I'm talking about."
Probably is it: (the whole code would be too long to post)

local item = player:getSlotItem(CONST_SLOT_BACKPACK)



LUA:
function defaultItemCallback(player, offer)
    local weight = ItemType(offer.itemId):getWeight(offer.count)
    if player:getFreeCapacity() < weight then
        return "This item is too heavy for you!"
    end

     local item = player:getSlotItem(CONST_SLOT_BACKPACK)
    if not item then
        return "You don't have enough space in backpack."
    end
    local slots = item:getEmptySlots(true)
    if slots <= 0 then
        return "You don't have enough space in backpack."
    end

    if player:addItem(offer.itemId, offer.count, false) then
        return true
    end

    return "Something went wrong, item couldn't be added."
end

function defaultOutfitCallback(player, offer)
    if offer.outfitMale.addons > 0 then
        if player:hasOutfit(offer.outfitMale.type, offer.outfitMale.addons) then
            return "You already have this outfit with addons."
        end

        player:addOutfitAddon(offer.outfitMale.type, offer.outfitMale.addons)
    else
        if player:hasOutfit(offer.outfitMale.type) then
            return "You already have this outfit."
        end

        player:addOutfit(offer.outfitMale.type)
    end
    if offer.outfitFemale.addons > 0 then
        player:addOutfitAddon(offer.outfitFemale.type, offer.outfitFemale.addons)
    else
        player:addOutfit(offer.outfitFemale.type)
    end
    return true
end

function defaultMountCallback(player, offer)
    if player:hasMount(offer.mount) then
        return "You already have this mount."
    end

    player:addMount(offer.mount)
    return true
end

function refreshPlayersPoints()
    for _, p in ipairs(Game.getPlayers()) do
        if p:getIp() > 0 then
            gameStoreUpdatePoints(p)
        end
    end
    addEvent(refreshPlayersPoints, 10 * 1000)
end

LoginEvent:type("login")
LoginEvent:register()
ExtendedEvent:type("extendedopcode")
ExtendedEvent:register()
 
these lines.
LUA:
function defaultItemCallback(player, offer)
    local weight = ItemType(offer.itemId):getWeight(offer.count)
    if player:getFreeCapacity() < weight then
        return "This item is too heavy for you!"
    end

     local item = player:getSlotItem(CONST_SLOT_BACKPACK)
    if not item then
        return "You don't have enough space in backpack."
    end
    local slots = item:getEmptySlots(true)
    if slots <= 0 then
        return "You don't have enough space in backpack."
    end

    if player:addItem(offer.itemId, offer.count, false) then
        return true
    end

    return "Something went wrong, item couldn't be added."
end

change to.

LUA:
function defaultItemCallback(player, offer)
    if player:getFreeCapacity() < ItemType(offer.itemId):getWeight(offer.count) then
        return "This item is too heavy for you!"
    end

    local storeInbox = player:getStoreInbox()
    if not storeInbox then
        return "Store Inbox is not available for your character."
    end

    local item = Game.createItem(offer.itemId, offer.count)
    if not item then
        return "Something went wrong, item couldn't be created."
    end

    item:setStoreItem(true)
    local result = storeInbox:addItemEx(item)
    item:setStoreItem(false)
    if result == RETURNVALUE_NOERROR then
        return true
    elseif result == RETURNVALUE_CONTAINERNOTENOUGHROOM then
        return "Your Store Inbox is full. Please remove some items to receive new ones."
    else
        return "Something went wrong, item couldn't be added."
    end
end
 
Solved! :) Thanks you :)
Post automatically merged:

these lines.
LUA:
function defaultItemCallback(player, offer)
    local weight = ItemType(offer.itemId):getWeight(offer.count)
    if player:getFreeCapacity() < weight then
        return "This item is too heavy for you!"
    end

     local item = player:getSlotItem(CONST_SLOT_BACKPACK)
    if not item then
        return "You don't have enough space in backpack."
    end
    local slots = item:getEmptySlots(true)
    if slots <= 0 then
        return "You don't have enough space in backpack."
    end

    if player:addItem(offer.itemId, offer.count, false) then
        return true
    end

    return "Something went wrong, item couldn't be added."
end

change to.

LUA:
function defaultItemCallback(player, offer)
    if player:getFreeCapacity() < ItemType(offer.itemId):getWeight(offer.count) then
        return "This item is too heavy for you!"
    end

    local storeInbox = player:getStoreInbox()
    if not storeInbox then
        return "Store Inbox is not available for your character."
    end

    local item = Game.createItem(offer.itemId, offer.count)
    if not item then
        return "Something went wrong, item couldn't be created."
    end

    item:setStoreItem(true)
    local result = storeInbox:addItemEx(item)
    item:setStoreItem(false)
    if result == RETURNVALUE_NOERROR then
        return true
    elseif result == RETURNVALUE_CONTAINERNOTENOUGHROOM then
        return "Your Store Inbox is full. Please remove some items to receive new ones."
    else
        return "Something went wrong, item couldn't be added."
    end
end
but problem with mounts now :(

LUA:
[Error - mysql_real_query] Query: INSERT INTO `player_inboxitems` (`player_id`, `pid`, `sid`, `itemtype`, `count`, `attributes`) VALUES (1, 0, 101, 26387, 1, '%\0'),(1, 0, 102, 26387, 1, '%\0')
Message: Duplicate entry '1-101' for key 'player_inboxitems.player_id_2'

and outfit


LUA:
Lua Script Error: [Scripts Interface]
C:\forgottenserver-1.4.2\Eternia\data\scripts\game_store.lua:callback
...enserver-1.4.2\Eternia\data\scripts\store\game_store.lua:1630: attempt to compare number with nil
stack traceback:
        [C]: in function '__lt'
        ...enserver-1.4.2\Eternia\data\scripts\store\game_store.lua:1630: in function 'callback'
        ...enserver-1.4.2\Eternia\data\scripts\store\game_store.lua:1285: in function 'gameStorePurchase'
        ...orgottenserver-1.4.2\Eternia\data\scripts\game_store.lua:622: in function <...orgottenserver-1.4.2\Eternia\data\scripts\game_store.lua:596>

When i want buy for me or gift


LUA:
local ExtendedEvent = CreatureEvent("GameStoreExtended")

function ExtendedEvent.onExtendedOpcode(player, opcode, buffer)
    if opcode == CODE_GAMESTORE then
        if not GAME_STORE then
            gameStoreInitialize()
            addEvent(refreshPlayersPoints, 10 * 1000)
        end

        local status, json_data =
            pcall(
            function()
                return json.decode(buffer)
            end
        )
        if not status then
            return
        end

        local action = json_data.action
        local data = json_data.data
        if not action or not data then
            return
        end

        if action == "fetch" then
            gameStoreFetch(player)
        elseif action == "purchase" then
            gameStorePurchase(player, data)
        elseif action == "gift" then
            gameStorePurchaseGift(player, data)
        end
    end
end

function gameStoreFetch(player)
    local sex = player:getSex()

    player:sendExtendedOpcode(CODE_GAMESTORE, json.encode({action = "fetchBase", data = {categories = GAME_STORE.categories, url = DONATION_URL}}))

    for category, offersTable in pairs(GAME_STORE.offers) do
        local offers = {}

        for i = 1, #offersTable do
            local offer = offersTable[i]
            local data = {
                type = offer.type,
                title = offer.title,
                description = offer.description,
                price = offer.price
            }

            if offer.count then
                data.count = offer.count
            end
            if offer.clientId then
                data.clientId = offer.clientId
            end
        
            if sex == PLAYERSEX_MALE then
                if offer.outfitMale then
                    data.outfit = offer.outfitMale
                end
            else
                if offer.outfitFemale then
                    data.outfit = offer.outfitFemale
                end
            end
            if offer.data then
                data.data = offer.data
            end
            table.insert(offers, data)
        end
        player:sendExtendedOpcode(CODE_GAMESTORE, json.encode({action = "fetchOffers", data = {category = category, offers = offers}}))
    end

    gameStoreUpdatePoints(player)
    gameStoreUpdateHistory(player)
end

function gameStoreUpdatePoints(player)
    if type(player) == "number" then
        player = Player(player)
    end
    player:sendExtendedOpcode(CODE_GAMESTORE, json.encode({action = "points", data = getPoints(player)}))
end

function gameStoreUpdateHistory(player)
    if type(player) == "number" then
        player = Player(player)
    end
    local history = {}
    local resultId = db.storeQuery("SELECT * FROM `shop_history` WHERE `account` = " .. player:getAccountId() .. " order by `id` DESC")

    if resultId ~= false then
        repeat
            local desc = "Bought " .. result.getDataString(resultId, "title")
            local count = result.getDataInt(resultId, "count")
            if count > 0 then
                desc = desc .. " (x" .. count .. ")"
            end
            local target = result.getDataString(resultId, "target")
            if target ~= "" then
                desc = desc .. " on " .. result.getDataString(resultId, "date") .. " for " .. target .. " for " .. result.getDataInt(resultId, "price") .. " points."
            else
                desc = desc .. " on " .. result.getDataString(resultId, "date") .. " for " .. result.getDataInt(resultId, "price") .. " points."
            end
            table.insert(history, desc)
        until not result.next(resultId)
        result.free(resultId)
    end
    player:sendExtendedOpcode(CODE_GAMESTORE, json.encode({action = "history", data = history}))
end

function gameStorePurchase(player, offer)
    local offers = GAME_STORE.offers[offer.category]
    if not offers then
        return errorMsg(player, "Something went wrong, try again or contact server admin [#1]!")
    end
    for i = 1, #offers do
        if offers[i].title == offer.title and offers[i].price == offer.price then
            local callback = offers[i].callback
            if not callback then
                return errorMsg(player, "Something went wrong, try again or contact server admin [#2]!")
            end

            local points = getPoints(player)
            if offers[i].price > points then
                return errorMsg(player, "You don't have enough points!")
            end

            local status = callback(player, offers[i])
            if status ~= true then
                return errorMsg(player, status)
            end

            local aid = player:getAccountId()
            local escapeTitle = db.escapeString(offers[i].title)
            local escapePrice = db.escapeString(offers[i].price)
            local escapeCount = offers[i].count and db.escapeString(offers[i].count) or 0

            db.query("UPDATE `accounts` set `premium_points` = `premium_points` - " .. offers[i].price .. " WHERE `id` = " .. aid)
            db.asyncQuery(
                "INSERT INTO `shop_history` VALUES (NULL, '" ..
                    aid .. "', '" .. player:getGuid() .. "', NOW(), " .. escapeTitle .. ", " .. escapePrice .. ", " .. escapeCount .. ", NULL)"
            )
            addEvent(gameStoreUpdateHistory, 1000, player:getId())
            addEvent(gameStoreUpdatePoints, 1000, player:getId())
            return infoMsg(player, "You've bought " .. offers[i].title .. "!", true)
        end
    end
    return errorMsg(player, "Something went wrong, try again or contact server admin [#4]!")
end

function gameStorePurchaseGift(player, offer)
    local offers = GAME_STORE.offers[offer.category]
    if not offers then
        return errorMsg(player, "Something went wrong, try again or contact server admin [#1]!")
    end
    if not offer.target then
        return errorMsg(player, "Target player not found!")
    end
    for i = 1, #offers do
        if offers[i].title == offer.title and offers[i].price == offer.price then
            local callback = offers[i].callback
            if not callback then
                return errorMsg(player, "Something went wrong, try again or contact server admin [#2]!")
            end

            local points = getPoints(player)
            if offers[i].price > points then
                return errorMsg(player, "You don't have enough points!")
            end

            local targetPlayer = Player(offer.target)
            if not targetPlayer then
                return errorMsg(player, "Target player not found!")
            end

            local status = callback(targetPlayer, offers[i])
            if status ~= true then
                return errorMsg(player, status)
            end

            local aid = player:getAccountId()
            local escapeTitle = db.escapeString(offers[i].title)
            local escapePrice = db.escapeString(offers[i].price)
            local escapeCount = offers[i].count and db.escapeString(offers[i].count) or 0
            local escapeTarget = db.escapeString(targetPlayer:getName())
            db.query("UPDATE `accounts` set `premium_points` = `premium_points` - " .. offers[i].price .. " WHERE `id` = " .. aid)
            db.asyncQuery(
                "INSERT INTO `shop_history` VALUES (NULL, '" ..
                    aid .. "', '" .. player:getGuid() .. "', NOW(), " .. escapeTitle .. ", " .. escapePrice .. ", " .. escapeCount .. ", " .. escapeTarget .. ")"
            )
            addEvent(gameStoreUpdateHistory, 1000, player:getId())
            addEvent(gameStoreUpdatePoints, 1000, player:getId())
            return infoMsg(player, "You've bought " .. offers[i].title .. " for " .. targetPlayer:getName() .. "!", true)
        end
    end
    return errorMsg(player, "Something went wrong, try again or contact server admin [#4]!")
end

function getPoints(player)
    local points = 0
    local resultId = db.storeQuery("SELECT `premium_points` FROM `accounts` WHERE `id` = " .. player:getAccountId())
    if resultId ~= false then
        points = result.getDataInt(resultId, "premium_points")
        result.free(resultId)
    end
    return points
end

function errorMsg(player, msg)
    player:sendExtendedOpcode(CODE_GAMESTORE, json.encode({action = "msg", data = {type = "error", msg = msg}}))
end

function infoMsg(player, msg, close)
    if not close then
        close = false
    end
    player:sendExtendedOpcode(CODE_GAMESTORE, json.encode({action = "msg", data = {type = "info", msg = msg, close = close}}))
end

function addCategory(title, description, iconType, iconData)
    if iconType == "item" then
        iconData = ItemType(iconData):getClientId()
    end

    table.insert(
        GAME_STORE.categories,
        {
            title = title,
            description = description,
            iconType = iconType,
            iconData = iconData
        }
    )
end

function addItem(category, title, description, itemId, count, price, callback)
    if not GAME_STORE.offers[category] then
        GAME_STORE.offers[category] = {}
    end

    if not callback then
        callback = defaultItemCallback
    end

    table.insert(
        GAME_STORE.offers[category],
        {
            type = "item",
            title = title,
            description = description,
            itemId = itemId,
            count = count,
            price = price,
            clientId = ItemType(itemId):getClientId(),
            callback = callback
        }
    )
end

function addOutfit(category, title, description, outfitMale, outfitFemale, price, callback)
    if not GAME_STORE.offers[category] then
        GAME_STORE.offers[category] = {}
    end

    if not callback then
        callback = defaultOutfitCallback
    end

    table.insert(
        GAME_STORE.offers[category],
        {
            type = "outfit",
            title = title,
            description = description,
            outfitMale = outfitMale,
            outfitFemale = outfitFemale,
            price = price,
            callback = callback
        }
    )
end

function addShader(category, title, description, outfitMale, outfitFemale, price, callback)
    if not GAME_STORE.offers[category] then
        GAME_STORE.offers[category] = {}
    end

    if not callback then
        callback = defaultShaderCallback
    end

    table.insert(
        GAME_STORE.offers[category],
        {
            type = "outfit",
            title = title,
            description = description,
            outfitMale = outfitMale,
            outfitFemale = outfitFemale,
            price = price,
            callback = callback
        }
    )
end

function defaultShaderCallback(player, offer)
    if player:hasShader(offer.outfitMale.shader) then
        return "You already have this shader."
    end

    player:addShader(offer.outfitMale.shader)
    return true
end

function addMount(category, title, description, mountId, clientId, price, callback)
    if not GAME_STORE.offers[category] then
        GAME_STORE.offers[category] = {}
    end

    if not callback then
        callback = defaultMountCallback
    end

    table.insert(
        GAME_STORE.offers[category],
        {
            type = "mount",
            title = title,
            description = description,
            mount = mountId,
            clientId = clientId,
            price = price,
            callback = callback
        }
    )
end



function addWings(category, title, description, wingsId, clientId, price, callback)
    if not GAME_STORE.offers[category] then
        GAME_STORE.offers[category] = {}
    end

    if not callback then
        callback = defaultWingsCallback
    end

    table.insert(
        GAME_STORE.offers[category],
        {
            type = "wings",
            title = title,
            description = description,
            wings = wingsId,
            clientId = clientId,
            price = price,
            callback = callback
        }
    )
end

function addAura(category, title, description, auraId, clientId, price, callback)
    if not GAME_STORE.offers[category] then
        GAME_STORE.offers[category] = {}
    end

    if not callback then
        callback = defaultAuraCallback
    end

    table.insert(
        GAME_STORE.offers[category],
        {
            type = "aura",
            title = title,
            description = description,
            aura = auraId,
            clientId = clientId,
            price = price,
            callback = callback
        }
    )
end

function defaultWingsCallback(player, offer)
    if player:hasWings(offer.wings) then
        return "You already have these wings."
    end

    player:addWings(offer.wings)
    return true
end

function defaultAuraCallback(player, offer)
    if player:hasAura(offer.aura) then
        return "You already have this aura."
    end

    player:addAura(offer.aura)
    return true
end





function addCustom(category, type, title, description, data, count, price, callback)
    if not GAME_STORE.offers[category] then
        GAME_STORE.offers[category] = {}
    end

    if not callback then
        error("[Game Store] addCustom " .. title .. " without callback")
        return
    end

    table.insert(
        GAME_STORE.offers[category],
        {
            type = type,
            title = title,
            description = description,
            data = data,
            price = price,
            count = count,
            callback = callback
        }
    )
end

function defaultItemCallback(player, offer)
    if player:getFreeCapacity() < ItemType(offer.itemId):getWeight(offer.count) then
        return "This item is too heavy for you!"
    end

    local storeInbox = player:getStoreInbox()
    if not storeInbox then
        return "Store Inbox is not available for your character."
    end

    local item = Game.createItem(offer.itemId, offer.count)
    if not item then
        return "Something went wrong, item couldn't be created."
    end

    item:setStoreItem(true)
    local result = storeInbox:addItemEx(item)
    item:setStoreItem(false)
    if result == RETURNVALUE_NOERROR then
        return true
    elseif result == RETURNVALUE_CONTAINERNOTENOUGHROOM then
        return "Your Store Inbox is full. Please remove some items to receive new ones."
    else
        return "Something went wrong, item couldn't be added."
    end
end

function defaultOutfitCallback(player, offer)
    if offer.outfitMale.addons > 0 then
        if player:hasOutfit(offer.outfitMale.type, offer.outfitMale.addons) then
            return "You already have this outfit with addons."
        end

        player:addOutfitAddon(offer.outfitMale.type, offer.outfitMale.addons)
    else
        if player:hasOutfit(offer.outfitMale.type) then
            return "You already have this outfit."
        end

        player:addOutfit(offer.outfitMale.type)
    end
    if offer.outfitFemale.addons > 0 then
        player:addOutfitAddon(offer.outfitFemale.type, offer.outfitFemale.addons)
    else
        player:addOutfit(offer.outfitFemale.type)
    end
    return true
end

function defaultMountCallback(player, offer)
    if player:hasMount(offer.mount) then
        return "You already have this mount."
    end

    player:addMount(offer.mount)
    return true
end

function refreshPlayersPoints()
    for _, p in ipairs(Game.getPlayers()) do
        if p:getIp() > 0 then
            gameStoreUpdatePoints(p)
        end
    end
    addEvent(refreshPlayersPoints, 10 * 1000)
end

LoginEvent:type("login")
LoginEvent:register()
ExtendedEvent:type("extendedopcode")
ExtendedEvent:register()
 
Last edited:
up
Post automatically merged:

these lines.
LUA:
function defaultItemCallback(player, offer)
    local weight = ItemType(offer.itemId):getWeight(offer.count)
    if player:getFreeCapacity() < weight then
        return "This item is too heavy for you!"
    end

     local item = player:getSlotItem(CONST_SLOT_BACKPACK)
    if not item then
        return "You don't have enough space in backpack."
    end
    local slots = item:getEmptySlots(true)
    if slots <= 0 then
        return "You don't have enough space in backpack."
    end

    if player:addItem(offer.itemId, offer.count, false) then
        return true
    end

    return "Something went wrong, item couldn't be added."
end

change to.

LUA:
function defaultItemCallback(player, offer)
    if player:getFreeCapacity() < ItemType(offer.itemId):getWeight(offer.count) then
        return "This item is too heavy for you!"
    end

    local storeInbox = player:getStoreInbox()
    if not storeInbox then
        return "Store Inbox is not available for your character."
    end

    local item = Game.createItem(offer.itemId, offer.count)
    if not item then
        return "Something went wrong, item couldn't be created."
    end

    item:setStoreItem(true)
    local result = storeInbox:addItemEx(item)
    item:setStoreItem(false)
    if result == RETURNVALUE_NOERROR then
        return true
    elseif result == RETURNVALUE_CONTAINERNOTENOUGHROOM then
        return "Your Store Inbox is full. Please remove some items to receive new ones."
    else
        return "Something went wrong, item couldn't be added."
    end
end
I have problem with that.

When he buys an item, it goes to Inbox. However, when he logs out and logs back in, the item disappears from Inbox forever.
Post automatically merged:

After logging out it disappears from the inbox but goes to the inbox in the depot. I would like it to stay in the player's inbox
 
Last edited:
compare to newer version this file:
C++:
iologindata.cpp

in function
C++:
bool IOLoginData::loadPlayer(Player* player, DBResult_ptr result)
you are supposed to load the inbox items from database

in function
C++:
bool IOLoginData::savePlayer(Player* player)
you are supposed to save the inbox items to database
 
is that it? I have 10.98

LUA:
    //load inbox items
    itemMap.clear();
    if ((result = db.storeQuery(fmt::format("SELECT `pid`, `sid`, `itemtype`, `count`, `attributes` FROM `player_inboxitems` WHERE `player_id` = {:d} ORDER BY `sid` DESC", player->getGUID())))) {
        loadItems(itemMap, result);
        for (ItemMap::const_reverse_iterator it = itemMap.rbegin(), end = itemMap.rend(); it != end; ++it) {
            const std::pair<Item*, int32_t>& pair = it->second;
            Item* item = pair.first;
            int32_t pid = pair.second;
            if (pid >= 0 && pid < 100) {
                player->getInbox()->internalAddThing(item);
            } else {
                ItemMap::const_iterator it2 = itemMap.find(pid);
                if (it2 == itemMap.end()) {
                    continue;
                }
                Container* container = it2->second.first->getContainer();
                if (container) {
                    container->internalAddThing(item);
                }
            }
        }
    }
    //load store inbox items
    itemMap.clear();
    if ((result = db.storeQuery(fmt::format("SELECT `pid`, `sid`, `itemtype`, `count`, `attributes` FROM `player_storeinboxitems` WHERE `player_id` = {:d} ORDER BY `sid` DESC", player->getGUID())))) {
        loadItems(itemMap, result);
        for (ItemMap::const_reverse_iterator it = itemMap.rbegin(), end = itemMap.rend(); it != end; ++it) {
            const std::pair<Item*, int32_t>& pair = it->second;
            Item* item = pair.first;
            int32_t pid = pair.second;
            if (pid >= 0 && pid < 100) {
                player->getStoreInbox()->internalAddThing(item);
            } else {
                ItemMap::const_iterator it2 = itemMap.find(pid);
                if (it2 == itemMap.end()) {
                    continue;
                }
                Container* container = it2->second.first->getContainer();
                if (container) {
                    container->internalAddThing(item);
                }
            }
        }
    }

LUA:
    //save inbox items
    if (!db.executeQuery(fmt::format("DELETE FROM `player_inboxitems` WHERE `player_id` = {:d}", player->getGUID()))) {
        return false;
    }

    DBInsert inboxQuery("INSERT INTO `player_inboxitems` (`player_id`, `pid`, `sid`, `itemtype`, `count`, `attributes`) VALUES ");
    itemList.clear();

    for (Item* item : player->getInbox()->getItemList()) {
        itemList.emplace_back(0, item);
    }

    if (!saveItems(player, itemList, inboxQuery, propWriteStream, openContainers)) {
        return false;
    }

    //save store inbox items
    if (!db.executeQuery(fmt::format("DELETE FROM `player_storeinboxitems` WHERE `player_id` = {:d}", player->getGUID()))) {
        return false;
    }

    DBInsert storeInboxQuery("INSERT INTO `player_storeinboxitems` (`player_id`, `pid`, `sid`, `itemtype`, `count`, `attributes`) VALUES ");
    itemList.clear();

    for (Item* item : player->getStoreInbox()->getItemList()) {
        itemList.emplace_back(0, item);
    }

    if (!saveItems(player, itemList, inboxQuery, propWriteStream, openContainers)) {
        return false;
    }

    if (!db.executeQuery(fmt::format("DELETE FROM `player_storage` WHERE `player_id` = {:d}", player->getGUID()))) {
        return false;
    }

    DBInsert storageQuery("INSERT INTO `player_storage` (`player_id`, `key`, `value`) VALUES ");
    player->genReservedStorageRange();

    for (const auto& it : player->storageMap) {
        if (!storageQuery.addRow(fmt::format("{:d}, {:d}, {:d}", player->getGUID(), it.first, it.second))) {
            return false;
        }
    }

    if (!storageQuery.execute()) {
        return false;
    }

    //End the transaction
    return transaction.commit();
}
 
I've tried several ways but I'm doing something wrong.

Currently:
After buying an item in the store it's thrown into my Inbox (Good)

I want to take an item out of the Inbox to the Backpack or depot but I can't (bad)

I can throw an item from the Inbox back into the Inbox (bad) the Inbox should have a function to throw anything there blocked


Store:
LUA:
function defaultItemCallback(player, offer)
    if player:getFreeCapacity() < ItemType(offer.itemId):getWeight(offer.count) then
        return "This item is too heavy for you!"
    end

    local storeInbox = player:getStoreInbox()
    if not storeInbox then
        return "Store Inbox is not available for your character."
    end

    local item = Game.createItem(offer.itemId, offer.count)
    if not item then
        return "Something went wrong, item couldn't be created."
    end

    item:setStoreItem(true)
    local result = storeInbox:addItemEx(item)
    item:setStoreItem(false)
    if result == RETURNVALUE_NOERROR then
        return true
    elseif result == RETURNVALUE_CONTAINERNOTENOUGHROOM then
        return "Your Store Inbox is full. Please remove some items to receive new ones."
    else
        return "Something went wrong, item couldn't be added."
    end
end

Inbox.cpp:

Code:
// Copyright 2022 The Forgotten Server Authors. All rights reserved.
// Use of this source code is governed by the GPL-2.0 License that can be found in the LICENSE file.

#include "otpch.h"

#include "inbox.h"
#include "tools.h"

Inbox::Inbox(uint16_t type) : Container(type, 30, false, true) {}

ReturnValue Inbox::queryAdd(int32_t, const Thing& thing, uint32_t,
        uint32_t flags, Creature*) const
{
    if (!hasBitSet(FLAG_NOLIMIT, flags)) {
        return RETURNVALUE_CONTAINERNOTENOUGHROOM;
    }

    const Item* item = thing.getItem();
    if (!item) {
        return RETURNVALUE_NOTPOSSIBLE;
    }

    if (item == this) {
        return RETURNVALUE_THISISIMPOSSIBLE;
    }

    if (!item->isPickupable()) {
        return RETURNVALUE_CANNOTPICKUP;
    }

    return RETURNVALUE_NOERROR;
}

void Inbox::postAddNotification(Thing* thing, const Cylinder* oldParent, int32_t index, cylinderlink_t)
{
    Cylinder* parent = getParent();
    if (parent != nullptr) {
        parent->postAddNotification(thing, oldParent, index, LINK_PARENT);
    }
}

void Inbox::postRemoveNotification(Thing* thing, const Cylinder* newParent, int32_t index, cylinderlink_t)
{
    Cylinder* parent = getParent();
    if (parent != nullptr) {
        parent->postRemoveNotification(thing, newParent, index, LINK_PARENT);
    }
}

Cylinder* Inbox::getParent() const
{
    if (parent) {
        return parent->getParent();
    }
    return nullptr;
}s


Inbox.h:
Code:
// Copyright 2022 The Forgotten Server Authors. All rights reserved.
// Use of this source code is governed by the GPL-2.0 License that can be found in the LICENSE file.

#ifndef FS_INBOX_H_C3EF10190329447883B9C3479234EE5C
#define FS_INBOX_H_C3EF10190329447883B9C3479234EE5C

#include "container.h"

class Inbox final : public Container
{
    public:
        explicit Inbox(uint16_t type);

        //cylinder implementations
        ReturnValue queryAdd(int32_t index, const Thing& thing, uint32_t count,
                uint32_t flags, Creature* actor = nullptr) const override;

        void postAddNotification(Thing* thing, const Cylinder* oldParent, int32_t index, cylinderlink_t link = LINK_OWNER) override;
        void postRemoveNotification(Thing* thing, const Cylinder* newParent, int32_t index, cylinderlink_t link = LINK_OWNER) override;

        //overrides
        bool canRemove() const override {
            return false;
        }

        Cylinder* getParent() const override;
        Cylinder* getRealParent() const override {
            return parent;
        }
};

#endif
 
Back
Top