• 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!

TFS 1.X+ onMoveItem apply customAttribute

Addams

OTMadness.com OTSes Services
Staff member
Board Moderator
Joined
Sep 29, 2009
Messages
2,920
Solutions
342
Reaction score
1,688
Location
Egypt
Why would this affect the whole stack not only the (1) moved item? What I am missing?
Lua:
local ec = EventCallback

ec.onMoveItem = function(self, item, count, fromPosition, toPosition, fromCylinder, toCylinder)
    local moveFromItem = ItemType(item:getId())
    if moveFromItem:isStackable() then
        if toPosition.x == CONTAINER_POSITION then
            local moveToItem = self:getSlotItem(toPosition.y)
            if not moveToItem and toCylinder:isItem() then
                moveToItem = toCylinder:getItem(toPosition.z)
            end
            if moveToItem then
                if item:getId() == moveToItem:getId() then
                    if moveToItem and moveToItem:getCustomAttribute("Test", "Attribute") then
                        item:setCustomAttribute("Test", "Attribute")
                        self:sendTextMessage(MESSAGE_INFO_DESCR, "Custom attribute added.")
                        item:setAttribute("description", "Worked")
                        return RETURNVALUE_NOERROR
                    end
                end
            end
        end
    end
    return RETURNVALUE_NOERROR
end

ec:register()
CustomAttribute.gif
I want to apply only to this (1) custom attribute onMoveItem so I don't need to change the source to allow stacking all the custom attributed items.
 
Solution
ok the problem is that you are adding an attribute in one situation and not in both, here I will show you an example code, this only works for articles that are going to have only one different property, since we are only copying a single one, make sure of that.

in this case it is better to use an onLook event to see the changes:
Lua:
local customAttributeKey = "Test"
local customAttributeValue = "Worked"

local function applyChanges(player, item)
    item:setCustomAttribute(customAttributeKey, customAttributeValue)
    player:sendTextMessage(MESSAGE_INFO_DESCR, "Custom attribute added.")
end

local ec = EventCallback

function ec.onMoveItem(player, item, count, fromPosition, toPosition, fromCylinder, toCylinder)
    if toPosition.x ~=...
maybe you should use onItemMoved instead of onMoveItem This is because onMoveItem is checking the object being moved, not the moved item.
I'm not sure if it will work but it should.
 
maybe you should use onItemMoved instead of onMoveItem This is because onMoveItem is checking the object being moved, not the moved item.
I'm not sure if it will work but it should.
onItemMoved will only apply after confirming the item has already been moved.
In my case my item will never move before the script sets the customAttribute to it because TFS stops stacking items with no custom attributes to the same items with custom attributes.
 
So you want to set a description to an item that is not actually moved yet, but you want to do it when you are moving it?
 
Not a description, a custom attribute. The description was just to show that items in the backpack got affected too.
I think the correct way to do this would be onAddItem but I am unable to check players there.
 
The way stackable items work I doubt I'll find exactly what you're looking for, but maybe with tricks you can achieve a similar result.
Maybe there are more tricks but thinking quickly, I think copying the item and then removing all items from the copy leaving only 1, and use that as a result? obviously you will have to remove 1 item from the original pile to simulate that you have separated it
Also in some cases you will have to cancel the move so you will have an error message, here I will show you an example, I have not tried all the scenarios so it will be a matter of finding out if it is safe to use this, if you find any error let me know.

you must use the itemApplyAttributes function to modify the "item" to be moved:
Lua:
local function itemApplyAttributes(item)
    print(item, item:getName(), item:getCount())
    item:setCustomAttribute("Test", "TEST Value")
end

local ec = EventCallback

