Как написать скрипт на ламбер

тут можно задать вопрос по скриптингу
Post Reply
Edred
Moderator
Moderator
Posts: 559
Joined: 28.03.2006 21:29

Как написать скрипт на ламбер

Post by Edred »

Когда у меня найдется время на уроки - хз, но вот эту тему попробую расписать в подобной форме. Назовем ее, скажем:

УРОК 11 :)

Внимание: в этом уроке не будет дано готового скрипта на ламбер! Но будут приведены необходимые функции и алгоритмы, так, чтобы желающий в этом разобраться мог написать себе такой скрипт сам, с учетом особенностей своего шарда.

Итак, ламбер. Что нам надо для хорошего ламбера? Во-первых, нам потребуется массив координат деревьев, их типов, а также, с учетом отсутствия удобной ходилки с обходом препятствий, массив координат в которых чар должен стоять перед деревьями. Естественно, писать такой массив в файл) сложно и не нужно, проще такое сделать на скрипте.

Потому заходим в игру на инжекте. Нам потребуется домик в лесу/около леса, рядом прилоченный/засечуренный сундук. Встаем около сундука и в инжекте запускаем этот скрипт:

Code: Select all

sub MarkRail()
; ====================================================
; ВНИМАНИЕ! Это скрипт для инжекта, а не для стелса!!!
; ====================================================
; Скрипт разметки маршрута передвижения чара и копки/рубки
; Создает файл со строками вида:
; X Y TileType TileX TileY TileZ
; где: X, Y - координаты чара в узловой точке
;      TileType   - тип цели. То есть тип тайла или статики,
;                   которую либо рубим/либо копаем
;      TileX, TileY, TileZ - координаты цели
; Узловые точки могут быть двух видов - либо тут копаем/рубим,
; либо тут чар должен повернуть при передвижении. Если второе, то
; последние четыре параметра равны 0. Учитывайте это в своих скриптах.
; 
; Как работает? Записываются начальные координаты с нулями в четырех последних
; параметрах, запоминается направление взгляда чара, чистится журнал.
; Потом каждые 50 мс проверяются: не изменилось ли направление взгляда чара, не
; появилось ли сообщение в журнале о копке/рубке. Если одно из условий выполнено,
; то в файл записывается строка с текущими данными чара. То есть, если чар повернул,
; но копка/рубка не началась - пишется строка с четырьмя нулями в конце, если есть
; сообщение - пишутся координаты ласттайла и тип из-под него.
; Скрипт прекращает работу при появлении в журнале слова Finish, произнесенного
; данным чаром (проверяется по сериалу строки журнала).
;
; v.1.01b (с) Edred
;
; В данной версии данные пишутся в текстовое окно, а не файл.
; Также не проверяется сериал чара, сказавшего Finish.
;
	VAR msg1 = 'You put the'
	VAR msg2 = 'There is nothing'
	VAR msgf = 'Finish'
	VAR cx1, cy1, cdir1, tx1, ty1, tz1, ttyp1, oldx, oldy
	UO.TextOpen()
	UO.TextClear()
	cx1 = UO.GetX()
	cy1 = UO.GetY()
	cdir1 = UO.GetDir()
	UO.TextPrint(str(cx1) + ' ' + str(cy1) + ' ' + '0 0 0 0')
	oldx = cx1
	oldy = cy1
	repeat
		UO.DeleteJournal()
		repeat
			wait(50)
		until UO.InJournal(msg1) OR UO.InJournal(msg2) OR UO.InJournal(msgf) OR UO.GetDir() <> cdir1
		if UO.InJournal(msgf) then
			return
		endif
		If UO.InJournal(msg1) OR UO.InJournal(msg2) Then
			cx1 = UO.GetX()
			cy1 = UO.GetY()
			ttyp1 = UO.LastTile( 0 )
			tx1 = UO.LastTile( 1 )
			ty1 = UO.LastTile( 2 )
			tz1 = UO.LastTile( 3 )
			UO.TextPrint(str(cx1) + ' ' + str(cy1) + ' ' + str(ttyp1) + ' ' + str(tx1) + ' ' + str(ty1) + ' ' + str(tz1))
			oldx = cx1
			oldy = cy1
			cdir1 = UO.GetDir()
		Else
			cx1 = UO.GetX()
			cy1 = UO.GetY()
			if (cx1 <> oldx) OR (cy1 <> oldy) then
				UO.TextPrint(str(cx1) + ' ' + str(cy1) + ' ' + '0 0 0 0')
				oldx = cx1
				oldy = cy1
			endif
			cdir1 = UO.GetDir()
		Endif
	until false
endsub
Проведите чара от сундука по лесу, по разу рубя каждое рубимое дерево. Завершите маршрут снова около сундука.

На выходе у нас будет файл (не забудьте перекинуть координаты из текстового окна в файл) такого вида:

Code: Select all

3266 2767 0 0 0 0
3266 2766 3280 3265 2766 10
3266 2765 0 0 0 0
3265 2765 0 0 0 0
3262 2765 0 0 0 0
3259 2762 3291 3258 2762 10
3259 2760 3296 3258 2761 10
3259 2754 3286 3258 2754 10
3260 2754 0 0 0 0
.......
Теперь нам надо написать скрипт, который будет работать по такому файлу.

Для этого, для начала, нам надо определиться, в каком виде мы данные из этого файла будем использовать в скрипте. Считывать данные из файла мы можем через StringList (фактически - массив строк переменной длины), но использовать эти строки в скрипте не очень удобно. Гораздо лучше для этого годится Record.

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

Code: Select all

type LumbRecord = Record
	x,y,tt,tx,ty,tz : integer;
	end;
Здесь есть еще одна вещь: объявление type. В Паскале есть различные виды данных, типа integer (целые числа), string (строки), array (массивы). Для удобства программистов есть еще возможность объявить свой собственный тип данных, для этого и используется команда type. В приведенном выше коде мы объявляем тип данных под названием LumbRecord, который представляет из себя запись, каждая ячейка которого содержит пять целочисленных элемента, названия для этих элементов мы также задали.
Теперь мы можем объявлять любое количество нужных нам записей, просто используя LumbRecord как тип данных.

Code: Select all

var
LumberDim : array [0..5000] of LumbRecord;
Мы создали массив записей с максимальной длиной 5000 ячеек. Вполне возможно, что у нас будет меньше точек на маршруте, это нестрашно, главное - чтобы не было больше.

Теперь надо занести в этот массив данные из файла.

Для этого будем использовать такую процедуру:

Code: Select all

procedure GetRail(FileNam : String);
var
List : TStringList; 
i : integer;
s : string;
begin
	List := TStringList.Create;
	List.LoadFromFile(FileNam);
	for i := 0 to List.Count-1 do
	begin
		s := List.strings[i] + ' ';
		LumberDim[i].x := StrToInt(Copy(s,1,Pos(' ',s)-1));
		Delete(s,1,Pos(' ',s));
		LumberDim[i].y := StrToInt(Copy(s,1,Pos(' ',s)-1));
		Delete(s,1,Pos(' ',s));
		LumberDim[i].tt := StrToInt(Copy(s,1,Pos(' ',s)-1));
		Delete(s,1,Pos(' ',s));
		LumberDim[i].tx := StrToInt(Copy(s,1,Pos(' ',s)-1));
		Delete(s,1,Pos(' ',s));
		LumberDim[i].ty := StrToInt(Copy(s,1,Pos(' ',s)-1));
		Delete(s,1,Pos(' ',s));
		LumberDim[i].tz := StrToInt(Copy(s,1,Pos(' ',s)-1));
		Delete(s,1,Pos(' ',s));
	end;
	MaxPosL := i;
end;
Разберем процедуру. Мы объявляем StringList под именем List, создаем его, загружаем в него файл и в цикле от 0 (то есть от начала) до List.Count-1 (List.Count - длина файла, так как мы считаем от 0 - то цикл идет до List.Count-1 элемента. Если вы этого не понимаете - это не ко мне. Читайте базовые учебники по программированию) перебираем строки файла, загруженные в StringList.
Так как мы будем разбирать строку на отдельные элементы через пробелы, то для удобства добавим в конец строки пробел (я для удобства делаю это уже в отдельной переменной s). Теперь функцией Copy(скопировать из строки s часть, начиная с 1 символа до позиции перед первым пробелом) выделяем символы первого числа, преобразуем его из строки в число и заносим в первый элемент данной ячейки нашего массива записей. Формат обращения к элементам ячеек таков:

Code: Select all

LumberDim[ячейка].элемент
После этого мы для удобства дальнейшей работы просто удаляем из строки символы начиная с 1 до первого пробела включительно. Дальше все точно также повторяется еще 5 раз (у нас 6 элементов в каждой ячейке массива).
В конце, после выхода из цикла, мы записываем в переменную MaxPosL получившуюся длину массива. Не забудьте объявить эту переменную в начале скрипта как целочисленную!

Теперь уже можно писать главную процедуру нашего скрипта. Что будет представлять из себя такой скрипт? Это будет цикл, в котором будет какой-то блок, отвечающий за перемещение чара по маршруту от сундука к сундуку обратно по лесу и рубку деревьев, какой-то блок отвечающий за разгрузку чара, еще какие-то блоки по вашему желанию (например, рес чара если он был убит, или взятие нового топора). Так и напишем:

Code: Select all

repeat
	...ходим и рубим...
	...разгружаемся...
	...что-то еще...
until false;
Я сделал бесконечный цикл, но вы можете ограничить его чем-нибудь. Разгрузку и прочие действия вы будете писать сами, я дальше рассматриваю только первый блок, блок хождения и рубки.

