Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Messages - lydaan

Pages: [1] 2 3 ... 5
1
Quote
You mentioned you want to preserve the %# variables (%0, %1, %2, ... %n), and do this with namespaces.

The prefix for namespace variables is ! (not %). So those sub parameters will not be preserved via namespaces.

I've already done this (as I explained in the same post). I was just showing what I was doing before, for anyone else who might find this thread at a later time. I often scroll through threads from years ago to see if a previous discussion involves something I'm working on.

Quote
I do not use deletevar because the documentation declares it deprecated, however, have you tested:
Code: easyuo
  1. deletevar % . local_ca . %i

yep. I've tried just about everything I can think of. the only thing I haven't tried yet is a %deletevar . %i as a string reference of the variable name, but I don't really care at this moment as it is no longer relevant. I'll do a full test later and do a write-up once I'm satisfied I've exhausted all options.

The wiki says "considered deprecated," not exactly deprecated and I would assume the spotty concatenation issue is due to it not being updated once "set %variable   ," was implemented.

The main reason why I prefer to use deletevar is because it supposedly deletes the address, or at least when you reference the address it returns "N/A," mimicking an undefined address. Conversely you could set %variable N/A, and I do this for persistent variables like #result, but my goal is to not populate anything that doesn't need to be. But that's me.

"set %variable  ," returns a value of " ," and if want to check against that you have to set another check variable, like %null to the same value to check against it.

Example:
Code: easyuo
  1. set %variable
  2. if %variable =    ;how do I check for this????
  3.  
  4. ;you must set a checkVar to the same value
  5. set %null
  6. if %variable = %null ;now you can check against %null

like in most situations there are many ways to solve this, but it comes down to personal preference.

2
I very much appreciate you posting that, as well as sort of translating what Gadarian was sharing. I looked at Gad's post and just thought... "hmmm, interesting. I have no idea what Gad is trying to do but it looks interesting." And I'm not trying to do anything that complex currently.

I was sort of guessing that you would use namespace copy to share relevant values across multiple instances of the same function, and you confirmed that by posting the CLAw recursion engine. This is well beyond what I'm trying to do at this moment, but I appreciate you posting that for reference.

Just for reference, 99% of my coding experience is within EUO. Probably ~2000 hours, the majority of which is fixing designed bugs or correcting for the client behaving unexpectedly. But thanks to this I can generally read any OO language without too much difficulty, after looking up vocabulary.

;----------------------

2 weeks ago, I had never used namespace except for passing a very limited amount of global variables between scripts/clients. This current interest basically started with wanting a sub to call another sub while maintaining the original gosub arguments (%0-n). I was storing the variables with a simple for() declaring %local_variables and then deleting them before returning.

Simplified example:
Code: easyuo
  1. sub clientAction
  2.    for %i 0 %0
  3.       set %local_ca . %i
  4.    ...
  5.    for %i 0 %local_ca0
  6.       deletevar %local_ca . %i
  7. return
*note: this specific case of deletevar does not work. you can concatenate within the deletevar parameter, but only under unique conditions.

I still have to do that, as the only other option I can think of is creating a passVar handler sub with n-if statements and subsequent gosubs with n-arguments, where n is the count/maximum number of possible gosub arguments in a script, and I don't want to write ~80 (or unknown) if statements (Sub MultiClientAction, a handler sub stores n clientAction gosub calls for specific situations), nor do I think this would be a beneficial solution.

Originally, I was looking at namespace for use of CLEAR, but quickly realized I can handle a lot of functionality by setting new namespaces within a sub as well as allowing for a sub to call itself without overwriting stored %variables by utilizing namespace-local !variables.

Sub ClientAction is really just a two state directory function with a single multi-state checkVar, that calls another directly callable sub to check for server/client-connection, and if lost, calls another directly callable login sub, ultimately retaining EUO cursor focus so that the script flow picks up at the last client action and script flow is maintained or easily regained. The goal is to funnel 99% of client interaction into a single checkVar/connection check, as connection to the server is an issue for me, and I'm trying to write as close to 24/7 (theoretical maximum) uninterrupted bot scripts.

