Forum in READ ONLY mode! All questions and discussions on Discord official server, invite link: https://discord.gg/VxsGzJ7

Работа с гампами в скрипте.

тут можно задать вопрос по скриптингу
Post Reply
User avatar
Vizit0r
Developer
Developer
Posts: 3958
Joined: 24.03.2005 17:05
Contact:

Работа с гампами в скрипте.

Post by Vizit0r »

Итак, предполагается, что хотя бы азы скриптинга вы знаете.

Букв будет много, набирайтесь терпения.

Для начала общая информация о гампах:
1) Так как гампов может быть больше одного, то работа с ними идет через номер гампа в списке.Количество гампов в списке можно получить через GetGumpsCount При этом обычно идет перебор от нуля до GetGumpsCount -1 с проверкой, тот ли это гамп, который нам нужен
2) У гампа есть два поля - Serial и GumpID, которые обычно привязаны к действиям\скиллам и пр, и на которые можно ориентироваться для нахождения нужного гампа. Получать их можно через GetGumpID и GetGumpSerial
3) У всех гампов есть набор элементов, которые собственно и показываются на экране. Текст, картинки, кнопки, чекбоксы, поля ввода - это всё оно. Элементов одного типа в гампе может быть много. Полный список всех элементов и их полей тут. Отдельные элементы будем рассматривать дальше.
4) У гампов есть свойства (полный список по ссылке в п.3), для нас интересен только пункт NoClose, который можно проверить через IsGumpCanBeClosed. Обычно гампы, у которых NoClose = False - это простые информационные гампы, которые закрываются кликом правой кнопки мыши в клиенте. В стелсе это же можно сделать через CloseSimpleGump.


По гампэлементам в целом:
1) Каждый гампэлемент имеет поля: Page и ElemNum. Первое отвечает за номер страницы, на которой находится элемент, второе - за номер элемента в общем списке элементов гампа (без разделения по типу).
2) ВАЖНО! Те элементы, которые используются в скриптах - TextEntry, RadioButton, CheckBox, GumpButton - имеют поле return_value. Это одно их самых важных полей, поскольку именно оно передается как id элемента в функции, например TextEntryID в функции NumGumpTextEntry. Коряво и запутано, но имеем то, что имеем. Надо просто запомнить это.
3) все изменения в гампе, в частности TextEntry, RadioButton, CheckBox - должны делаться ДО нажатия кнопки - она закрывает, отправляет и уничтожает гамп в стелсе! Еще раз - NumGumpButton или WaitGump должно вызываться ПОСЛЕДНИМ!

Теперь по конкретным гампэлементам, которые чаще всего используются в скриптах:
1) TextEntry - поле ввода. Меняется через GumpAutoTextEntry либо NumGumpTextEntry. Параметр Value - устанавливаемое значение строки, параметр TextEntryID - это значение поля return_value элемента.
2) Radiobutton- переключатель. Может выглядеть как выбор из нескольких вариантов, так и как обычный chekbox. Меняется через GumpAutoRadiobutton либо NumGumpRadiobutton. Параметр Value - 0 для снятия выбора, любое другое - для выбирания. параметр RadiobuttonID - это значение поля return_value элемента.
3) CheckBox- флажок. Обычно выглядит как квадратик с галкой. Меняется через GumpAutoCheckBox либо NumGumpCheckBox. Параметр Value - 0 для снятия выбора, любое другое - для выбирания. параметр CBID- это значение поля return_value элемента.
4) GumpButton - кнопка. Всегда закрывает гамп, отправляя ответ серверу. Вызывается через WaitGump либо NumGumpButton. Параметр Value - это значение поля return_value кнопки.

