Что нового

Как прервать выполнение цепочки функций и вернуться в цикл ожидания GUIGetMsg?

SurikenTSD

Новичок
Сообщения
67
Репутация
1
Сделал GUI для своего скрипта. При нажатии одной кнопочки запускается функция, которая в свою очередь запускает несколько других функций. В одной из функций есть цикл, в котором, если один из параметров меняется до окончания цикла, вызывается другая функция для приведения этого параметра в норму... и так далее, и тому подобное.
Если вызванная функция не может привести этот параметр в норму, значит произошло такое стечение обстоятельств, что с помощью скрипта ничего не сделаешь - необходимо вмешательство пользователя. Как в таком случае прервать выполнение цепочки этих функций и вернуться в цикл ожидания GUIGetMsg() ?
В случае моего скрипта тупо воткнуть Exit, чтобы закрылся скрипт с GUI, не вариант...
Помогите, пожалуйста, дельным советом. А то сижу уже час втыкаю в монитор и все не могу придумать выход из сложившейся ситуации...


Добавлено:
Сообщение автоматически объединено:

Вот, если бы это был Basic, который я лет 100 назад "изучал" буквально пару минут на уроке "информатики", я бы воспользовался GoTo, но в Autoit его нету...
 

Belfigor

Модератор
Локальный модератор
Сообщения
3 596
Репутация
938
Ты создал вермишель. Я бы на твоем месте переписал скрипт с нуля. Иначе последующая доработка придет к систематической приставке костылей.
 
Автор
S

SurikenTSD

Новичок
Сообщения
67
Репутация
1
Ну так это мой первый скрипт. Костыли это даже хорошо - чем больше раз ударюсь, тем умнее буду в будущем.
 

_ToBe_

Осваивающий
Сообщения
142
Репутация
34
Согласен с Уважаемым Белфигором
Сам тоже начинал с лапши :D

А по теме... Не надо из одной функции вызывать вторую, третью ... десятую. Делай всё постепенно:

Код:
$gui = GUICreate("GuGuGui", 100, 100)
GUISetState(@SW_SHOW)

While 1 
	$msg = GUIGetMsg()
	If $msg = $GUI_EVENT_CLOSE Then Exit
	
		_function1()
		If $var = 7 Then ;Если первая функция вернула нам число 7, то...
			_function2() ;идём делать следующую ф-цию
		Else					;иначе...
			_function3() ;фун-цию три :)
		EndIf
		
	
WEnd

Func _function1()
	;Описываем её... Если что-то надо передать, то...
	$var = 7
	Return($var) ;Это даёт нам понять что произошло в функции и как реагировать дальше
EndFunc
 
Автор
S

SurikenTSD

Новичок
Сообщения
67
Репутация
1
Ну, мой код пока что сейчас выглядит так (сразу скажу, работу над ошибками не делал, буквально только что закончил писать, так что в коде могут быть косяки, ляпы и недоработки). Сразу видно, что я пытаюсь написать несложного бота для браузерки, но не об этом речь.

Код:
Func AutoBuff()
	$S = 1
	While $S < 10
		$spotscrd = IniReadSection($BuffListPath, "Sector "&$S)
		Local $i = 1
		$cnt = 0
		While $cnt < $spotscrd[0][0] / 2
			CheckBuff()
			MouseClick( "left", $spotscrd[$i][1], $spotscrd[$i+1][1], 1, $MouseSpeed)
			$i = $i + 2
			$cnt = $cnt + 1
		WEnd
		$S = $S + 1
	WEnd
EndFunc


Основная часть скрипта: из файла настроек берем координаты точек, на которые надо накладывать баф, баф не бесконечный, поэтому через функцию CheckBuff я проверяю каждый раз перед наложением остался ли баф в наличии или надо использовать новый.

Код:
Func CheckBuff()
	Local $x1 = IniRead($GameInfoIniPath, "Coordinates of Objects", "Cancel Buff Box Left Corner X")
	Local $y1 = IniRead($GameInfoIniPath, "Coordinates of Objects", "Cancel Buff Box Left Corner Y")
	Local $x2 = IniRead($GameInfoIniPath, "Coordinates of Objects", "Cancel Buff Box Right Corner X")
	Local $y2 = IniRead($GameInfoIniPath, "Coordinates of Objects", "Cancel Buff Box Right Corner Y")
	ImgSearch($x2, $y2, $x1, $y1, 0xA6A093, 1, 2)
	Switch @error
		Case 1
			UseBasketBuff()
	EndSwitch