Certain functions, like #property management for example, require the variable I'm checking against to be in a specific state, known or unknown, and I must set/confirm that state before checking for the intended resolution. I was originally handling this with a simple counter and cycling through the internal functionality with gotos, but this felt clunky.

Now, thanks to the discussion on this thread, I can implement a more elegant solution of having the sub call itself to set/confirm a checkVar state before checking the original argument.

For this specific case I only need access to the basic functionality of the sub while maintaining local variable integrity of the original call, and not the state of variables within recursive instances of the function. But now, if I need that as well, I have that option (or at least the groundwork) due to this discussion.

Your last post set my brain ablaze, TM. I've understood the concept of recursion for a long while, but never experienced a necessary use case. The last few hours have been a fun learning/understanding experience. I'd like to thank both you and Gad again for sharing your incites with me. I'm mostly done with questions regarding this topic for now, but if I need to tackle full EUO-style recursion, I'm sure I'll have more.

3
Now that I understand that for every push there should be a pop, push/pop already handles many:many.

This is the solution I came up for a more complex situation I'm dealing with:
Code: easyuo
  1. sub clientAction
  2.    namespace push
  3.    if clientAction notin #nsname || clientAction in #nsname && #nstype <> local
  4.       namespace local clientAction0
  5.    else 3
  6.       str right #nsname 1
  7.       set #strres #strres + 1
  8.       namespace local clientAction . #strres
  9.    ...
  10.    namespace clear
  11.    namespace pop
  12. return

glad I asked about how I assumed push/pop works. this new solution solves some other problems, like maintaining counter integrity within a sub. I realize that this solution will only work if the sub will never call itself indirectly.

If I need a sub to do that in the future, for some reason I don't as of yet, know, I'll just make a string handler to make a list of namespaces for every active namespace in order of declaration and then cut the last added value from the string_list for every pop.

I might do this anyway as an exercise, but at this point I'm distracting myself from writing a directory for all event macros.

Thanks for the help and ideas.

;-------

Ok, I didn't want to work on writing event macros, anyway...
Code: easyuo
  1. sub clientAction
  2.    namespace push
  3.    if local_clientAction notin %activeNamespaceList
  4.       namespace local clientAction
  5.    else 2
  6.       str count %activeNamespaceList local_clientAction
  7.       namespace local clientAction . #strres
  8.    set %activeNamespaceList %activeNamespaceList , | , #nstype , _ , #nsname
  9.    ...
  10.    gosub namespacePop clear
  11. return
  12.  
  13. sub namespacePop
  14.    if %1 = clear && %0 = 1
  15.       namespace clear
  16.    str count %activeNamespaceList |
  17.    set #strres #strres - 1
  18.    str left %activeNamespaceList #strres
  19.    set %activeNamespaceList #strres
  20.    namespace pop
  21. return

4
Quote
Generally I abused the stack-style of management knowing that you needed a pop for every push

I just assumed it wasn't recursive, so I didn't test for it. Turns out EUO gets to be recursive, but your scripts can't. It makes a lot more sense now after Gaderian made me test for it.

Quote
allow for persistent namespaces for data required locally throughout a script

I have something like this in a sub I'm designing, but am unsure as of yet if I will just copy variables or declare them in a unique namespace. need more testing to decide.

Quote
perhaps you might be overthinking it a bit

At this point, definitely. I can think why you might need access to NSNAME and NSTYPE, and how you would use them, but have no idea when such complexity would be necessary.

Thanks for the reply. I was feeling like an idiot, now I realize I was just being foolish.

5
lol, thanks. you made me retest it... I didn't expect push/pop to be fully recursive (you know... EUO things and all). thanks for that. exactly what I was looking for. I overlooked something and solved a problem that didn't exist.

6
I, like probably many, was very confused and intimidated by NameSpace management for a long time. I recently started managing sub-variable integrity manually, and the relevance of namespaces finally became clear.

Instead of passing variables %0-%n to a static %sub_variable, and then deleting them at the exit of the sub, EUO already has tools to manage this for you. By declaring a local namespace for the sub and clearing it and recalling the previous namespace, all that legwork is handled for you (for the majority of scenarios).