Отличия серии методов NumGump* от GumpAuto* :
1) NumGump* - функции, которые возвращают результат выполнения. В них задается GumpIndex, а не простой перебор гампов до первого совпадения. Работает только с имеющимся гампом (GumpIndex), не устанавливает ловушки на приходящий гамп.
2) GumpAuto* - не возвращает результат выполнения. Перебираются все гампы до первого совпадения (которое может быть совсем не в том гампе, который нужен!). Если совпадений среди имеющихся гампов нет, то ставится ловушка на входящий гамп, в котором сразу будет искаться элемент, при обнаружении - сразу устанавливается значение.


Теория закончилась, переходим к практике.

Простые примеры из гампа с двумя кнопками - неинтересны, берем сразу что-то посложнее.

Image
Наблюдаем тут прозрачный гамп (на самом деле просто гамп без "подложки" с картинкой), где визуально справа вроде бы чекбоксы с названиями мест. Задача - выбрать, ну например Minoc и телепортнуться туда.
Выполняется в 2 действия - 1) поставить галку 2) нажать кнопку.
Идем по шагам:
1) Сначала надо получить полную информацию о гампе, чтобы найти нужные элементы и получить их return_value
Можно получить разными путями (результат будет одинаков). Либо запустить граф. клиент из стелса, открыть в клиенте этот гамп, и написать ,infogump - вылетит окно с полной информацией о гампе. Другой вариант - получить эту информацию через скриптовый метод GetGumpFullLines:

Code: Select all

   SetSilentMode(False);    
   GetGumpFullLines(GetGumpsCount-1, st);//var st : TStringList;
Полная инфа
Serial: 40887E29
GumpID: 0406
X: 0000
Y: 0000
Pages: 7
Gump Options:

ResizePics: X Y ID Width Height Page ElemNum
0: 190 180 5054 400 300 0 0

CheckerTrans: X Y Width Height Page ElemNum
0: 195 185 390 290 0 1

RadioButtons: X Y Released_ID Pressed_ID Status Return_value Page ElemNum
0: 400 215 210 211 0 11 1 23
1: 400 240 210 211 0 12 1 24
2: 400 265 210 211 0 13 1 25
3: 400 290 210 211 0 14 1 26
4: 400 315 210 211 0 15 1 27
5: 400 340 210 211 0 16 1 28
6: 400 390 210 211 0 18 1 29
7: 400 415 210 211 0 19 1 30
8: 400 215 210 211 0 21 2 41
9: 400 240 210 211 0 22 2 42
10: 400 265 210 211 0 23 2 43
11: 400 290 210 211 0 24 2 44
12: 400 315 210 211 0 25 2 45
13: 400 340 210 211 0 26 2 46
14: 400 365 210 211 0 27 2 47
15: 400 390 210 211 0 28 2 48
16: 400 415 210 211 0 29 2 49
17: 400 440 210 211 0 30 2 50
18: 400 215 210 211 0 31 3 63
19: 400 240 210 211 0 32 3 64
20: 400 265 210 211 0 33 3 65
21: 400 290 210 211 0 34 3 66
22: 400 315 210 211 0 35 3 67
23: 400 340 210 211 0 36 3 68
24: 400 365 210 211 0 37 3 69
25: 400 390 210 211 0 38 3 70
26: 400 215 210 211 0 41 4 81
27: 400 240 210 211 0 42 4 82
28: 400 265 210 211 0 43 4 83
29: 400 290 210 211 0 44 4 84
30: 400 315 210 211 0 45 4 85
31: 400 340 210 211 0 46 4 86
32: 400 215 210 211 0 51 5 95
33: 400 240 210 211 0 52 5 96
34: 400 265 210 211 0 53 5 97
35: 400 215 210 211 0 61 6 103
36: 400 240 210 211 0 62 6 104
37: 400 265 210 211 0 63 6 105
38: 400 290 210 211 0 64 6 106
39: 400 315 210 211 0 65 6 107
40: 400 215 210 211 0 71 7 115
41: 400 240 210 211 0 72 7 116
42: 400 265 210 211 0 73 7 117
43: 400 290 210 211 0 74 7 118
44: 400 315 210 211 0 75 7 119
45: 400 340 210 211 0 76 7 120
46: 400 365 210 211 0 77 7 121
47: 400 390 210 211 0 78 7 122

