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

Solved Using Item() in a Creaturescript [TFS 1.1]

imkingran

Learning everyday.
Premium User
Joined
Jan 15, 2014
Messages
1,317
Solutions
35
Reaction score
434
Hey Guys,

Is it possible to do something like this?

action script:
Code:
function onUse(player, item, fromPosition, itemEx, toPosition)
    --> Run a DB Query to store the Item's Unique ID
    db.query("UPDATE `players` SET `uniqueItem` = "..itemEx.uid.." WHERE `id`  = "..player:getGuid()..";")
return true
end


Code:
function onLogin(player)
    local item = 0
    local result_plr = db.storeQuery("SELECT `uniqueItem` FROM `players` WHERE `id` = "..player:getGuid()..";")
    if(result_plr ~= false) then
        item = Item(result.getDataInt(result_plr, "uniqueItem"))
        result.free(result_plr)
    end

    Item(item):getPosition():sendMagicEffect(CONST_ME_FIREWORK_RED)
end

What I'm trying to ask is:
Is it possible to use Item(item.uid) in a creaturescript if I store the item's unique ID in the database through the action script and then call the same unique id in the creaturescript. So far it seem as though it's not possible (per my own tests), however maybe someone with more knowledge and experience knows better.

Thanks for your time and help. :)

p.s.
If I was unclear of what I'm trying to accomplish just please let me know and I'll try to clarify what my end goal is.
 
Thanks, I'll try it out as soon as I get back home and let know how it went!

@Colors
______________
Post Testing:
Essentially it's the same thing as my first post. The UID is constantly changing so it returns a NIL value when I'm trying to call it again in the creaturescript.

Even when I set it again to be a constant UID in the action script:
Code:
Item(itemEx.uid):setAttribute(ITEM_ATTRIBUTE_UNIQUEID, player:getGuid() + 5000)
STORE_UPGRADE[player:getGuid()] = {item = itemEx.uid}
print(itemEx.uid) -- prints: 5009
print(Item(itemEx.uid)) -- prints: userdata: 0x41c98bb8
local storageUID = STORE_UPGRADE[player:getGuid()].item
print(storageUID) -- prints: 5009
print(Item(storageUID)) -- prints: userdata: 0x41b5de18

In the creaturescript I still get a nil value:
Code:
local item = (STORE_UPGRADE[player:getGuid()].item)
Item(item):setAttribute('name', nam)
print(item) -- prints: 5009
print(Item(item)) -- prings: nil


It's most likely me being dumb. Am I doing something wrong? :oops:
For this one, you're making a global variable in actions, which isn't possible as far as I know. Create a variable in another script, throw it in your lib folder (or in data/) and have global.lua load it. Store the item's UID in that variable, and it should be accessible as long as the server stays online and global.lua doesn't reload. The reason it prints nil is because it literally does not exist as far as the creaturescript is concerned. Make this change and you should be fine to access it and use the actionid (on a non-god character, the player won't be able to move their item if it has a Unique ID on it)
 
Setting a database value would work....however you are calling the wrong values.... You cannot set an UID like that, you have to call a specific item. So when trying to do this, you need to follow something like this:

I am not sure of the new scriptsystems but something like:

Action script:
-- Player uses item
-- sets database value to itemid

CreatureScript:
--Call value from database
--look for item // player:getItemNameById(value from database)
--set new value for item // local item = player:getItemNameById(valuefromdatabase)



Right now you are just trying to get the script to read the item as the value imput to database......which the script really only knows it is a INT value, but doesn't know ANYTHING else....

All the script knows is it is looking at...lets say:

1566......All it knows is it is 1556, it doesn't know its and item....or even what item you are calling....

There can be 500000 items with itemid 1566 on the map..... So, you have to specify which item....

So you have to tell the script 2 things:
1. That what it is reading (1556) is an item....
2. Which item it is specificly


The only way to do that is compare it to another item....So something like this would work.....

Lets say the itemid that is in the database is mapped somwhere on the map....

if database.itemid == position::getThing(x = 1000, y = 1000, z = 7}.itemid then
item = position::getThing(x = 1000, y = 1000, z = 7}.itemid


Now the script knows what you are trying to call (an item).... Now you have to say what item specificly in the map you want to call....So, if its on the player...

if player::getItem(item) == item then
player_item = player::getItem(item)

Then you could start your scripting like:

item(player_item)::setAttibute

or what ever else you want to do.....

If there was a thing like this:

if isItem(database.itemid) then
if player::getItem(database.itemid) then
item_specific = player::getItem(database.itemid)
item(item_specific)::setAttribute("UID", 5000)
end
end

it would be 100% easier to do something like this....


I hope you get what im saying....


Again:

1) script doesn't know what 1556 is....
2) so you tell it 1556 is an item.....
3) then call the item specificly that you want
4) then the item is defined
5) then you can use the script you are wanting... item(item_defined)::blah
 
Last edited:
Thanks everyone for taking the time to help me out!

