Слил всю инфу по доступным функциям в первый пост.
Переписал алгоритм поиска пути. Теперь он не колдует пол часа над файлами УО. Вычисление пути на фрагменте карты 150х150 (без учета игровых объектов) заняло около секунды. С учетом объектов УО - 3 секунды.
Описание класса:
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
Может застрять на входах/выходах из пещер, там сложная статика, пока ещё не разобрался с ней. Клиент не может пройти на свободном месте.