EndFunc


Тут проверяю, если иконка бафа пропадает, то перехожу к функции UseBasketBuff для того, чтобы активировать новый баф.

Код:
Func UseBasketBuff()
	Local $i = 0
	Local $e = 0
	Local $x = IniRead($GameInfoIniPath, "Coordinates of Objects", "Star Menu X")
	Local $y = IniRead($GameInfoIniPath, "Coordinates of Objects", "Star Menu Y")
	Local $x2 = IniRead($GameInfoIniPath, "Coordinates of Objects", "Star Menu Effects X")
	Local $y2 = IniRead($GameInfoIniPath, "Coordinates of Objects", "SStar Menu Effects Y")
	Local $smbx1 = IniRead($GameInfoIniPath, "Coordinates of Objects", "Star Menu Box Left Corner X")
	Local $smby1 = IniRead($GameInfoIniPath, "Coordinates of Objects", "Star Menu Box Left Corner Y")
	Local $smbx2 = IniRead($GameInfoIniPath, "Coordinates of Objects", "Star Menu Box Right Corner X")
	Local $smby2 = IniRead($GameInfoIniPath, "Coordinates of Objects", "Star Menu Box Right Corner Y")
	MouseClick("left", $x, $y, 1, $MouseSpeed)
	MouseClick("left", $x2, $y2, 1, $MouseSpeed)
	While $i = 0
		$i = 1
		Local $buffcrd = ImgSearch($smbx2, $smby2, $smbx1, $smby1, 0x8DA02A, 1, 3)
		Switch @error
			Case 1
				$e = $e + 1
				If $e = 15 Then
					MsgBox(0, "Ошибка!", "Корзины не найдены!")
				Else
					Local $x3 = IniRead($GameInfoIniPath, "Coordinates of Objects", "Star Menu Arrow Down X")
					Local $y3 = IniRead($GameInfoIniPath, "Coordinates of Objects", "Star Menu Arrow Down Y")
					MouseClick("left", $x3, $y3, 1, $MouseSpeed)
					$i = 0
				EndIf
			Case 0
				MouseClick("left", $buffcrd[0], $buffcrd[1], 1, $MouseSpeed)
		EndSwitch
	WEnd
EndFunc


И вот собственно активация самого бафа. Тут фишка заключается в том, что есть окошко, в котором эти бафы находятся, у окошка есть скролл. Если баф не находится, скрипт тыкает на стрелочку вниз для прокрутки странички. Вот он так 5 раз протыкает вниз страничку и если бафа не найдет, мне надо закончить разом эту цепочку функций и я ломаю голову как..)

По всяким синтаксическим ошибкам - это я и сам разберусь, а вот по архитектуре кода я б срадостью послушал замечания.
 

_ToBe_

Осваивающий
Сообщения
142
Репутация
34
Попробую объяснить на примере написанным мною выше:

Код:
While 1 
	$msg = GUIGetMsg()
	If $msg = $GUI_EVENT_CLOSE Then Exit
	
		_AutoBuff()
	
WEnd

Func _AutoBuff()
	;Описываем её... 
	;Из неё же вызываем 
	_CheckBuff()
	If $check_buff = True Then ;Если ЧекБАф - истинный, значит нам нужно забафаться
		_useBasketBuff()
	EndIf
	
EndFunc

Func _CheckBuff()
	;Проверяем нужно ли нам бафаться или нет
	If @error Then
		$check_buff = False
	Else
		$check_buff = True
	EndIf
	Return($check_buff)	;Возвращаем занчение ЧекБаф в предыдущую функцию
EndFunc