function ec.onMoveItem(player, item, count, fromPosition, toPosition, fromCylinder, toCylinder)
    if item:getCount() > count then
        local moveItem = item:split(count)
        if toPosition.x ~= CONTAINER_POSITION then
            itemApplyAttributes(moveItem)
            moveItem:moveTo(toCylinder)
        elseif bit.band(toPosition.y, 0x40) == 0 then
            local topSlot = player:getSlotItem(toPosition.y)
            if topSlot and topSlot:getType():isContainer() then
                local clonedItem = moveItem:clone()
                itemApplyAttributes(moveItem)
                if topSlot:addItemEx(moveItem) ~= RETURNVALUE_NOERROR then
                    moveItem:remove()
                    clonedItem:moveTo(toCylinder)
                    return RETURNVALUE_CONTAINERNOTENOUGHROOM
                end
                clonedItem:remove()
            else
                itemApplyAttributes(moveItem)
                player:addItemEx(moveItem, false, toPosition.y)
            end
        else
            local container = player:getContainerById(toPosition.y - 64)
            if container then
                local topSlot = container:getItem(toPosition.z)
                if topSlot and topSlot:getType():isContainer() then
                    local clonedItem = moveItem:clone()
                    itemApplyAttributes(moveItem)
                    if topSlot:addItemEx(moveItem) ~= RETURNVALUE_NOERROR then
                        moveItem:remove()
                        clonedItem:moveTo(toCylinder)
                        return RETURNVALUE_CONTAINERNOTENOUGHROOM
                    end
                    clonedItem:remove()
                else
                    local clonedItem = moveItem:clone()
                    itemApplyAttributes(moveItem)
                    if container:addItemEx(moveItem) ~= RETURNVALUE_NOERROR then
                        moveItem:remove()
                        clonedItem:moveTo(toCylinder)
                        return RETURNVALUE_CONTAINERNOTENOUGHROOM
                    end
                    clonedItem:remove()
                end
            end
        end
        return RETURNVALUE_NOTPOSSIBLE
    end
    itemApplyAttributes(item)
    return RETURNVALUE_NOERROR
end

ec:register(--[[0]])

In this case I am making use of the amount you move, not just 1 as in the textual example, if you move a package of 10, all 10 will get the attributes you want.
 
Thank you for the great effort, I really appreciate it.
I just started testing now, I will test every possible situation.
I have quickly found 2 issues.
  1. It adds the custom attribute on moving the item (even to an empty toPosition), It is supposed to check if this toPosition has an item with the custom attribute then it applies to the moved item. I had a check for it in the test script if moveToItem and moveToItem:getCustomAttribute("Test", "Attribute") then
  2. When moving a spear from a stack it moves 2 by 2 randomly somehow.
test_onMoveItem.gif
Can you make it so it checks if the moved to item has already got the custom attribute then it adds same attribute to the moved item? and also only left-hand slot position is enough for me now, I am only adding it to different spear weapons.
I may have had it messed up in my test script but it was meant to only check left-hand slot only. Just getting confused between toPositions as always.
 
Thank you for the great effort, I really appreciate it.
I just started testing now, I will test every possible situation.
I have quickly found 2 issues.
  1. It adds the custom attribute on moving the item (even to an empty toPosition), It is supposed to check if this toPosition has an item with the custom attribute then it applies to the moved item. I had a check for it in the test script if moveToItem and moveToItem:getCustomAttribute("Test", "Attribute") then
  2. When moving a spear from a stack it moves 2 by 2 randomly somehow.
View attachment 72083
Can you make it so it checks if the moved to item has already got the custom attribute then it adds same attribute to the moved item? and also only left-hand slot position is enough for me now, I am only adding it to different spear weapons.
I may have had it messed up in my test script but it was meant to only check left-hand slot only.
perfect, try to generalize it for all cylinders of destiny, hahahaha, if it is only the left slot of the player's inventory of course, I will try to do it for you.
 
perfect, try to generalize it for all cylinders of destiny, hahahaha
Yeah, my bad I didn't clear it on the post. That's why yours had many checks. XD
if it is only the left slot of the player's inventory of course, I will try to do it for you.
Thank you, I will wait then to test the final script instead of the above for all cylinders.
 
Yeah, my bad I didn't clear it on the post. That's why yours had many checks. XD

Thank you, I will wait then to test the final script instead of the above for all cylinders.
Lua:
local ec = EventCallback

function ec.onMoveItem(player, item, count, fromPosition, toPosition, fromCylinder, toCylinder)
    if toPosition.x ~= CONTAINER_POSITION or bit.band(toPosition.y, 0x40) ~= 0 or toPosition.y ~= CONST_SLOT_LEFT then
        return RETURNVALUE_NOERROR
    end

    local topSlot = player:getSlotItem(toPosition.y)
    if not topSlot or topSlot:getType():isContainer() then
        return RETURNVALUE_NOERROR
    end

    local value = topSlot:getCustomAttribute("Test")
    if not value then
        return RETURNVALUE_NOERROR
    end

    if item:getCount() > count then
        local moveItem = item:split(count)
        moveItem:setCustomAttribute("Test", value)
        player:addItemEx(moveItem, false, CONST_SLOT_LEFT)
        return RETURNVALUE_NOTPOSSIBLE
    end

    item:setCustomAttribute("Test", value)
    return RETURNVALUE_NOERROR
end

ec:register(--[[0]])
 
