• 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+ TFS 1.5 setCustomAttribute crash

Itutorial

Legendary OT User
Joined
Dec 23, 2014
Messages
2,426
Solutions
68
Reaction score
1,074
Whenever I try to use the setCustomAttribute lua method the server crashes. I created a talkaction that works like /attr but will just set item rarity to whatever I want.

LUA:
local talkaction = TalkAction("/rarity")

function talkaction.onSay(player, words, param)
    if player:getAccountType() < ACCOUNT_TYPE_GOD then
        return false
    end
  
    local position = player:getPosition()
    position:getNextPosition(player:getDirection())

    local tile = Tile(position)
    if not tile then
        player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "There is no tile in front of you.")
        return false
    end

    local thing = tile:getTopVisibleThing(player)
    if not thing then
        player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "There is an empty tile in front of you.")
        return false
    end

    if thing:isItem() then
        thing:setCustomAttribute("Rarity", param)
        player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, string.format("Attribute Rarity set to: %s", param))
        position:sendMagicEffect(CONST_ME_MAGIC_GREEN)
    else
        player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Thing in front of you is not supported.")
        return false
    end
  
    return false
end

talkaction:separator(" ")
talkaction:register()

I upgraded my server from 1.4.2 but have made sure all source code related to custom attributes is up to date. Anyone got any ideas?

Side note the crash has to do with the hashing function.

1713545946572.png
 
Sugar boom boom bump. I have tried a bunch of different methods to use the custom attributes. Can't figure this one out.
 
@Itutorial

Going strictly based of what I can read in your call stack, seems the problem is with a conversion of a string view datatype into a string datatype.

My best guess, they expected an implicit conversion to handle things properly under the hood and that is not happening.

If you want to test this, try following the stack and see when and where it expects the std::string instead of std::string_view, and do a cast conversion or something, and if that fixes it, then you know that was the problem.
 
setCustomAttribute
What you should use is the method setCustomAttribute to set the 'Rarity' attribute to true on the item. For example, it would be like this: thing:setCustomAttribute("Rarity", true). This defines the item, and if it is successful, it will set the item's custom attribute. If you don't set it to true, it won't be defined, and nothing will be set. This could result in a crash or no visible change, indicating that the attribute does not exist.


I added getCustomAttribute to check if the item doesn't have the custom attribute, and then it will set it with setCustomAttribute("Rarity", true). You can try it out.

LUA:
local talkaction = TalkAction("/rarity")

function talkaction.onSay(player, words, param)
    if player:getAccountType() < ACCOUNT_TYPE_GOD then
        return false
    end

    local position = player:getPosition()
    position:getNextPosition(player:getDirection())

    local tile = Tile(position)
    if not tile then
        player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "There is no tile in front of you.")
        print("No tile found in front of player.")
        return false
    end

    local thing = tile:getTopVisibleThing(player)
    if not thing then
        player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "There is an empty tile in front of you.")
        print("Empty tile in front of player.")
        return false
    end

    if thing:isItem() then
        print("Item found: ", thing:getId())
        local currentRarity = thing:getCustomAttribute("Rarity")
        if currentRarity == nil then
            local status, error = pcall(function()
                thing:setCustomAttribute("Rarity", true)
            end)
            
            if status then
                player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Attribute Rarity set to: true")
                position:sendMagicEffect(CONST_ME_MAGIC_GREEN)
                print("Attribute Rarity set to: true")
            else
                player:sendTextMessage(MESSAGE_STATUS_CONSOLE_RED, "Error setting attribute: " .. tostring(error))
                print("Error setting attribute: " .. tostring(error))
            end
        else
            player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Item already has the Rarity attribute set.")
            print("Item already has the Rarity attribute set.")
        end
    else
        player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Thing in front of you is not supported.")
        print("Thing in front of player is not supported.")
        return false
    end

    return false
end

talkaction:separator(" ")
talkaction:register()
 
What you should use is the method setCustomAttribute to set the 'Rarity' attribute to true on the item. For example, it would be like this: thing:setCustomAttribute("Rarity", true). This defines the item, and if it is successful, it will set the item's custom attribute. If you don't set it to true, it won't be defined, and nothing will be set. This could result in a crash or no visible change, indicating that the attribute does not exist.


I added getCustomAttribute to check if the item doesn't have the custom attribute, and then it will set it with setCustomAttribute("Rarity", true). You can try it out.

LUA:
local talkaction = TalkAction("/rarity")

function talkaction.onSay(player, words, param)
    if player:getAccountType() < ACCOUNT_TYPE_GOD then
        return false
    end

    local position = player:getPosition()
    position:getNextPosition(player:getDirection())

    local tile = Tile(position)
    if not tile then
        player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "There is no tile in front of you.")
        print("No tile found in front of player.")
        return false
    end

    local thing = tile:getTopVisibleThing(player)
    if not thing then
        player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "There is an empty tile in front of you.")
        print("Empty tile in front of player.")
        return false
    end

    if thing:isItem() then
        print("Item found: ", thing:getId())
        local currentRarity = thing:getCustomAttribute("Rarity")
        if currentRarity == nil then
            local status, error = pcall(function()
                thing:setCustomAttribute("Rarity", true)
            end)
          
            if status then
                player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Attribute Rarity set to: true")
                position:sendMagicEffect(CONST_ME_MAGIC_GREEN)
                print("Attribute Rarity set to: true")
            else
                player:sendTextMessage(MESSAGE_STATUS_CONSOLE_RED, "Error setting attribute: " .. tostring(error))
                print("Error setting attribute: " .. tostring(error))
            end
        else
            player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Item already has the Rarity attribute set.")
            print("Item already has the Rarity attribute set.")
        end
    else
        player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Thing in front of you is not supported.")
        print("Thing in front of player is not supported.")
        return false
    end

    return false
end

talkaction:separator(" ")
talkaction:register()
According to the Author of that code, you should be able to use numbers, strings or booleans for the value... which is a very important part of this system, the only other part that matters is that you can set the key to string or number... those two things combined are the entire reason custom attribute was made...

1721001396812.png

So using it the way he did, should work without crash... as that is the entire point of this system.

@Itutorial

Probably this is the fix that was needed?

 
Last edited:
"This was nullptr", a nullptr dereference, you called that method on a deleted item object thus it crashed. If you see hashers or iterator errors in maps it usually is use after free.

Nothing wrong with tfs code, it's incorrectly used.
 
According to the Author of that code, you should be able to use numbers, strings or booleans for the value... which is a very important part of this system, the only other part that matters is that you can set the key to string or number... those two things combined are the entire reason custom attribute was made...

View attachment 86042

So using it the way he did, should work without crash... as that is the entire point of this system.

@Itutorial

Probably this is the fix that was needed?

I will check it out and report back. Thank you.

Damn bro.. I can't believe no one has helped with this yet...

Did you ever figure this one out, or no?
There are a few people on here that don't like me I think. I usually get help though so I aint mad about it.
 
Back
Top