My question has to do with push/pop and I'm looking for confirmation or correction on what I understand to be limitations. I am not an expert, but I believe I have the logic of namespace worked out.

Quote
*FYI*: For the context of this thread I will assume that any Sub will populate a sub-local namespace, and as such I will purposefully conflate "namespace," with "sub." I want to frame namespace management in the context of sub-local variable management so that namespaces novices like myself can more easily interpret a namespace use case.

This will likely be most people's first experience/need for NameSpace Management. The NameSpace function has more usages than sub-variable management, but grasping this specific usage will translate to understanding when other uses are necessary.

*Properly defining "many," without making assumptions (every sub will populate a sub-local namespace) quickly degrades into a recursive argument nightmare.

For those unfamiliar with NameSpace Push and Pop:
;---------------------------------------------------------------
NameSpace Push saves the current namespace as a temporary variable. Probably something like (pseudo-code) #pushed_nsname|type. All of a namespace's defined child !variables are stored within their parent namespace address, regardless of whether it was "pushed," or not.

NameSpace Pop sets the name space to the LAST "pushed," namespace AND can only be called once per push/pop (EUO seems to clear #pushed_nsname|type when pop is called).

If NameSpace Push is called multiple times before the cursor parses a NameSpace Pop, EUO will overwrite #pushed_nsname|type every time, destroying NameSpace Pop integrity.

As long as a sub maintains a 1:1 relationship, as in the called sub will only be called directly and does not call other subs, Push/Pop works fine.

Example of 1:1:
Code: easyuo
  1. ;current namespace = default namespace = local std
  2. body:
  3. ...
  4. gosub one_to_one
  5. ...
  6. goto body
  7.  
  8. sub one_to_one ;Sub One_To_One will only ever be called directly and never calls other subs.
  9.    namespace push ;Saves the current (local std) namespace, including
  10.                   ;   any defined !variables for recall with pop.
  11.    namespace local one_to_one ;Changes the current (local std) namespace to "local one_to_one."
  12.    ;Sub One_To_One Body.
  13.    ;Do Sub One_To_One things setting local !variables and referencing local !variables
  14.    ;   as well as setting script %variables to be passed to the script,
  15.    ;   and referencing script %variables previously defined.
  16.    ...
  17.    namespace clear ;Deletes all !variables for the current (local one_to_one) namespace.
  18.    namespace pop ;Changes the current (local one_to_one) namespace
  19.                  ;   back to the last_pushed (local std) namespace
  20.                  ;   and restores the stored !variables for it.
  21. return

But as soon as any directly called sub calls an/other sub(s), or a sub can be called directly and/or by an/other sub(s), or both/all (1:many || many:1 || many:many), push/pop integrity breaks down, and namespace integrity must be maintained manually. Luckily EUO also has #system_variables to handle this: #nsname and #nstype.
   *Note: There is more nuance to defining "many," but in the context of this thread,
              where I assume that all subs will populate a sub-local namespace,
              it is safe to assume my definitions above are correct.

My solution for this conundrum, for when I develop a new subroutine, is to assume that all subs will populate a sub-local namespace and have a many:many call relationship and manually store and delete #nsname and #nstype, and edit this out if I want to. Conversely I could assume this is not the case and add this in after the fact, but that doesn't change the solution.

Example solution for all relationship states (1:1 || 1:many || many:1 || many:many):
Code: easyuo
  1. sub many_to_many
  2.    set %many_to_many_nsname #nsname ;store the current #nsname and #nsntype
  3.    set %many_to_many_nstype #nstype ;before populating another namespace
  4.    namespace local many_to_many ;or whatever the sub is named
  5.    ;Do sub many_to_many things
  6.    ...
  7.    namespace clear
  8.    namespace %many_to_many_nstype %many_to_many_nsname
  9.    deletevar %many_to_many_nsname
  10.    deletevar %many_to_many_nstype
  11. return

This solution works the same as push/pop, except with several advantages:
   1. You don't have to know the final state of a sub's namespace relationship (n:n).
   2. It frees up push/pop for specified use elsewhere in your script/subs, if you prefer.
   3. You may ignore the current state of push/pop in publicly published subs.
   4. Each current namespace is permanently stored until all calls are returned.

The only disadvantage I can think of is that it costs 3 more lines/parse processes per potential push/pop, but that is immediately nullified when a potential push/pop push is overwritten.

Back to my original question, am I over-thinking this or is this a relevant solution?
In simpler terms, "Am I doing this right?" Or is there a better way?

Thanks for your time.

7
Quote
Ah, the "kinda-parser" of EasyUO strikes again!  :)
You actually can concatenate in the deletevar parameter, but I've found it only works in specific cases, and even then it sometimes works how you would expect for specific concatenated variables, but sometimes it deletes an address, but not the one you expect/intended.

