How to allow function() to finish before continuing?

Posted by Blixel on Fri 04 Feb 2022 08:29 PM — 5 posts, 19,642 views.

#0
When my character is in a town, I always buy healing flasks and other consumables before heading back out into the dungeon. When I'm in a town, I am in a safe place, nothing can attack me. I have a lua function called topUpFlasks() which just buys as many healing flasks as my character can hold. At the moment, I have a wait.time() immediately after topUpFlasks() so that my script will give the character enough time to buy flasks before moving further into the script. This works reasonably well, but it's not ideal ... and if something goes wrong and it ends up taking longer than wait.time() allowed, it gets messy fast. (So I have to increase wait.time() even more ... and then I end up having long, unnecessary delays 99% of the time when everything goes right.)

So my question is, is it possible to call a function from my script in such a way as to allow the function to finish and return before it goes further?

topUpFlasks() -- this needs to happen first
countFlasks() -- this doesn't make sense until topUpFlasks() is done
goAdventure() -- I'd rather not be out on an adventure while the script is still trying to buy and count healing flasks ... especially when we aren't even in town any longer
#1
I've figured something out for this question, though I'm still interested if anyone has any better ideas. But here's my method at the moment and it seems to be working. This isn't actual code from my script, but this is the exact concept:


topUpFlasksReturn = false
topUpFlasks()
repeat
    wait.time(0.05)
until (topUpFlasksReturn == true or allStop == true)


At the very end of the topUpFlasks() function, I have topUpFlasksReturn = true. So the idea is that MUSHclient will sit in the repeat until loop until topUpFlasks() is done. (The allStop variable is something I use throughout my script to stop everything if I ever type "allstop" into MUSHclient. It's like an emergency stop.)
Amended on Mon 07 Feb 2022 12:16 AM by Blixel
Australia Forum Administrator #2

Personally I would be waiting for a message to say that the flask was full, rather than waiting for a certain amount of time.

So my question is, is it possible to call a function from my script in such a way as to allow the function to finish and return before it goes further?

Well, how do you know that the function has finished?

#3
Nick Gammon said:
Personally I would be waiting for a message to say that the flask was full, rather than waiting for a certain amount of time.


When I'm buying flasks, I enable a trigger that looks for the text variations that I know are possible such as not being able to afford them:
^\>?(.*)I\'m sorry, but you don\'t have enough gold to buy that\.$|^\>?(.*)Sorry, but you can\'t afford that\.$


Or letting me know when I'm maxed out (which is the preferred and most common outcome):

^\>?You are overloaded\.$


This works fine, but if I want this to be inside of a function, the problem I'm having is that the script doesn't wait for the function to finish before moving on to the rest of the script. The reason I want to use a function is because I have many places in my script where I buy flasks, so I want to have a single function where I update that code.


function topUpFlasks()

	require "wait"

	wait.make (function ()

		if (stopAdventuring == false) then  
			buyFlasks()
			wait.time(buyFlasksDelay)
			EnableTrigger("HealthCheckMax", true)
			Send("health")
			wait.time(healthCheckDelay)
			countFlasksCommand()
			wait.time(minorActionDelay)
			EnableTrigger("HealthCheckMax", false)
			if (flaskCount == 0) then
				ColourNote("white", "red", "Your inventory is full. You can't carry any healing flasks. Exiting...")
				allStop()
				wait.time(minorActionDelay)
				Send("x")
				topUpFlasksReturn = true
				return false
			end
		end

		topUpFlasksReturn = true
		return true

	end)

end


In the above function, I've added these "topUpFlasksReturn" statements to let me know when the function is done. And then as you saw in my second post, I have a repeat-until loop waiting for topUpFlasksReturn to become true before leaving the loop. It's crude, but it seems to work in lieu of a better idea.



Nick Gammon said:
Well, how do you know that the function has finished?


Typically I know a function has finished when the function returns, but with this type of programming ... it seems as though the script moves on to the next line as soon as the function is called as opposed to waiting until the function returns.
Australia Forum Administrator #4

Yes, but you can wait for output as well as time, as described here.

So if you send something to “buy flasks” then you can wait for a response, and using the “or” feature of regular expressions you could wait for this or that response.

Or, timeout if you got neither.