GumpTexts: X Y Color Text_ID Page ElemNum
0: 350 190 42 0 0 2
1: 235 405 55 1 0 3
2: 235 430 55 2 0 4
3: 220 215 55 3 0 7
4: 220 240 55 4 0 8
5: 220 265 55 5 0 9
6: 220 290 55 6 0 10
7: 220 315 55 7 0 11
8: 220 340 55 8 0 12
9: 220 365 55 9 0 13
10: 220 215 42 10 1 22
11: 425 215 55 11 1 31
12: 425 240 55 12 1 32
13: 425 265 55 13 1 33
14: 425 290 55 14 1 34
15: 425 315 55 15 1 35
16: 425 340 55 16 1 36
17: 425 390 55 17 1 37
18: 425 415 55 18 1 38
19: 220 240 42 19 2 40
20: 425 215 55 20 2 51
21: 425 240 55 21 2 52
22: 425 265 55 22 2 53
23: 425 290 55 23 2 54
24: 425 315 55 24 2 55
25: 425 340 55 25 2 56
26: 425 365 55 26 2 57
27: 425 390 55 27 2 58
28: 425 415 55 28 2 59
29: 425 440 55 29 2 60
30: 220 265 42 30 3 62
31: 425 215 55 31 3 71
32: 425 240 55 32 3 72
33: 425 265 55 33 3 73
34: 425 290 55 34 3 74
35: 425 315 55 35 3 75
36: 425 340 55 36 3 76
37: 425 365 55 37 3 77
38: 425 390 55 38 3 78
39: 220 290 42 39 4 80
40: 425 215 55 40 4 87
41: 425 240 55 41 4 88
42: 425 265 55 42 4 89
43: 425 290 55 43 4 90
44: 425 315 55 44 4 91
45: 425 340 55 45 4 92
46: 220 315 42 46 5 94
47: 425 215 55 47 5 98
48: 425 240 55 48 5 99
49: 425 265 55 49 5 100
50: 220 340 42 50 6 102
51: 425 215 55 51 6 108
52: 425 240 55 52 6 109
53: 425 265 55 53 6 110
54: 425 290 55 54 6 111
55: 425 315 55 55 6 112
56: 220 365 42 56 7 114
57: 425 215 55 57 7 123
58: 425 240 55 58 7 124
59: 425 265 55 59 7 125
60: 425 290 55 60 7 126
61: 425 315 55 61 7 127
62: 425 340 55 62 7 128
63: 425 365 55 63 7 129
64: 425 390 55 64 7 130

Text Lines:
Gate Travel
Accept
Cancel
Guarded Towns (free)
Unguarded Towns (500 gp)
Old Dungeons (1000 gp)
New Dungeons (1000 gp)
Ancient Statues (2000 gp)
Islands (3000 gp)
Other Places (3000 gp)
Guarded Towns (free)
Britain
Minoc
Moonglow
Nujel'm (Save Zone)
Trinsic
Vesper
Nujel'm Market
Nujel'm Cemetary
Unguarded Towns (500 gp)
Buccaneer's Den
Cove
Delucia
Jhelom
Magincia
Ocllo
Papua
Serpent's Hold
Skara Brae
Yew
Old Dungeons (1000 gp)
Covetous
Despise
Destard
Hythloth
Ice Dungeon
Shame
Terathan Keep
Wrong
New Dungeons (1000 gp)
Blighted Grove
Hopper's Bog
Painted Caves
Paroxysmus
Sanctuary
Trinsic Passage
Ancient Statues (2000 gp)
GM Frib's Statue
GM Non Stop's Statue
GM Observer' Statue
Islands (3000 gp)
Chillwind Isle
Cyclops Valley
Fisherman's Hut
Ice Thistle Isle
Murloc Isle
Other Places (3000 gp)
City of the Dead
Cove Goblin Fort
Ettin Valley
Hedge Maze
Hidden Valley
Moonglow Cemetary
Sak Teb
Tanner's Huts