Basically it breaks down like this:
99% of the time you cannot concatenate within the command parameter, and it will do nothing.
.9% of the time it will work as intended with concatenation
.1% of the time it will delete an address, but not the one you were intending.

The .9% and .1% of cases I've found are when I've defined a *non-specific (as best you can in EUO) reference variable inside the parameter with #dot.

There actually may be a way to make that invalid code work if you concatenate in a specific order including outside of the parameter, but I doubt it. I could be wrong as EUO often makes you think you know how it works, but in reality you don't. I need to do a little more testing first.

I'll do a full write up on concatenation, nondescript-reference variables and deletevar once I have it all worked out in EUO.

edit added:
Quote
The hardest part of writing my own EasyUO parser for ScriptUO
I can't imagine the length of the migraine while building ScriptUO. This was about a 6 hour migraine for me... probably ~15 minutes of actually writing test code, and the rest of the 6 hours rubbing my brow (VERY intensely) with my head down and eyes closed while muttering nonsense.

8
for anyone who actually bothers to read what I wrote, I was completely wrong about how the command deletevar works in EUO. while it does delete the specified variable, you cannot concatenate within the command parameter.

invalid code:
Code: [Select]
deletevar %sbodid . %i
there are a few options to delete these variables.
1. namespace management would be the simplest in terms of effort.
2. manually delete each entry made with a hardcode. This would be excruciatingly arduous.
3. settle for "set %variable   ," which stores the value " ," that's not #spc, it's literally a blank string, and the address remains active. this is fine in 99% of situations

9
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=30

Quote
last post from Gaderian for some context
Quote
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.

Quote
... #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:
Code: [Select]
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:
Code: [Select]
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:
Code: [Select]
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:
Code: [Select]
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:
Code: [Select]
%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:
Code: [Select]
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:
Code: [Select]
;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.

Quote
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:
Code: [Select]
;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.

Quote
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?

Quote
finditem TYPE Index location

I am unsure of what exactly you are expressing here. If this is still relevant, please post an example.


10
Scripting Chat / Re: OSI tester Needed. Mining with Fire Beetle. ~5 minutes.
« on: September 18, 2021, 02:09:49 PM »
Quote
everything without any filtering in your container/ground search

this is basically it. * isn't really a parameter, it's just a modifier for finditem when you don't want to define what you're searching for, but do want to define where you are searching,

Example:
Code: [Select]
finditem c_ , #backpackidfinditem assumes that is parameter 1 i.e. what to search for, and it will find your backpack on your paperdoll #findcnt = 1 #bagid = #charid

using the * mods finditem so that the first parameter in the call is where to search.

so for your example, you could have done something like:
Code: [Select]
;run this with an "empty" backpack... no bods, no extra stuff
finditem * c_ , #backpackid
for #findindex 1 #findcnt
   ignoreitem #findid
or made a list and added an if_not check in your finditem_check_for_craft
these are not necessarily better options... just other options, but in that last example finditem would return everything that is in your backpack.

as to your other point about keeping track of %sbodindex/cnt. I usually index at mnimum #findid as well, and just put everything in a big for loop, that way I don't have to finditem again every time I want to open a BOD.

Code: [Select]
for #findindex 1 #findcnt ​
  ​set %sbodid . #findindex #findid
set  %sbodcnt #findcnt
;then you just use your counter or a for() to set the id every cycle
if %sbod_index > %sbod_count
  break
else
   set %current_sbod %sbodid . %sbod_index

what's the command for that EUO code output?