Func _useBasketBuff()
	;Тут мы заходим в цикл. Цикл должен закончиться при выполнении 2 условий
	;1. Дошли до конца страницы (прокликали 5 раз)
	;2. Нашли баф и забафались
	$click = 0
	$buff = False
	Do
		;Ищем наш баф
		ImageSearch() ;P.S. Никогда им не пользовался =D
		If @error Then	;Если картинка не найдена, то 
			$buff = False   
		Else
			$buff = True
			MouseClick("left", $x, $y) ; Кликаем по бафу
		EndIf
		$click = $click + 1 ;делаем клик и проходим ниже
		Until $click >=5 Or $buff = True  ;цикл закончится как только бафф будет = True или сделает 5 кликов, после чего он выйдет из цикла
EndFunc


или можно принудительно выйти из цикла:
Код:
Func _useBasketBuff()
    $click = 0
    $buff = False
    Do
        ImageSearch() 
        If @error Then  
            $buff = False   
        Else
            $buff = True
            MouseClick("left", $x, $y) ; Кликаем по бафу
            ExitLoop ;тут он выходит из цикла принудительно
        EndIf
        $click = $click + 1 ;делаем клик и проходим ниже
        Until $click >=5 
EndFunc
 
Автор
S

SurikenTSD

Новичок
Сообщения
67
Репутация
1
Так, а теперь, собственно, возвращаясь к сабжекту, уже для другой цели, но все-таки как организовать через хоткей остановку скрипта?
Цель такова, чтобы при нажатии на заданную кнопку останавливался скрипт, в какой бы части когда он в данный момент не работал, и переходил в цикл ожидания нажатия кнопок в GUI?

Ввести переменную типа $STOP = 0, которой при нажатии на хоткей будет задаваться значение 1 и по всему коду понатыкать условия типа while $STOP = 0 ? Или есть способ получше?
 

C2H5OH

AutoIT Гуру
Сообщения
1 473
Репутация
333
Таких примеров на форуме куча
Код:
HotKeySet("{F10}", "_pause")

Global $Pause = False

Func _pause()
	$Pause = Not $Pause
	While $Pause
		Sleep(1000)
	WEnd
EndFunc


Если хочется чего-нибудь эдакого, то можешь кликать на иконку в трее.
 
Автор
S

SurikenTSD

Новичок
Сообщения
67
Репутация
1
Да не, пауза - это легко, тут даже такой нуб, как я, легко сообразит. Я, наверное, некорректно выражаюсь из-за не знания терминологии... Вот смотри. Ниже кусок приведен - это бесконечный цикл ожидания, пока юзер в гуи кнопку тыкнет.

Код:
While 1
	$nMsg = GUIGetMsg()
	Switch $nMsg
		Case $GUI_EVENT_CLOSE
			Exit
		Case $GGInfo
			GettingInfo()
			WinActivate($BOTWindowName)
		Case $S1BuffList
			$S = 1
			GetBuffSpots()
			WinActivate($BOTWindowName)
		Case $S2BuffList
			$S = 2
			GetBuffSpots()
			WinActivate($BOTWindowName)
		Case $S3BuffList
			$S = 3
			GetBuffSpots()
			WinActivate($BOTWindowName)
		Case $S4BuffList
			$S = 4
			GetBuffSpots()
			WinActivate($BOTWindowName)
		Case $S5BuffList
			$S = 5
			GetBuffSpots()
			WinActivate($BOTWindowName)
		Case $S6BuffList
			$S = 6
			GetBuffSpots()
			WinActivate($BOTWindowName)
		Case $S7BuffList
			$S = 7
			GetBuffSpots()
			WinActivate($BOTWindowName)
		Case $S8BuffList
			$S = 8
			GetBuffSpots()
			WinActivate($BOTWindowName)
		Case $S9BuffList
			$S = 9
			GetBuffSpots()
			WinActivate($BOTWindowName)
		Case $StartAutoBuff
			$STOP = 0
			HotKeySet("{ESC}", "StopScript")
			AutoBuff()
			HotKeySet("{ESC}")
			WinActivate($BOTWindowName)
	EndSwitch
WEnd


Тыкает юзер кнопку, запускается функция:

Код:
Func AutoBuff()
	While 1
	HotKeySet("{F10}", "_Exit")
	WinActivate($GameWindowName)
	If WinActivate ($GameWindowName) Then
		$S = 1
		While $S <= 9
			$spotscrd = IniReadSection($BuffListPath, "Sector "&$S)
			If Not @error Then
				Send ($S)
				Sleep (1000)
				Local $i = 1
				$cnt = 0
				While $cnt < $spotscrd[0][0] / 2
					CheckBuff()
					Switch $checkbuff
						Case False
							UseBasketBuff()
						Case True
							MouseClick( "left", $spotscrd[$i][1], $spotscrd[$i+1][1], 1, $MouseSpeed)
							$i = $i + 2
							$cnt = $cnt + 1
							Sleep (2500)
						Case 0
							MsgBox(0, "Ошибка!", "Бафов нет в наличии!")
							$cnt = $spotscrd[0][0]
							$S = 10
					EndSwitch
				WEnd
			EndIf
			$S = $S + 1
		WEnd
	Else
		MsgBox(0, "Ошибка!", $gwnf)
	EndIf
	Sleep (21660000)
	WEnd
EndFunc


И вот мне надо, чтобы из любой точки этой функции при нажатии к примеру на Ф10 скрипт не на паузу вставал, не завершался при использовании Exit, а переходил в режим ожидания, пока пользователь не тыкнет в графическом интерфейсе кнопку, то есть перешел в первый приведенный кусок кода.

Много же подобных программ есть, тыкаешь в интерфейсе кнопочку Старт, программка че-то начинает делать. Ты передумал и жмякаешь на кнопочку Стоп. И сразу програмка забивает на свою прежнюю вселенскую миссию. Но прога-то при это не выключается, а ждет, чего там дальше пользователь учудит.


Добавлено:
Сообщение автоматически объединено:

А мышкой, кстати, тыкать куда-либо - дело гиблое в моем случае, эта функция перехватывает движение мышкой, так что единственный вариант - это хоткей.
 

C2H5OH

AutoIT Гуру
Сообщения
1 473
Репутация
333
Кажется понял. :beer:
Ну, я бы сделал второй скрипт отдельным exe-шником, вызывал бы его из первого по нажатию кнопки в GUI и таки завершал бы Exit по нажатию кнопки, например F10.
:blum:oke:


Добавлено:
Сообщение автоматически объединено:

Вообще я не понимаю чем вызвана такая немедленность.
Я бы натыкал контрольных точек и не мучался бы.
Код:
HotKeySet("{F10}", "_EmergencyExit")

Global $Alarm

Func _EmerrgencyExit()
	$Alarm = True
EndFunc

Func AutoBuff()
	$Alarm = False
    While Not $Alarm   ; <--- Тут
    WinActivate($GameWindowName)
    If WinActivate ($GameWindowName) Then
        $S = 1
        While $S <= 9 And Not $Alarm   ; <--- Тут
            $spotscrd = IniReadSection($BuffListPath, "Sector "&$S)
            If Not @error Then
                Send ($S)
                Sleep (1000)
                Local $i = 1
                $cnt = 0
                While $cnt < $spotscrd[0][0] / 2 And Not $Alarm   ; <--- и тут
                    CheckBuff()
                    Switch $checkbuff
                        Case False
                            UseBasketBuff()
                        Case True
                            MouseClick( "left", $spotscrd[$i][1], $spotscrd[$i+1][1], 1, $MouseSpeed)
                            $i = $i + 2
                            $cnt = $cnt + 1
                            Sleep (2500)
                        Case 0
                            MsgBox(0, "Ошибка!", "Бафов нет в наличии!")
                            $cnt = $spotscrd[0][0]
                            $S = 10
                    EndSwitch
                WEnd
            EndIf
            $S = $S + 1
        WEnd
    Else
        MsgBox(0, "Ошибка!", $gwnf)
    EndIf
    Sleep (21660000)
    WEnd
EndFunc
 
Автор
S

SurikenTSD

Новичок
Сообщения
67
Репутация
1
Так-то я тоже изначально о контрольных подобных контрольных точках думал, но в тот момент за моей спиной массивная фигура тетки-качка по имени Лень маячила... Отдельным экзешником, тоже вариант, я о нем не подумал, но... наверное, это не круто будет. Придется действовать через "алярм".
 
Верх