GumpButtons: X Y Released_ID Pressed_ID Quit Page_ID Return_value Page ElemNum
0: 200 405 4005 4007 1 0 1 0 5
1: 200 430 4005 4007 1 0 0 0 6
2: 200 215 2117 2118 0 1 0 0 14
3: 200 240 2117 2118 0 2 0 0 15
4: 200 265 2117 2118 0 3 0 0 16
5: 200 290 2117 2118 0 4 0 0 17
6: 200 315 2117 2118 0 5 0 0 18
7: 200 340 2117 2118 0 6 0 0 19
8: 200 365 2117 2118 0 7 0 0 20

Previous gump reply:
Button id: 1
Radiobuttons/Checkboxes:
12 is checked
Внезапно, в дампе гампа очень много элементов. Присмотревшись, видно, что они вполне четко разделяются группами по Page. Еще присмотревшись с GumpButtons, видны кнопки, у которых Page_ID совпадают с номерами этих page. Они-то и переключают показ страниц.
Изначально казалось, что нам нужен Checkbox - но здесь вообще нет Checkbox элементов, зато полно RadioButtons. Смотрим те из них, у которых Page 1. Прикинув, что по стандартной логике они идут сверху вниз, смотрю на второй из них, беру его Return_value - 12. В сложных случаях приходится примеряться по координатам.
Насчет кнопки - они все идут в ряд, поэтому координата X одинакова. Нам нужна предпоследняя кнопка по Y, и это оказывается кнопка за номером 0, Return_value = 1.

Соответственно в итоге имеем:

Code: Select all

  NumGumpRadiobutton(GetGumpsCount-1, 12, 1);
  NumGumpButton(GetGumpsCount-1, 1);
Для того, чтобы поставить галку на элементе с другой страницы - ничего не переключать не надо, просто подставляйте Return_value нужного элемента и всё.

Для того, чтобы проверить себя (либо в особо запущенных случаях, когда так сходу не находится) - можно поставить все нужные галки, заполнить поля ввода и отправить гамп из клиента, потом вызвать ,infogump и подсмотреть в самом конце инфы в Previous gump reply: нужные значения. В примере выше это как раз показано.


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

Code: Select all

if XXX then//тут мы проверили все, что надо, и уверены - гамп есть, и он именно тот, который нужен.
  begin
   GetGumpInfo(GetGumpsCount-1, gi);       
   NumGumpRadiobutton(GetGumpsCount-1, 12,1);
   if Length(gi.Text)> 0 then
     for k := 0 to Length(gi.Text) - 1 do
       if BMSearch(1, gi.Text[k], 'Accept') > 0 then
        NumGumpButton(GetGumpsCount-1, gi.GumpButtons[0].return_value);
   wait(2000); 
 end;
Типичные ошибки в скриптах по работе с гампами:
1) не проверять, есть ли действительно нужный гамп. Например, в скрипте был вызван гамп, потом wait(3000), и дальше юзер действует исходя из того, что гамп 100% пришел. Но иногда он может и не прийти - например на сейве, на лаге, еще почему-то. Поэтому всегда проверяйте, что количество гампов больше нуля, и нужный вам действительно в их числе.
2) забывать создавать объект TStringList, передаваемый параметром в функции типа GetGumpTextLinesи похожие. Сейчас скрипт выкинет ошибку, получив в параметре не созданный объект, но лучше до такого не доводить.
3)Получив строки из GetGumpTextLines и похожих - ВСЕГДА проверяйте. что кол-во строк больше нуля. Очень часто не проверив гамп по п.1 - юзер работает не с тем гампом, и получает ноль строк, и скрипт с грохотом падает на обращении к несуществующим строкам в StringList.
"Пишите код так, как будто сопровождать его будет склонный к насилию психопат, который знает, где вы живете". (с) Макконнелл, "Совершенный код".
Post Reply