ScriptUO
Official ScriptUO EasyUO Scripts => Scripting Chat => Topic started by: lydaan on December 29, 2015, 07:36:32 PM
-
As I've been working on my mule script and specifically the endless tinker sub and the dig routine, I find myself becoming very accustomed with the limitations of finditem and event property... specifically the update lag that exists... ESPECIALLY in #property. I know setting LPC really high will not effect the ability of these 2 to process info, but as cheffe eluded, finditem takes about 18.5 lines of the 20 alotted? i think? just due to the length of time to process and the length (in time) of a cycle. Do you think setting LPC to 1 or 2 would give finditem enough time to fully process before the next few lines were read?
As an example, I think I could eat the time by reducing a wait timer, since EUO does nothing during waits, and gives those cycles to the OS, setting LPC to 1 or 2 seems like a better use of that downtime, especially since it's only 1/20 of a second.
Sample current "code:"
sub dig
repeat
finditem shovel
if no shovel
make shovel
dig
wait 6
scan journal for stuff
wait 8
until forever
return
Now with an lpc adjustment:
sub dig
repeate
lpc 2
finditem shovel ;1
lpc 10? ;2
if no shovel
make shovel
dig
wait 6
scan journal for stuff
WAIT 7 ;<--------- reduced by 1
until forever
return
While I think this might help finditem, and would only really be neccesary in extreme cases, I don't think it would help event property/#property as it feels like that update is server response related, and limited to ping.
I'll probably fart around with this on my endless tinker sub, and think of someways to speed test finditem update...
-
I'll probably fart around with this on my endless tinker sub, and think of someways to speed test finditem update...
set %x #systime
finditem blabla
set %y #systime - %x
display %y time passed
halt
-
I'll probably fart around with this on my endless tinker sub, and think of someways to speed test finditem update...
set %x #systime
finditem blabla
set %y #systime - %x
display %y time passed
halt
AHAHH.... derr... thanks for that, but I was also thinking it might be server dependant?
-
well the response is server and client dependent.. but that will be different on every machine and connection and the number of items in findable distance when you search ... But you can get an average for youself
-
Was just going to edit my last post...
here's what I'm experiencing my dig loop has a full wait of 14, or ~700ms, with a finditem and a #findcnt=0 check at the top. Sometimes it loops two full times before #findcnt is updated, probably 60/40 2loops/1loop... roughly an average of 1.1 seconds
About 30% of the time my first scanjournal for "you have worn..." at wait ~6 or ~300ms triggers gosub shovel, and adding a second one @ wait 8 or ~400ms after that, ~700ms total brings the scanjournal success rate to about 90%, resulting in finditem accounting for that last 10% as a failsafe
my brain is jello at this point, after cleaning up my script all day... but I think I'm saying what I mean to... :-\
-
Was just going to edit my last post...
here's what I'm experiencing my dig loop has a full wait of 14, or ~700ms, with a finditem and a #findcnt=0 check at the top. Sometimes it loops two full times before #findcnt is updated, probably 60/40 2loops/1loop... roughly an average of 1.1 seconds
About 30% of the time my first scanjournal for "you have worn..." at wait ~6 or ~300ms triggers gosub shovel, and adding a second one @ wait 8 or ~400ms after that, ~700ms total brings the scanjournal success rate to about 90%, resulting in finditem accounting for that last 10% as a failsafe
my brain is jello at this point, after cleaning up my script all day... but I think I'm saying what I mean to... :-\
Well without seeing your code...kinda hard to know what your talking about... but sounds like your happy with the results.
-
Alirght... here's my dig loop... as I posted in my Mulchine thread, just trying to make that script, and specifically this sub as fast as possible:
Notes:
wait 14 does not post "you must wait..." for any action on my FS, and atleast appears to dig faster than wait 20 (<14 seems to skip loops every now and then)
%digjournal <6 skips veins... have not *seen* it skip any with wait 6
set %digloopglobalwait 14
set %digjournalwait 6
set %digloopwait %digloopglobalwait - %digjournalwait
sub dig
repeat
{
if #weight > %carryweight
{
gosub travel home
gosub secops
gosub travel back
gosub dig <---- overweight fail-safe
}
finditem %digtools * c_ , #backpackid
set %shovcheck #findcnt
set #lobjectid #findid
set #ltargetx %digx
set #ltargety %digy
set #ltargetz %digz
set #ltargetkind %dkind
set #ltargettile %dtile
if %shovcheck = 0
gosub tinkershovel
event sysmessage mining at Book %bookcnt Rune %runecnt Vein %onvein
finditem %digtools * c_ , #backpackid
set #lobjectid #findid
event macro 17 0
target
event macro 22 0
wait %digjournalwait
scanjournal 1
if You_have_worn in #journal
gosub tinker
if There_is_no in #journal
{
if #weight > %nrweight && %onvein = %veincnt && %stripmine = no ;travels to secure THEN NEXT RUNE if on the last vein of the rune and weight is CLOSE to max... EFFICIENCY!!!
{
event sysmessage Stripmining? %stripmine
gosub travel home
gosub secops
}
goto nextrune
}
if #weight > %carryweight
{
gosub travel home
gosub secops
gosub travel back
gosub dig
}
if That_is_too in #journal || Target_cannot in #journal ;will iterate trhough all veins at a rune, then next rune until...
{
event sysmessage Whoops, travel broke... HOLD ON
gosub travel nextrune %runecnt
goto nextrune
}
wait %digloopwait
scanjournal 1
if You_have_worn_out in #journal
{
event sysmessage journal tool check %shovcheck
gosub tinkershovel
}
}
until %theendoftime = now
event sysmessage THE END OF TIME IS NOW!!!
return
-
ahhh.... nooooooooooooooooooooooooooo recursion.
Ok you have a number of issues to fix in this code.
(1) Journal -- Journal scanning can be tricky ... journal messages take time to appear. Therefor you have to wait for them. So you need a loop that checks journal for x ms waiting for what you need to see and then moves on. For example of some advanced journal useage see TMs journal subs.. or I have some as well but they are buried in other code without a write up.
(2) Recursions --- the sub dig calls itself from a number of places... not good .. means over time more and more memory is used .. run it longer enough and it will burn up all available memory. + its not necessary ie the if #weight > %carryweight calls dig but if you just removed the Gosub dig line it would loop back to the beginning of dig anyways !!! + you have this same code repeated at start of repeat loop and near end.
(3) gotos out of a sub ... goto nextrune .. nextrune is not in the sub dig therefor it can never return to this spot and eats memory like (1).
Sorry cannot help myself... nitpicking .. but do check out tms journal subs will help you.
-
ahhh.... nooooooooooooooooooooooooooo recursion.
Ok you have a number of issues to fix in this code.
HAHAHA ;)
I know my skills suck :P and have much to learn... I can take the criticism, please enlighten me! Willing and eager to learn!!! Learning on the fly, here... really just started writing script (yes, singular... onlly one semi-legitimate script so far) about a month ago.
(1) Journal -- Journal scanning can be tricky ... journal messages take time to appear. Therefor you have to wait for them. So you need a loop that checks journal for x ms waiting for what you need to see and then moves on. For example of some advanced journal useage see TMs journal subs.. or I have some as well but they are buried in other code without a write up.
Just worked that out to some extent in my travel sub... not perfect, but works for my mule for now, I realize that i really should be using for loops for journal scans, but scanjournal has been causing me to smash my face on my keyboard for about a week, and I'm working up to spending the time and care it really needs...
Here's what I did in my travel sub just now:
recover:
manarecallwait:
if #mana < 10
goto manarecallwait
spcrwait:
set %endcrwait #systime
set %checkcrwait %endcrwait - %startcrwait
if %checkcrwait < %spcr
goto spcrwait
event macro 15 31 ;recall
target 5s
event macro 22 0
set %jupdate #jindex
set %startcrwait #systime
set %closerbx #contposx + 250
set %closerby #contposy + 130
if #contsize = 452_236
click %closerbx %closerby r
jindexupdatewait:
if #jindex = %jupdate <----------------------- journal update wait!
{
if %xcheck <> #charposx || %ycheck <> #charposy
return
goto jindexupdatewait
}
scanjournal 1
if That_location in #journal
return
if More_reagents in #journal || You have_not in #journal
goto recover
return
(2) Recursions --- the sub dig calls itself from a number of places... not good .. means over time more and more memory is used .. run it longer enough and it will burn up all available memory. + its not necessary ie the if #weight > %carryweight calls dig but if you just removed the Gosub dig line it would loop back to the beginning of dig anyways !!! + you have this same code repeated at start of repeat loop and near end.
LOL!!!! literally LOL!!!
I did a triple take on that a few times when I was posting it, lmao... I get tired at the end of the night, and I just fix any errors in my scripts with the first thing I think of.
I can tell you why I did that, and it's because of finditem fails AND that's one of the many finditem fails that caused me to start this thread... sometimes when my mule drops ore at secure, finditem just fails and and my for #findindex 1 #findcnt just misses one... I tried for #findindex 0 #findcnt for a couple hours a couple weeks ago, but finally realized that it didn't really add one, just probably posted an N/A in the background, and like you've pointed out... probably a memory leak.
Again, i find it hilarious you called me on that... as I was posting it, I literally was thinking *I really should make that "finditem ore" loop until finditem updates correctly* ;)
(3) gotos out of a sub ... goto nextrune .. nextrune is not in the sub dig therefor...
OK, so I was a bit miffed ??? by this at first, but...
AHA! :o
(so I wrote that like a month ago, and it was literally my first excursion into actual looping script writing :-\ )
But I think I've got it figured out, so here's THAT PART f what I have, and then the fix:
sub rune
{
set %runecnt %1
set %veincnt %2
set %onvein %3
set %digx %4
set %digy %5
set %digz %6
set %dkind %7
set %dtile %8
if %onvein = 1
gosub travel nextrune %runecnt
gosub dig
nextrune: <------------ the goto's target
continue
}
return
...
if #weight > %carryweight
{
if #weight > %nrweight && %onvein = %veincnt && %stripmine = no
{
event sysmessage Stripmining? %stripmine
gosub travel home
gosub secops
}
goto nextrune <------------------ the goto in question
}
and the fix:
sub rune
{
set %runecnt %1
set %veincnt %2
set %onvein %3
set %digx %4
set %digy %5
set %digz %6
set %dkind %7
set %dtile %8
if %onvein = 1
gosub travel nextrune %runecnt
gosub dig <------------ sub dig>return goes where I wanted the goto to go, anyway!!!! :D
continue
}
return
...
if There_is_no in #journal
{
if #weight > %nrweight && %onvein = %veincnt && %stripmine = no
{
event sysmessage Stripmining? %stripmine
gosub travel home
gosub secops
}
return <------- sub dig return
}
I literraly had NO idea how...
sub blahblahblah
return
...worked when I wrote that, and so I used goto... (first few days I just put return because I thought it needed it before realizing that leaving out return is like having an if with only an "{") THANK YOU FOR POINTING THAT OUT! :D
LMAO!!! I actually find this hilarious...
it can never return to this spot and eats memory like (1).
so, I'm assuming my other 2 weightchecks should ALSO return rather than gosub... which isn't really waht I want it to do... I'll figure that out... again, THANK YOU!
Sorry cannot help myself... nitpicking .. but do check out tms journal subs will help you.
NOOOOO!!!!! Please do nitpick!!! I've looked over your library as well as TM's, and at somepoint I'll probably go over everyone's... Spent a couple hours earlier looking over 12x's mining script, and reading the forum thread until it was just bug fixes... (that mining script was the only thing I've really been able to understand, so far, as that's the only thing I've really written... still learning... hard to translate, when you don't even understand the language you're reading)
[jk ;sorta]
But seriously...
MEMORY LEAKS???
first off... I'm fairly detatched from this with 16gb of RAM.. I realize that memory leaks are like the plague and NO amount of RAM will ultimately protect from leaks... especially with software like EUO, where enhanced memory detection/correction was doubtfully implememnted...
And SECONDLY... we're talking about a 35/19 year old game... MEMORY LEAKS??? Yes, I remember having 64mb of RAM and an 80gb HDD... but the memory leaks you're talking about would take something like a week for Windows Task Manager to even register... ---> .01gb!!!!
[/jk]
Seriously, tho... I really do appreciate the time you've given me on this subject... I really am hoping to learn techniques that apply to RL programming, and I'm glad you've pointed out the things you have. ;D
I was just rereading Cheffe's tut on LPC: http://wiki.easyuo.com/index.php?title=Tutorials:Cheffe1 (http://wiki.easyuo.com/index.php?title=Tutorials:Cheffe1)
and he pretty much says what I was thinking about doing... I probably thought of that, because he said it...
-----------------------
Hey EN!
Just wanted to say Thanks again... i just realized what you were saying about waiting for the journal to update... going to work that in the dig sub... that might actually the fix the sub 50ms variance (AND get rid of the finditem that was pissing me off) I've been wanting to fix!!!! :o
AND...
wanted to ask about goto's... since I use them a lot... as long as they goto a a blahblah: in the same sub, they're fine? because that would fix the other 2 gosubs in my dig sub...
-
Valid test code Enters and leaves sub with a goto inside sub.
gosub test ; execute order 1
; this is the last line executed prior to halt. ; execute order 9
halt ; execute order 10
sub test
loop: ; execute order 2 ; execute order 6
if %something = N/A ; execute order 3 ; execute order 7
{
set %something YES ; execute order 4
goto loop ; execute order 5
}
return ; execute order 8
Invalid code will leak memory how much depends on how bad and how long you run it for. I used to run scripts for weeks or months at a time.. so smallest leak builds up and ive got 32gb of ram.
gosub test ; execute order 1 ; execute order 10
; this is the last line executed prior to halt. ; execute order NEVER
halt ; execute order NEVER
sub test
if %something = N/A ; execute order 2 ; execute order 7 ; execute order 11 .....
{
set %something YES ; execute order 3
goto loop ; execute order 4
}
return ; execute order 8
loop: ; execute order 5
gosub test ; execute order 6
; no halt command script goes to line 1 ; execute order 9
-
HAHA thanks for putting in my place about mem leaks...
another question on that notion...
my dig sub never returns...
sub dig
repeat
until %theendoftime = now
return
mem leak issue?
i think of it as a folding/joining loop...
script runs into the "main" loop which goes into the digloop, and never leaves... repeating the main loop over and over again inside the dig loop
--------------
wait... the return discussed above will push the cursor out of the loop... nevermind, i think
---------------------------
Alright... had a HAHA moment about my dig sub and that return....
since my dig loop loops indefinitely (well atleast until %theendoftime = now) and only returns after "There_is_no_metal_here_to_mine"... ;D is there even a reason to have that return at the "end" of the sub? (failed journal catch will cause it to hang either way....)
Like this:
sub dig
repeat
*dig fool*
if There_is_no in #journal
return
until %theendoftime = now
; return <--------------- don't need this :P
-----------------------
WEEEElP.... EN, you were right.... tried to maximize a client window last night and windows said there was no more memory and it crashed lol.... fixed my script after that.... thanks a lot for the help
-
sub dig
repeat
*dig fool*
if There_is_no in #journal
return
until %theendoftime = now
; return <--------------- don't need this :P
Well above is a minor leak as well... Think of it as a stack of paper every time you "gosub" or "for" or "repeat" you add a sheet of paper on the stack. When you return or end the loop legally via "break" or loop condition met you remove a sheet of paper.
So above code you gosub dig +1 piece of paper, you Repeat +2 paper in stack, you Return inside repeat loop -1 paper, Stack now = 1. You cannot ever now remove that one piece of paper as you didn't end the Repeat,Until loop. Call dig again exit same way again stack now +2 that can never be removed. IE slowly using unrecoverable memory. = memory leak.
All you have to do is think how can i write it so that I only EVER need a SINGLE return in the sub. IE have a valid exit condition on the repeat until loop. Here are a couple ways of doing this...
sub dig
set %ExitLoop = NO
repeat
*dig fool*
if There_is_no in #journal
set %ExitLoop = YES
until %ExitLoop = YES
return
sub dig
repeat
*dig fool*
until There_is_no in #journal
return
Now you may say I needed that repeat until never ending as thats the main loop of my script. I always create a mainloop outside of the actual action ie
gosub Mainloop
Halt
Sub Mainloop
set %HaltScript #false
repeat
gosub Dig
; Check for halt conditions .. not logged in etc
until %HaltScript = #True
Return
sub Dig
; dig stuff
return
TO Be clear ... in most scripts posted you will find these minor memory leaks even by some of the best scriptors. Almost every scriptors take shortcuts like this ... and as you said prior it doesn't really matter as you are not running continuous 24x7 x 365 and you have boat loads of ram. But I think its good practice to have a logical flow and that way your scripts perform how you expect...
The main pitfalls to avoid is:
- REcursion --- Dont have a sub call itself with out an obvious way to exit (thats when the memory leaks pile up fast)
- GOTO -- do not goto out of a sub
- RETURN -- try to have only one exit point "REturn" from a sub preferably at the end .. ie sub..code..return not sub .. code.. if x=y return.. code
-
so... speed is what i was after... i wanted it to move to the nextvein as fast as possible without glitching, and I found wait 6 ( in the middle of the dig loop) to be the minimum to read the journal without it doubling the if check result... so I guess I'd like to do something like:
sub dig
repeat
*dig*
wait 6
if there_is_no in #journal
{
set %something #true
goto skipwait
}
wait 8
skipwait:
until %something = #true
return
------------
I dont know if you saw my edit above... posted it as you were posting... but my client crashed last night after 4 solid days of running the script...
-
so... speed is what i was after... i wanted it to move to the nextvein as fast as possible without glitching, and I found wait 6 ( in the middle of the dig loop) to be the minimum to read the journal without it doubling the if check result... so I guess I'd like to do something like:
sub dig
repeat
*dig*
wait 6
if there_is_no in #journal
{
set %something #true
goto skipwait
}
wait 8
skipwait:
until %something = #true
return
------------
I dont know if you saw my edit above... posted it as you were posting... but my client crashed last night after 4 solid days of running the script...
The problem you will have here is how about if thier are more than one journal entries posted and the one you are looking for is older you wont see it. ??
sub dig
set %something #false ; set exit condition negative
repeat
set %MyJINDEX #Jindex ; set journal start point
*dig*
set %WaitTime #Systime + 6 ; set max wait time
set %OreFOund #False
repeat
if #Jindex > %MyJindex ; new journal entry
{
set %MyEndJindex #Jindex
For %c %MyJindex %MyEndJindex ; Loop though all the new journal entries
{
scanJournal %c
if there_is_no in #journal
set %something #true
if ....... in #Jounral ; set condition of text for ore found so exits journal wait loop
set %OreFound #True
}
set %MyJindex %MyEndJindex
}
until #systime >= %WaitTime || %something = #true || %OreFound = #True
until %something = #true
return
-
The problem you will have here is how about it thier are more than one journal entries posted and the one you are looking for is older you wont see it. ??
yes... that was *make believe code* going to work on a waitfor journal update sub or insert.... as I said somewhere up top before... scan journal is something I want to master... but have not taken the time to yet... I'll get it.
Thank you for that example, I know I will be looking at that when writing the journal wait/scan journal stuff...
the ultimate goal with this dig loop is to ratchet it down as tight as possible, and I really need to do some tests on for loops, or possibly multiple singular scanjournals nested in ifs... not sure what i want to do here, and not really looking forward to it, as I'm starting to get burned out.
my miner script is getting to the point that little changes keep breaking it, and I'm getting pissed...
^^^^^^^ I keep fixing things and my little crap fixes break...
-
LOL hang in their sometimes its just easier to paste in some code you know works... ie TM journal subs... http://www.scriptuo.com/index.php?topic=33.0
Its common to break your own script... I do it all the time... I often add lines that read display ok gOt here and x = %x and further down display ok got here 2 and x = %x or such stuff just so i can figure out whats happening....
-
So for EN and anyone else interested... I've figured out how I wanted to do my journal update wait.
If TM's sub is the "Advanced," version... then this is the "get a bigger hammer" remedial version of journal scanning:
event sysmessage mining at Book %bookcnt Rune %runecnt Vein %onvein
finditem %digtools * c_ , #backpackid
set #lobjectid #findid
set %jupdate #jindex + 1
event macro 17 0
target
event macro 22 0
set %digwaitbegin #systime
...
jup:
scanjournal #jindex
if There_is_no in #journal
{
if #weight > %nrweight && %onvein = %veincnt && %stripmine = no
{
gosub travel home
gosub secops
}
set %stopdigging now
goto stopdigging
}
if You_have_worn in #journal
{
gosub checkingots
gosub tinker shovel
}
if That_is_too in #journal || Target_cannot in #journal
{
event sysmessage Whoops, travel broke... HOLD ON
gosub travel nextrune %runecnt
set %stopdigging now
goto stopdigging
}
set %endcheck #systime - %digloopwaitcheck
set %digwaitend ( #systime - %digwaitbegin )
if %digwaitend > 300 && %endcheck > 980
{
;event sysmessage %digwatend | %endcheck
goto keepdigging
}
goto jup
The only way I've broken it so far is if I spam event sysmessages during the update loop... I believe it should be fast enough to read through the global chat spam on my server... and if not, I'll just turn global chat off...
*edit* oh, and by moving to scanjournal dependant catches, I was able to improve my move to nextvein rate by about 30%... it catches the "no_metal" at about an average of 200ms (was a "wait 6..." ~315ms), and moves to the nextvein at an average of about 650-750ms.
Pretty happy with the results