I'm going to read through everyone's post a few times to make sure I understand what advice was given and try to apply it.
I'll post back here with hopefully successful results.
 
Setting a database value would work....however you are calling the wrong values.... You cannot set an UID like that, you have to call a specific item. So when trying to do this, you need to follow something like this:

I am not sure of the new scriptsystems but something like:

Action script:
-- Player uses item
-- sets database value to itemid

CreatureScript:
--Call value from database
--look for item // player:getItemNameById(value from database)
--set new value for item // local item = player:getItemNameById(valuefromdatabase)



Right now you are just trying to get the script to read the item as the value imput to database......which the script really only knows it is a INT value, but doesn't know ANYTHING else....

All the script knows is it is looking at...lets say:

1566......All it knows is it is 1556, it doesn't know its and item....or even what item you are calling....

There can be 500000 items with itemid 1566 on the map..... So, you have to specify which item....

So you have to tell the script 2 things:
1. That what it is reading (1556) is an item....
2. Which item it is specificly


The only way to do that is compare it to another item....So something like this would work.....

Lets say the itemid that is in the database is mapped somwhere on the map....

if database.itemid == position::getThing(x = 1000, y = 1000, z = 7}.itemid then
item = position::getThing(x = 1000, y = 1000, z = 7}.itemid


Now the script knows what you are trying to call (an item).... Now you have to say what item specificly in the map you want to call....So, if its on the player...

if player::getItem(item) == item then
player_item = player::getItem(item)

Then you could start your scripting like:

item(player_item)::setAttibute

or what ever else you want to do.....

If there was a thing like this:

if isItem(database.itemid) then
if player::getItem(database.itemid) then
item_specific = player::getItem(database.itemid)
item(item_specific)::setAttribute("UID", 5000)
end
end

it would be 100% easier to do something like this....


I hope you get what im saying....


Again:

1) script doesn't know what 1556 is....
2) so you tell it 1556 is an item.....
3) then call the item specificly that you want
4) then the item is defined
5) then you can use the script you are wanting... item(item_defined)::blah
What happens when the player has more than one of that item on them?
As for the isItem thing, you can just cast it.
"if Item(itemid) then"

but regardless, this option wouldn't work because the player can have more than one of the same item. The only way to check it would be checking a slot for an item. At that point the player has to have the item in that slot and that may be annoying and I doubt that's the desired functionality.

@imkingran I just tested on my server. In the actions script, set a global variable (in a global script, like I mentioned before) to Item(itemEx.uid). You can access it from outside the actions script. I was able to print the actionid of the item. As long as the item exists still, it will work. Since those variables are affected by anyone who uses the script, you'll want to set up a table in that global script.

Code:
upgitems = {}
in the actions script,
Code:
upgitems[player:getGuid()] = Item(itemEx.uid)
This will create or add to an index that is unique to the player, allowing them to access their item without affecting any other users of the system. to call it in the creaturescript just access it the same way. also good to check if it's not a valid value to avoid issues with memory usage. if you set an actionid to the item, you can check it easily. if the item is destroyed it will return values still, it will not be considered nil, so do something like this:
Code:
if upgitems[player:getGuid()]:getAttribute(ITEM_ATTRIBUTE_ACTIONID) > 0 then
--item still exists
else
upgitems[player:getGuid()] = nil
end

edit:
use this, makes your life easier for this sorta stuff xD
https://otland.net/threads/tfs-1-x-lib-folder-in-data-like-0-4.228660/
 
I was just explaining how the script needs things to be. I don't know exactly what hes trying to do...but if you use what i said, it will call one of the many items they could have with the same ID....I just don't know if he needs the exact item called everytime or if he was just trying to get it to register an item with that ID so the script can be used as: item(item)::
 
You guys are amazing! It's working properly now with this:

Action:
Code:
STORE_UPGRADE[player:getGuid()] = {item = Item(itemEx.uid):getId()}
STORE_UPGRADE[player:getId()] = {action = Item(itemEx.uid):getActionId()}

Creaturescript:
Code:
-- Check to make sure the item is there --
if not player:getItemById(STORE_UPGRADE[player:getGuid()].item, true) then
player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, "Item not found:\nMake sure the item is either in your backpack or equipped.")
return true
end
         
-- Check the actionID on the item --
local item = player:getItemById(STORE_UPGRADE[player:getGuid()].item, true)
if not (item:getActionId() == (STORE_UPGRADE[player:getId()].action)) then
player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, "Wrong Item.")
return true
end

(Sorry about the tabbing)

Currently though, let's say I have 2 axes:
1. If I use it on the first axe in my BP it will work.
2. If I use it on the 2nd it will say "wrong item". So that will be the next adventure!

(edit I just read the last 2 posts before this -- I'll test it now)

Final Edit:
@RazorBlade
Code:
upgitems[player:getGuid()] = Item(itemEx.uid)

Works like a charm. Doesn't matter if the item is at X position in the backpack, equipped, or on the ground. Working fine thus far! :)
 
Last edited:
Back
Top