Вообщем накалякал поддержку include файлов в скриптовый модуль.
Ссылка:
http://rghost.ru/48433355UP! 28.08.2013 Стандартное оформление.Ссылка:
http://rghost.ru/48433366UP! 28.08.2013 Новое оформление с дополнительным окошком.Ссылка:
http://rghost.ru/48433372UP! 28.08.2013 English version.Доступные функции:В названии функций обязательно учитывать регистр.
#include(File) - заменяет данную строку содержимым файла 'File'
Например:
#include(C:/includes/test.sc)
#SETPATH Path - задаёт дефолтный патч ко всем последующим инкладам
Пример:
#SETPATH C:/includes/
#include(test.sc) - добавит файл 'C:/includes/test.sc'
#include(testinc/test.sc) - добавит файл 'C:/includes/testinc/test.sc'
Однако, #include(C:/includes/test.sc) - будет искать файл 'C:/includes/C:/includes/test.sc'
#UNSETPATH - удалит дефолтный путь к инклад файлам
#SETSHOW - установит галочку Show в окне инжи (о галках чуть позже.)
#UNSETSHOW - снимет галочку Show
#SETMSGS - установит галочку Messages
#UNSETMSGS - снимет галочку Messages
#SETLINK File - установит полный путь к файлу, из которого будет черпать функции
#link(functions) - заменяет данную строку функциями 'functions' из файла, указанного в '#SETLINK File'
Пример:
#SETLINK C:/includes/test.sc
#link(main,CheckCrime,WalkToChar) - добавит в скрипт функции 'main', 'CheckCrime', 'WalkToChar' (В названии функций обязательно учитывать регистр.)
#UNSETLINK - удалит дефолтный путь к link файлам
Галки:Show - показывает проанализированный скрипт в окошке скриптов
Messages - показывает/скрывает некоторые сообщения редактора в окне УО
Чуть ниже видел темку Beyonder'a с подобным, судя по комментам в ней, отличается следующим:
Работает ',terminate fun' и ',terminate all' и, соответственно, 'uo.exec("terminate fun")' и 'uo.exec("terminate all")'
Работает autoload.
Автоматически анализирует скрипт при автостарте, загрузке или изменении скрипта.
И на счёт ,terminate - мб что-то намудрил когда писал её, но теперь он мгновенно обрубает функцию, в модуле Yoko функция висит в списке некоторое время, как я понял - ждёт завершения одного из wait(...), если на него попало. Но с этим проблемм не возникало) 2 суток стабильной работы)
На счёт совместимости с ASM - переименуйте файл в scriptengine.dll - и будет Вам счастье ^^
По крайней мере у меня с 'ASM-3 [Частная редакция] [604.21]' проблемм не наблюдалось.
Авторасстановка отступов и подсветка синтаксиса.
Добавил метод
'terminate alln_<fun>'Вырубает все функции, кроме функций, с названием
'<fun>'Пример:
,terminate alln_main - оставит работающими только функции 'main'
Комманда
uo.CloseHandle() закрывает оно УО, даже если ещё не вошли в игру, либо при дисконнекте. Вообщем там, где uo.CloseUO() не помогает)
Комманда
uo.ActivateHandle() делает активным окно УО (выводит на 1 план)
Функция
Remain(Source,Div) возвращает true в случае остатка от деления Source на Div
Загрузка скрипта:Функция скрипта
uo.exec("exec __PauseAll") поставит на паузу все запущенные скрипты.
В игре:
,exec __PauseAllФункция скрипта
uo.exec("exec __ResumeAll") восстановит работу всех скриптов, которые были поставлены на паузу.
В игре:
,exec __ResumeAllФункция скрипта
uo.exec("exec __LoadSC#<File>") загрузит скрипт по пути 'File' и проанализирует его. Единственное НО - в пути 'File' не должно быть пробелов, иначе инжа крашанёт(
Пример:
Code:
Sub Loading()
#Загрузим скрипт 'E:\UOInjection\Scripts\Archery.sc'
uo.exec("exec __LoadSC#E:\UOInjection\Scripts\Archery.sc")
#Задержка на загрузку (на всякий случай)
wait(1000)
#Запустим функцию 'main' из этого скрипта.
uo.exec("exec main")
end sub
Добавил 2 функции по работе со строками:
StrUp(str) - возвращает строку str всю в верхнем регистре.
StrLow(str) - возвращает строку str всю в нижнем регистре.
Добавил класс
Buffer:
Предназначен для хранения массива строк и чисел.
Мб многим не пригодится, но мне понадобился)
Объявление:var b=Buffer(Length) где Length - длинна массива (максимум 1000), при длине более 1к - она автоматически изменится на 1к. Если Length=-1 - устанавливается автозаполнение массива для строк и чисел отдельно.
Функции:b.GetLen() - вернёт длину массива
b.SetStr(str,pos) - установит str в позицию pos строчного массива
b.SetNum(num,pos) - установит num в позицию pos числового массива
b.GetStr(pos) - вернёт строку массива позиции pos
b.GetNum(pos) - вернёт число массива позиции pos
b.AddStr(str) - Добавит str в последнюю ячейку массива строк
b.AddNum(num) - Добавит num в последнюю ячейку массива чисел
b.GetStrCount() - Вернёт длину автозаполненного массива строк
b.GetNumCount() - Вернёт длину автозаполненного массива чисел
b.Delete() - удалит Buffer
При загрузке/сохранении скрипта делает активным окно УО и, если открыт редактор - выводит его на 1 план.
Кнопки в редакторе:
Sweep Code - расставляет пробелы во всём тексте
'sub' и 'end sub' начинаются с самого начала строчки, всё что между ними - приводится в "нормальный" вид
Реализована поддержка else if в конструкции if else endif.
Реализована "Перегрузка процедур и функций"
Пример использования:
Code:
sub main()
FindType('0x00DA')
if FindCount() then
Print('В паке найдено '+str(FindCount())+' предметов типа 0x00DA')
else
Print('Предметов типа 0x00DA в паке нет')
endif
FindType('0x00DA','0x0000')
if FindCount() then
Print('В паке найдено '+str(FindCount())+' предметов типа 0x00DA и цвета 0x0000')
else
Print('Предметов типа 0x00DA и цвета 0x0000 в паке нет')
endif
FindType('0x00DA','0x0000','0x0008FA04')
if FindCount() then
Print('В контейнере 0x0008FA04 найдено '+str(FindCount())+' предметов типа 0x00DA и цвета 0x0000')
else
Print('Предметов типа 0x00DA и цвета 0x0000 в контейнере 0x0008FA04 нет')
endif
end sub
Sub FindType(Type)
UO.FindType(Type)
end sub
Sub FindType(Type,Color)
UO.FindType(Type,Color)
end sub
Sub FindType(Type,Color,Container)
UO.FindType(Type,Color,Container)
end sub
Sub FindCount()
return UO.FindCount()
end sub
Sub Print(Message)
UO.Print(Message)
end sub
Реализована работа с *.mul файлами Ультимы.
Класс поиска пути на карте (пока что не кротчайшего):
Code:
PathFind(UOPath, MapNum, Z, Alg) - Первый конструктор. UOPath - путь к папке УО с *.mul файлами, MapNum - номер карты, для которой вычисляется путь, Z координата (пока что не работает), Alg - Выбор алгоритма поиска пути, может принимать значения 0 (волновой алгоритм поиска) и 1 (алгоритм поиска А*) см. википедию по сути алгоритмов.
PathFind(UOPath, MapNum, Z, Alg, ScreenCatalog) - Второй конструктор. По первым 4 параметрам см. выше. ScreenCatalog - путь к папке, куда сохранять изображения с фрагментом карты, на котором ведется поиск пути. На картинке отражается цветом:
Белый - Свободные тайлы
Черный - Заблокированные тайлы
Синий - Вода
Темно-бардовый - Мост (тайлы статики, имеющие флаг 0x00000400 (Bridge))
Темно-синий - Точка, от куда ведется расчет пути
Фиолетовый - Точка, куда ведет путь
Setup(PX, PY, TX, TY) - Устанавливает начальную и конечную точки и извлекает по ним путь.
PX PY - координаты начальной точки пути.
TX TY - координаты конечной точки пути.
First() - Доступ к первому элементу массива.
Last() - Доступ к последнему элементу массива.
SetPos(Position) - Изменить текущий указатель позиции в массиве на Position. Индексы от 0 до Size()-1
GetPos() - Получить текущий указатель на позицию в массиве.
GetX() - Получить координату Х текущий позиции.
GetY() - Получить координату Y текущий позиции.
Next() - Доступ в следующему элементу массива. Вернёт 1 если удачно. 0 если это конец массива.
Back() - Доступ в предъидущему элементу массива. Вернёт 1 если удачно. 0 если это начало массива.
Size() - Вернёт размер массива.
Clear() - Очистит массив с картой и вектор пути.
AddObj(Graphic, X, Y) - Добавит в класс игровой объект с типом Graphic (строка) в координатах X и Y (числа)
Работает с файлами: map*.mul, statics*.mul, staidx*.mul, tiledata.mul, multi.mul, art.mul, artidx.mul, verdata.mul
Карта, созданная классом:
Пример кода поиска пути:
Code:
var UOPath='E:\Ultima Online Abyss' #Путь к папке с *.mul файлами УО
var ScreenPath='E:\UOPathScreens' #Путь к папке, куда сохранять скрины поиска пути
var PathAlg=1 #Индекс алгоритма
var PathMap=0 #Индекс карты
var CheckUOObject=1 #Учитывать игровые объекты при поиске пути? 0 - нет; 1 - да
Sub abs(i)
if i<0 then
i=i*(-1)
endif
return i
end sub
sub tWalk1()
var i,gr=''
var mapout=PathFind(UOPath,PathMap,uo.getz(),PathAlg,ScreenPath)
var x=uo.getx() #От куда начинаем путь по X
var y=uo.gety() #От куда начинаем путь по Y
var ChestX=1773 #Куда идем по X
var ChestY=3096 #Куда идем по Y
if CheckUOObject then
var dx=abs(x-ChestX)
var dy=abs(y-ChestY)
if dx<dy then #Получим наибольшее значение дистанции до объекта
dx=dy
endif
if remain(dx,2) then #Если есть остаток от деления на 2, то прибавим 1
dx=dx+1
endif
dx=dx*2 #Максимальная дистанция поиска объектов для алгоритма = максимальная дистанция * 2
uo.set('finddistance',str(dx))
uo.findtype(-1,-1,'ground')
uo.ignorereset()
if uo.findcount() then #Поиск предметов на земле, пока не кончатся
repeat
gr=uo.getgraphic('finditem')
#Проверка на людей. Все живые объекты нужно исключить из списка. Проверка Z координаты, если не больше 10 то заносим в список
if gr<>'0x0190' and gr<>'0x0191' and abs(uo.getz('finditem')-uo.getz('self'))<10 then
mapout.addobj(gr,uo.getx('finditem'),uo.gety('finditem'))
endif
uo.ignore('finditem')
uo.findtype(-1,-1,'ground')
until not uo.findcount()
endif
uo.ignorereset()
endif
uo.print('Setup...')
mapout.Setup(x,y,ChestX,ChestY) #Запускаем алгоритм поиска
if mapout.Size() then #Если есть размер вектора пути - алгоритм успешно нашел путь
uo.print('Путь вычислен!')
mapout.first() #Ставим указатель на первый элемент массива
repeat
#Тут делаем коррекцию ходьбы.
uo.print('X='+str(mapout.getx())+' Y='+str(mapout.gety()))
wait(10)
until not mapout.next() #Крутим цикл, пока массив не дойдет до конца
#Тут производим какие-то действия, добираем ресы из сундука или ресаемся...
mapout.last() #Устанавливаем указатель на последний элемент массива (он уже там, но малоли...)
repeat
#Тут делаем коррекцию ходьбы.
uo.print('X='+str(mapout.getx())+' Y='+str(mapout.gety()))
wait(10)
until not mapout.back() #Крутим цикл до начала вектора
else #Если нет размера вектора пути - путь не найден. Можно попробовать создать поиск с другим алгоритмом.
uo.print('Ошибка вычисления пути!')
endif
end sub
Может застревать на входах/выходах из пещер, там сложная статика, пока ещё не разобрался с ней. Клиент не может пройти на свободном месте.
Добавил функции по работе с тайлами:
Code:
UO.SetMulPath(Path) - Установить путь к папке с *.mul файлами (map*.mul, statics*.mul, staidx*.mul, tiledata.mul). Path - строка.
UO.SetShowZ(Mode) - Установить режим отображения Z координаты в информации. 0 - отключить, 1 - включить. Mode - число.
UO.GetLandscapeTile(X, Y, Map) - Получить ИД тайла земли в координатах X,Y на карте номер Map. X, Y, Map - числа. Возвращает строку.
UO.GetStaticTiles(X, Y, Map) - Получить ИД всех тайлов статики в координатах X,Y на карте номер Map. X, Y, Map - числа. Возсращает строку.
UO.GetTileFlags(TileGroup, TileID) - Получить флаги тайла соответствующей группы (TileGroup=0 - Landscape Tile, TileGroup=1 - Static Tile). TileGroup - число, TileID - строка. Возвращает строку.
Contains(Source, Flag) - Узнать, входит ли Flag в набор Source. Source, Flag - числа. Возвращает 1 если Source содержит Flag и 0 если нет.
GetLandscapeTile возвращает информацию в формате TileID, при включенной ShowZ в формате TileID(Z)
GetStaticTiles так же, как и GetLandscapeTile, но перечисляет все тайлы статики, находящиеся в заданных координатах через запятую. Если тайлов статики не обнаружено - вернет пустую строку.
При ошибке возвращают строку -1.
Пример:
Code:
sub test_gettile()
uo.setmulpath('E:\Ultima Online')
uo.setshowz(1)
uo.print('Landscape Tile ID(Z) = '+uo.getlandscapetile(4376,1119,0))
uo.print('Array of Static Tile ID(Z) = '+uo.getstatictiles(4376,1119,0))
uo.setshowz(0)
uo.print('Decimal Landscape Tile ID = '+str(uo.hex2int(uo.getlandscapetile(4372,1119,0))))
if (contains(0x12,0x10)) then
uo.print('0x12 Have! 0x10')
else
uo.print('0x12 NOT have 0x10!')
endif
if (contains(0x9,0x10)) then
uo.print('0x9 Have! 0x10')
else
uo.print('0x9 NOT have 0x10!')
endif
end sub
Выведет в чат:
Code:
Landscape Tile ID(Z) = 0x00C4(0)
Array of Static Tile ID(Z) = 0x177C(0)
Decimal Landscape Tile ID = 218
0x12 Have! 0x10
0x9 NOT have 0x10!
Чтоб узнать, проходимый это тайл или нет:
Узнайте TileID, укажите TileGroup (земля (0) или статика (1))
Флаг проходимости тайлов 0x40
Проверьте тайл на проходимость:
Code:
if Contains(uo.hex2int(UO.GetTileFlags(TileGroup,TileID)),0x40) then
//Непроходимый тайл
endif
Флаги УО (источник
http://uo.stratics.com/heptazane/fileformats.shtml):
Code:
0x00000001 Background
0x00000002 Weapon
0x00000004 Transparent
0x00000008 Translucent
0x00000010 Wall
0x00000020 Damaging
0x00000040 Impassable
0x00000080 Wet
0x00000100 Unknown
0x00000200 Surface
0x00000400 Bridge
0x00000800 Generic/Stackable
0x00001000 Window
0x00002000 No Shoot
0x00004000 Prefix A
0x00008000 Prefix An
0x00010000 Internal (things like hair, beards, etc)
0x00020000 Foliage
0x00040000 Partial Hue
0x00080000 Unknown 1
0x00100000 Map
0x00200000 Container
0x00400000 Wearable
0x00800000 LightSource
0x01000000 Animated
0x02000000 No Diagonal
0x04000000 Unknown 2
0x08000000 Armor
0x10000000 Roof
0x20000000 Door
0x40000000 StairBack
0x80000000 StairRight
Добавил возможность вызова скрипта с параметрами из хоткеев (или создание нового трида из уже запущенного скрипта)
,exec FunctionName#Params1#...#ParamNFunctionName - соответственно имя функции;
Params - передаваемые в неё параметры.
Params перечисляются используя разделитель не запятую, а #.
Ограничение по кол-ву параметров - 20.
Параметры строчного типа должны и быть вковычках.
Числовые параметры или имена переменных нужно записывать без ковычек.
Если в строчке необходим пробел - он должен быть заменён на $, ибо в обработку дллкой приходит функция уже без пробелов.
Пример:
Требуется вызвать функцию asd с параметрами: Переменная,Число,Строка
Где-то на просторах скрипта находится:
Code:
var Param1='Param1_data'
sub asd(a1,a2,a3)
uo.print(a1)
uo.print(str(a2))
uo.print(a3)
wait(10000)
end sub
В окне УО (или забиваем в хоткей) пишем
Code:
,exec asd#Param1#123#'Param3$with$spaces'
script.dll обработает этот запрос на вызов функции, создаст временную функцию с названием <FunName>_WithParams(), запустит её и из неё вызовет необходимую функцию
Code:
sub asd_WithParams()
asd(Param1,123,'Param3 with spaces')
end sub
В итоге в систем чате УО имеем:
Code:
Param1_data
123
Param3 with spaces
В списке запущенных скриптов, 10 секунд, будет висеть созданная функция asd_WithParams
Добавил функции (по-сути аналог SetGlobal/GetGlobal, только чуть более функциональные) по работе с глобальными переменными:
Code:
UO.GListSet(Name, Value) #Добавить/заменить глобальную переменную
UO.GListGet(Name) #Получить значение глобальной переменной
UO.GListClear() #Очистить список глобальных переменных
UO.GListSize() #Узнать размер списка (кол-во позиций) глобальных переменных
UO.GListPosName(Position) #Получить имя глобальной переменной, которая находится в позиции Position
UO.GListPosValue(Position) #Получить значение глобальной переменной, которая находится в позиции Position
Индексы позиций от 0 до Size-1
Теперь при возникновении ошибки
"Unhandled exception in parser." функция, в которой возникла данная ошибка
незамедлительно стирается из списка запущенных функций.
Добавлена проверка на то, запущенна ли функция в данный момент или нет.
Code:
UO.FunRunning(String Name)
Добавил поиск текста по файлу скрипта (блокнотное Ctrl+F), быстрый переход на указанную строку (Ctrl+G), замену текста (Ctrl+H).
Соответствующие кнопки добавлены на панель.
Хоткеи редактора:
Ctrl+O - открыть скрипт
Ctrl+S - быстрое сохранение последнего открытого скрипта. Если вручную не был загружен скрипт - запросит путь для его сохранения.
Ctrl+F/G/H - см. выше.
Диалоги открытия/сохранения скрипта не блокируют доступ к инжекту и окну УО.
Скрин редактора:
Над недостатками и всплывающими багами буду работать в свободное время)