Moving 1 spear only (not stacked one) works properly, But when moving 1 spear from a stack then it removes the topSlot stack and adds 1 spear (without custom attribute), No console errors.
Moveitem_IssueOne.gif
 
Moving 1 spear only (not stacked one) works properly, But when moving 1 spear from a stack then it removes the topSlot stack and adds 1 spear (without custom attribute), No console errors.
View attachment 72084
I am doing the same thing that you are doing in the GIF and everything seems fine, could you show your code already configured for your situation? have you changed something?
 
I am doing the same thing that you are doing in the GIF and everything seems fine, could you show your code already configured for your situation? have you changed something?
Nothing just added sendTextMessage and setAttribute.
Lua:
local ec = EventCallback

function ec.onMoveItem(player, item, count, fromPosition, toPosition, fromCylinder, toCylinder)
    if toPosition.x ~= CONTAINER_POSITION or bit.band(toPosition.y, 0x40) ~= 0 or toPosition.y ~= CONST_SLOT_LEFT then
        return RETURNVALUE_NOERROR
    end

    local topSlot = player:getSlotItem(toPosition.y)
    if not topSlot or topSlot:getType():isContainer() then
        return RETURNVALUE_NOERROR
    end

    local value = topSlot:getCustomAttribute("Test", "TEST Value")
    if not value then
        return RETURNVALUE_NOERROR
    end

    if item:getCount() > count then
        local moveItem = item:split(count)
        moveItem:setCustomAttribute("Test", "TEST Value")
        player:addItemEx(moveItem, false, CONST_SLOT_LEFT)
        return RETURNVALUE_NOTPOSSIBLE
    end

    item:setCustomAttribute("Test", "TEST Value")
    player:sendTextMessage(MESSAGE_INFO_DESCR, "Custom attribute added.")
    item:setAttribute("description", "Worked")
    return RETURNVALUE_NOERROR
end

ec:register(-777)
Could it be the test script I am using originally to add the custom attribute? That's the one I am using now.
Lua:
function onEquip(player, item, slot, isCheck)
    if isCheck then
        return true
    end
    if item then
        if not item:getCustomAttribute("Test", "TEST Value") then
            item:setCustomAttribute("Test", "TEST Value")
            player:sendTextMessage(MESSAGE_INFO_DESCR, "Custom attribute added.")
            item:setAttribute("description", "Worked")
        end
    end
    return true
end
 
ok the problem is that you are adding an attribute in one situation and not in both, here I will show you an example code, this only works for articles that are going to have only one different property, since we are only copying a single one, make sure of that.

in this case it is better to use an onLook event to see the changes:
Lua:
local customAttributeKey = "Test"
local customAttributeValue = "Worked"

local function applyChanges(player, item)
    item:setCustomAttribute(customAttributeKey, customAttributeValue)
    player:sendTextMessage(MESSAGE_INFO_DESCR, "Custom attribute added.")
end

local ec = EventCallback

function ec.onMoveItem(player, item, count, fromPosition, toPosition, fromCylinder, toCylinder)
    if toPosition.x ~= CONTAINER_POSITION or bit.band(toPosition.y, 0x40) ~= 0 or toPosition.y ~= CONST_SLOT_LEFT then
        return RETURNVALUE_NOERROR
    end

    local topSlot = player:getSlotItem(toPosition.y)
    if not topSlot or topSlot:getType():isContainer() then
        return RETURNVALUE_NOERROR
    end

    local value = topSlot:getCustomAttribute(customAttributeKey)
    if not value then
        return RETURNVALUE_NOERROR
    end

    if item:getCount() > count then
        local moveItem = item:split(count)
        applyChanges(player, moveItem)
        player:addItemEx(moveItem, false, CONST_SLOT_LEFT)
        return RETURNVALUE_NOTPOSSIBLE
    end

    applyChanges(player, item)
    return RETURNVALUE_NOERROR
end

ec:register(-777)

local ec = EventCallback

function ec.onLook(player, thing, position, distance, description)
    if thing:isItem() then
        local value = thing:getCustomAttribute(customAttributeKey)
        if value then
            description = string.format("%s\n%s", description, value)
        end
    end
    return description
end

ec:register(666)
 
Solution
ok the problem is that you are adding an attribute in one situation and not in both, here I will show you an example code, this only works for articles that are going to have only one different property, since we are only copying a single one, make sure of that.
Thank you works perfectly!
in this case it is better to use an onLook event to see the changes:
I used onLook, Worked the same as I wanted. Appreciate it.
I still cannot close the thread/mark as solution, Not sure why.
upvoted.PNG
 
Last edited:
Back
Top