added: I'm actually working on a finditem sub for storing multiple finditem arrays with chosen #findresults to parse against, but all of a sudden it's started "eating" one of my passed values in the middle of the sub and I can't figure out why, yet.

edit. just wanted to add about my previous post. I sort of knew how * worked, but I've never tried to describe it before, and on top of that I haven't touched a script or talked to anyone abut scripting for about 3 years. out of practice, and a bit out of touch lol. sorry if I confused you or seemed like an idiot before.

11
Scripting Chat / Re: OSI tester Needed. Mining with Fire Beetle. ~5 minutes.
« on: September 18, 2021, 11:16:51 AM »
lol. I was hoping that wouldn't happen. now I need to write like 3 separate parts to test thing individually. I just wrote that up real fast last night hoping that wouldn't happen, but you know... Murphy's law never seems to fail haha.

well, thank you for taking the time.

12
Scripting Chat / Re: OSI tester Needed. Mining with Fire Beetle. ~5 minutes.
« on: September 18, 2021, 10:17:29 AM »
thanks for testing it. I might refine the output so I can figure out exactly where it failed, that output wasn't very precise.

did it fail immediately or after a little bit?

13
Scripting Chat / Re: OSI tester Needed. Mining with Fire Beetle. ~5 minutes.
« on: September 17, 2021, 09:38:37 PM »
from EUO wiki:
Quote
If * is used instead of an id or an index, all items of all types will be returned.

I really don't know. In my experience,
Code: [Select]
finditem
returns everything everywhere.

apparently
Code: [Select]
finditem *does as well.

I just used the * when I first started writing scripts like 5 years ago, and have used
Code: [Select]
finditem %string * c/g_ , %modfor thousands of continuous hours, so I just stopped worrying about it.
it might add the A modifier if you just use the star. I really don't know lol.

*edit: I guess it if you don't use [parameter 1].
Code: [Select]
finditem * c/g_ , %modI have used it like that, but I always use it unless I just use
Code: [Select]
finditemalone


and thanks crisis. it's probably either going to fail in the wrong spot, or work as intended.

14
Scripting Chat / OSI tester Needed. Mining with Fire Beetle. ~5 minutes.
« on: September 17, 2021, 06:47:20 PM »
I was wondering if someone with an OSI account with a miner and a fire beetle could try a little bit of test code for me? I was sort of asking about this a few years ago when I was working on my miner for my FS, and I am still curious. The whole test will take roughly 5 minutes if you have a miner and fire beetle ready to go. Let me know if there are any issues with script execution.

Test code:
Code: [Select]
;just copy this code, grab a shovel and your fire beetle
;and head to the nearest cave.
;hit the dirt once, and if you pull up some ore, press play
set #lpc 100
set %oretypes TVJ_EWJ_DWJ_GWJ

finditem OHP * g
set %fireBeetleID #findid

set %shovel #lobjectid
set %mtile #ltargettile
set %mkind #ltargetkind
set %mx #ltargetx
set %my #ltargety
set %mz #ltargetz

finditem %oretypes * c_ , #backpackid
 if #findcnt > 0 6
   set #lobjectid #findid
   event macro 17
   set #ltargetid %fireBeetleID
   set #ltargetkind 1
   target
   event macro 22

wait 30
   
loop:
   set #lobjectid %shovel
   event macro 17
   set #ltargettile %mtile
   set #ltargetkind %mkind
   set #ltargetx %mx
   set #ltargety %my
   set #ltargetz %mz
   while #targcurs <> 1
      gosub scan journal
   event macro 22
   finditem %oretypes * c_ , #backpackid
   if #findcnt > 0 6
      set #lobjectid #findid
      event macro 17
      set #ltargetid %fireBeetleID
      set #ltargetkind 1
      while #targcurs <> 1
         gosub scanjournal
      event macro 22
   repeat
      gosub scanjournal
      finditem %oretypes * c_ , #backpackid
   until #findcnt > 0 || you_loosen in #journal
goto loop

sub scanjournal
   scanjournal #jindex
   if you_must in #journal 2
      display Test failed! you cannot dig>smelt>dig>smelt>... on OSI
      halt
   if there_is_no in #journal 2
      display Success! you can dig>smelt>dig>smelt>... on OSI
      halt
