I was discussing some things about finditem with Gaderian in another thread and thought I'd move the discussion to it's own thread.
Original thread where the conversation started:
http://www.scriptuo.com/index.php?action=post2;start=0;board=30last post from Gaderian for some context
I use the 'for #findindex 1 #findcnt' all the time, but it doesn't work in the example I showed above, because #findcnt gets reset with each 'finditem' statement (when looking for the tools), and I had to keep track of how far through the list I was.
The ignoreitem method doesn't work when trying to see if I have enough tinker tools to craft more tinker tools to fill the bod; additionally this won't work when the item stacks.
Also when you issue the 'finditem TYPE Index location' method, #findcnt returns 1 each time because you said you wanted to search for only 1. (I expected it to give me back the same #FindCnt value as if I had looked for the whole list, but that was incorrect.)
So using a number value for the Index into the list behaves very differently from the other methods.
In another thread here, TrailMyx states that everyone gets the items back in the same order (suppose you stand in range of the same NPC's with me, we both get the same order of NPC's). I haven't tried to prove or disprove that, but take his word for it. It makes sense because the Index parameter allows subsequent execution of the 'finditem TYPE LOCATION' to actually iterate through the list. If this return was variable on each call, then the Index parameter would not really work.
Interesting nuances in the language that we can take advantage of in scripts...
;--------------------------------------------------------
Few things here. A big one is that you're conflating EUO system functions(finditem) and #return variables with script-local user-defined functions and variables. You can define just about anything you can think of, function or variable, as long as you define it and address it correctly for your intended use.
For those who may be unfamiliar, finditem is an EUO system function. When you call finditem, it returns an array of data that you may reference until you call finditem again. For each subsequent finditem call, EUO will delete all previously held data at each memory/array address, and then populate a new array.
... #findcnt gets reset with each 'finditem' [call] ... and I had to keep track of [a previous finditem_return index position] ...
Correct. This is why, if you need to reference the data again, after future finditem calls, or the worst case scenario, against
THE NEXT or LAST finditem call, the best/only (if next or last) practice is to store the relevant data in a user-defined array for later reference. This can easily be done in EUO by using the append concatenator . (#dot).
In this particular case you may be able to get away with just doing a finditem call and then just using the first thing found before calling finditem again, but if you're wanting to reference values like #findiindex or #findcnt against the current data set, you will need to store all relevant data points in a referenceable manner if your flow requires another finditem call before that data is irrelevant. You're already doing half of this. Just take one more step and you've solved it.
If what TM was saying is correct (I would assume it is) then #findindex is more descriptive than I had previously assumed, but only when a finditem is called using the exact search_for parameter in the exact #charpos and/or container (and probably expecting the searched items having not been moved between searches, as it's likely a server propagation hierarchy). Only in that one special case could you consider #findindex to be descriptive for anything other than defining a position in the current finditem_result array.
#findindex holds no special relevance outside of the fact that for every #findindex = n, when and
only when used in conjunction with any #findresult, it points to a specific position in the current finditem_return (and the extremely rare usage above).
#findcnt also holds no relevant information outside of the amount of indices that were returned when finditem was last called making it easier to parse the array. it's just a count-value that is system function defined, and cannot be defined with set.
Example of #findindex irrelevance:
for #findindex 1 5
set %test . #findindex test . #findindex
;will produce identical results as
for %i 1 5
set %test . %i test.%i
;both will produce a 1x5 array of %test1-5 = test1-5
You can easily test this by opening a fresh EUO tab, with no previous finditem calls, and running this:
for #findindex 1 5
set %test . #findindex test . #findindex
for %i 1 5
display %test . %i
halt
now #findindex relevance and #findcnt ir/relevance. This is a usable test/example:
finditem * c_ , #charid
for #findindex 1 #findcnt
display Item #findid found at Index Position #findindex ,
+ ,$in the current finditem_result array$that has a total of
+ #findcnt unique indices.
;will produce identical results as
set %just_a_count #findcnt
for %i 1 %just_a_count
{
set #findindex %i
display Item #findid found at Index Position %i ,
+ ,$in the current finditem_result array$that has a total of
+ %just_a_count unique indices.
}
;this previous example also shows why we should be thankful we can shove #findindex in a for() call as parameter 1
;and finally, same with this one, and also why we should all be thankful for #findcnt as well as
;being able to shove it into the upper-bound parameter of our for() calls
;this also sets up a user-defined array, so you can reference the
;current finditem_results array permanently.
for %i 1 1000000
{
set #findindex %i
if #findid <> yc
set %just_a_moniker . %i #findid
if #findid = yc 2
set %literally_just_a_count %i - 1
set %i 1000000
}
set %from_1_to 1
for %any_old_numer %from_1_to %literally_just_a_count
display Item %just_a_moniker . %any_old_numer found at Index Position %any_old_numer
+ ,$in the current finditem_result array$that has a total of
+ %literally_just_a_count unique indices.
halt
So when I:
finditem %sbod_types c_ , #backpackid
set %sbod_cnt #findcnt
for #findindex 1 %sbod_cnt
set %sbodid . #findindex #findid
I create a user-defined 1xN array (IDxIndex|Indices) indexed to the data found in the finditem_result array that is permanently referenceable within the script until I manually delete it, overwrite it, or stop the script.
The sbodID array:
%sbodid1 = ;a unique #ObjectID found at index position 1 of the the previous finditem_sbods_results array
%sbodid2 = ;a unique #ObjectID found at index position 2 of the the previous finditem_sbods_results array
...
%sbodid . %sbod_cnt = ;a unique #ObjectID found at index position #findcnt of the the previous finditem_sbods_results array
A reference and pseudo-use-case for each index:
for %i 1 %sbod_cnt ;note, you could use %sbod_index in place of %i if that helps you,
{ ;but what you name the counter is entirely irrelevant.
;only the current count is relevant.
;the second parameter 1, will always start the count at 1
;and will continue to perform all actions below for each %sbodid . %i
;until it has completed all actions below for %sbod . %sbod_cnt
event property %sbodid . %i
;do sbod things
...
}
As a sort of aside, but on topic to the previous example use case, it would be best practice to delete all previous entries freeing the designated memory addresses, just the same as EOU does when you call finditem. The biggest concern is not really the memory usage (although that should
always be a concern, even when it is minimal), but rather that the sbod count might be variable if/when you're calling this user-defined function/sub multiple times in the same script.
My recommended example:
;check for if %sbod_cnt is defined = #true. This will only pass after the first time through.
;alternatively you could use if %sbod_cnt > 0 if for some weird reason
;you are defining it in parallel somewhere else in the script.
if %sbod_cnt <> n/a 2
for %i 1 %sbod_cnt
deletevar %sbodid . %i
;someone will probably comment about deletevar. "set %variable " does not delete the address. only the value.
;you don't need to delete %sbod_cnt as it will be overwritten before it is referenced again.
finditem %sbod_types c_ , #backpackid
set %sbod_cnt #findcnt
for #findindex 1 %sbod_cnt
set %sbodid . #findindex #findid
I hope this helped to simplify arrays.
The ignoreitem method doesn't work when trying to see if I have enough tinker tools to craft more tinker tools to fill the bod
This is literally one of it's usages. you just have to ignoreitem by ID. But this doesn't solve the issue of crafting another tinker tool before this one runs out. But that's a conversation for another thread.
Test code:
;clear your backpack of Tinkering Tool Kits.
;put one in your backpack then press play:
finditem %tinkerToolTypes c_ , #backpackid
ignoreitem #findid
set %ignoredTool #findid ;set this so you can clean up the ignoreitem command later
pause
;now put as many tinker tools as you like in your backpack and press play again
finditem %tinkerToolTypes c_ , #backpackid
for #findindex 1 #findcnt
{
if %ignoreditem = #findid 3
set %ignoreitem = #false
display Welp, ignoreitem doesn't work :(
halt
}
if %ignoreitem <> #false
display finditem found #findcnt Tinkering Tool Kits, but did not find the one that was ignored.
pause
;now if you still don't think it works we'll un-ignore that ID
ignore item %ignoreitem
finditem %tinkerToolTypes c_ , #backpackid
display finditem now found #findcnt Tinker Tool Kits in your backpack!
halt
there are other ways to do this as well, but this is the simplest. not necessarily the best option, but it is simple.
additionally this won't work when the item stacks
i don't know what else would be important to ignore except the items you normally keep in your backpack and a tinkerer's tool so you can craft more tinkerer's tools when needed. could you provide an example?
finditem TYPE Index location
I am unsure of what exactly you are expressing here. If this is still relevant, please post an example.