Этот блок тоже будет представлять из себя цикл, но уже с конкретным количеством шагов, так что нам лучше всего подойдет цикл for...do:

Code: Select all

For k := 0 to MaxPosL-1 do
begin
	GotoXY(LumberDim[k].x,LumberDim[k].y,0,true);
	if LumberDim[k].tt <> 0 then LumbCurTree(LumberDim[k].tt,LumberDim[k].tx,LumberDim[k].ty,LumberDim[k].tz);
end;
Я сознательно упростил наши действия на каждом шаге цикла, оставив за бортом проверки на смерть чара, на макс вес и прочее. Все это вы можете уже добавить сами. Процедура LumbCurTree отвечает за рубку конкретного дерева, причем она получает в качестве параметров тип тайла и его координаты. В этой процедуре вы должны будете сделать какие-то необходимые проверки, использование топора и направление ловушки на данный тип тайла с заданными координатами. После этого необходимо проверить сообщения о успехе/физле рубки, если необходимо, повторить рубку в цикле, проверить вес и прочее. Но это уже обычно и тут на форуме есть примеры как это делать.

Функцию GotoXY() вы можете найти в разделе Scripts данного форума.
Edred
Moderator
Moderator
Posts: 559
Joined: 28.03.2006 21:29

Post by Edred »

Комментируем, спрашиваем уточнения, а главное - поправляем. Наверняка где-то нафантазировал. :oops:
SLAK
Novice
Novice
Posts: 65
Joined: 15.01.2006 3:20

Post by SLAK »

procedure GetRail(FileNam : String);
*****
for i := 0 to List.Count-1 do
*****
MaxPosL := i;
For k := 0 to MaxPosL-1 do
Может я чегото не понимаю, но зачем дважды отнимать?
Edred
Moderator
Moderator
Posts: 559
Joined: 28.03.2006 21:29

Post by Edred »

Задача:

Code: Select all

program Test;
var
i, a : integer;
begin
for i := 1 to 5
begin
   a := i;
end;
addtosystemjournal('a=' + inttostr(a) + ' i=' + inttostr(i));
end.
Вопрос: можешь сказать, чему будут равны "a" и "i" при выводе? Проверь свой ответ. :P

Ответ из конца учебника:

a=5
i=6

Почему? Подумай сам, ты точно можешь до этого додуматься...
Spoiler
Posts: 6
Joined: 20.10.2006 9:39

Post by Spoiler »

Небудем пальцами тыкать, но уроков так и нет...
А ведь именно такие простейшие уроки как "ХЕЛЛО ВОРЛД" для стелса и нужны массам, тобиш мне. Я уже говорил что в програмировании 0. В школе информатику изучали на картонках с изображением клавиатуры. И уроки по инжекту помогли освоить основы. Я на инжекте могу написать скриптик средней паршивости и как бы не смеялись на ними "Destruction" и "You Must Die" , они всетаки у меня работают.
Урок №11 это кул но с урока №1 начать былоб деликатней :)
Edred
Moderator
Moderator
Posts: 559
Joined: 28.03.2006 21:29

Post by Edred »

Читай уроки по инжекту. Я все равно не собираюсь повторять одно и тоже. А команды стелса для игры полностью аналогичны инжектовским. Есть некоторые мелкие различия и некоторое количество дополнений. О них и имеет смысл написать, а переписывать те же уроки, на фиг? Мне лично жалко свое свободное время. Его очень мало.

Насчет тырканья пальцем: ты, похоже, перепутал малость. Я совсем не обязан писать какие-либо уроки. Я сказал, что когда будет время и когда придет нужное время я этим займусь. Урок по скрипту на ламбер просто родился преждевременно. Сначала надо привести в порядок хелп на сайте. Потому что никакие уроки его не заменят.
SLAK
Novice
Novice
Posts: 65
Joined: 15.01.2006 3:20

Post by SLAK »

Иногда аж стыдно насколько я глупый :)
Пасиб Эдред, буду знать.
uzver1234
Neophyte
Neophyte
Posts: 17
Joined: 14.09.2010 16:09

Post by uzver1234 »

спасибо:) заюзал. прикрутил простейшую ходилку которая ходит по прямой. и все работает:) как часы. при каждой рубке добавил проверку на вес. и возврат домой при наборе веса=сила*3. идеи про такой файлик с координатами сам вынашивал, но пока для меня сложно.
grundick
Developer
Developer
Posts: 271
Joined: 31.01.2008 21:16

Post by grundick »

Вот вы динозавры )
uzver1234
Neophyte
Neophyte
Posts: 17
Joined: 14.09.2010 16:09

Post by uzver1234 »

гыгыкс:)) да. на дату не посмотрел:))
всеравно актуально. спасибо:))
Post Reply