return

15
New member introductions / Re: Hello Script UO
« on: September 17, 2021, 06:43:56 AM »
Hello again! It's been a long while, so I thought I'd "re-introduce," myself.

I stopped playing Ultima about 3 years ago as life got busy for myself as well as for my IRL friend who got me into the Free Shard he was on. On top of that the server owner started making changes that I found less enjoyable, so I just left. I'm between jobs right now, and found myself with a lot of free time and fired up Ultima and EasyUO to work on some unfinished business that had been bothering me. I also wanted to say thanks to TrailMyx for maintaining the site and providing the forum.

From the help of many here I was able to go from a scripting novice, where my scripts would memory leak to no end causing constant client crashes and Windows BSODs every 3-5 days, to the point where I can run several scripts that do several things almost endlessly (weeks to months) before a client crash. And no more BSODs. Thanks for your patience and willingness to help, EN.

I wouldn't really consider myself a player as much as a scripter. I find much more satisfaction from the challenges of how to script something than from playing. I don't know how long I'll be around this time, but I've invested several thousands of hours into EasyUO over the years, and am working on some subs that I'd like to share once I get some testing and/or logic done.

I left before with a handful of scripts ~90% complete, (miner, logger, BOD sorter, BOD filler/turn-in, and a bunch of stand-alone helper scripts for certain tasks). All in working order and decent enough to share if I wanted to. But there was always one nagging issue that I didn't want to tackle at the time. I knew how to solve it, but I also knew it would require restructuring my scripts from the ground up and that was too daunting at the time. Now, after 3 years, I am no longer invested in my previous scripts and it feels "fresh."

I play on an AFK friendly FS (great place for script testing/writing) that's based in Sweden. I live near west coast US. My ping varies from 250-350ms regularly with spikes from 700-1500ms, AND I often lose connection. My scripts work just fine in a vacuum, but not in reality where the server I'm connecting to is thousands of miles away across an ocean.

I've solved ping for basically any situation (exevent drag/drop is the only action I can think of where I have to use a "static," wait time with sufficient tolerance, as I have not found some type of confirmation in EasyUO), but losing connection was the big issue. Reconnecting is easy, but to truly tackle the issue requires structuring scripts so that connection is the focal point for every client interaction. If stable, full automation is the goal.

The big sub I'm working on right now I call Sub ClientAction, where every client action is funneled into a singular varCheck that checks for connection and reconnects if lost and your script picks up at or near where it left off. The goal is to minimize client spam and bifurcate all client interactions from the EasyUO logic, so that EasyUO keeps itself busy, rather than spamming the client if connection is lost.

A simple example of a call:
instead of
Code: [Select]
event macro 8 7
while #contid <> #backpackid
   wait
you would
Code: [Select]
gosub clientAction open backpackAnd if connection is lost before the backpack opens, Sub ClientAction would automatically reconnect, attempt again to open the backpack, and then return once successful. The script/client having been none the wiser.

I'm reaching the point where I'm polishing the first-ish draft, but I won't post it until I do a write-up which will likely take me a full days work, as it includes a few sub-subs and at least one handler sub. And I still need to decide how to handle click actions for crafting/other multi-click-action gumps. That's not happening soon. Maybe in a week or two. I'll start a discussion thread about it once I start working on the write-up. Maybe within a few days time. I'm very interested in any/all feedback, critical or otherwise.

My main focus right now is this sub, and other "operational" functionality, as well as the ins/outs of beating EasyUO into submission. I think most can agree, it is somewhat limited in terms of expected functionality (like subs not being true localized functions), but it is also VERY robust and provides ample work-arounds for any perceived short-comings. And that also adds to the enjoyment (or maybe headache ;)) of scripting in EasyUO, and I am looking forward to hopefully discussing these topics and more with everyone here, again.

Well... that's about it for my "re-introduction," sorry for the long-winded post, resurrecting a "dead," thread and probably/partially off-topic directory. Thanks to those who bothered to read it.

And thanks again, TM!

Pages: [1] 2 3 ... 5