PDA

Просмотр полной версии : пишем свой нубский скрипт для автоточки


SeregaZ
24.12.2011, 20:13
сервер в дауне... и лежать будет незнамо сколько. решил я создать тему-конкурс о создании нубского скрипта для автоточки для любого сервера, где работает l2ph, с подробным расписыванием что нам нужно и как и где и почему. дабы любой смог бы подправить его для своего сервера без проблем. тема будет в виде конкурса для новичков, с заданиями найти что-то на форуме и скопипастить с нужными поправками в эту тему.




задание первое:
для начала нам нужен механизм отправки пакетов из l2ph на сервер. (он стандартный для всех серверов). выкладывайте кусочек кода, которым можно отправить что-то на сервер :)
правильный ответ: NLObP
buf:=hstr('0F');
SendToServerEx(Name);
buf - это переменная, в которую мы записываем информацию, которую надо отправить на сервер.

hstr('0F') - путем применения hstr мы записываем в нашу переменную buf кусочек информации (в данном случае коротенький пакет 0F) в понятном виде для сервера.
buf:=0F; неправильно
buf=hstr(0F); неправильно

SendToServerEx(Name); - этой командой мы посылаем buf на сервер. причем посылаем от имени конкретного клиента Name - это нужно для того, если у вас запущено 2-3 окна, чтобы l2ph не путался от какого именно окна посылать данные серверу.





задание второе:
привести кусочек кода для оператора если - if
правильный ответ: Pinko & NLObP
if (STAKAN=0) then begin // если стакан пуст, то начать следующие операции
STAKAN:=1; // налить
end
else begin // в случае, если стакан изначально полон,
//то срабатывает эта часть кода

STAKAN:=0; //выпить и закусить=)
end;
здесь мы рассматриваем сложный оператор если - if - сложный то есть с двумя значениями "если равно" и "если не равно" (else).
важная деталь что тут два end, причем первый должен быть обязательно без точки с запятой.

в случае простого if код будет выглядеть чуть чуть по другому:
if (STAKAN=0) then begin // если стакан пуст, то начать следующие операции
STAKAN:=1; // налить
end;

бывают случаи когда нужно провести проверку сразу двух параметров - то здесь нам поможет and. выглядит он следующим образом:
if (STAKAN=0) and (ZAKUSKA=0) then begin // если стакан пуст и нет закуски, то начать следующие операции
STAKAN:=1; // налить
ZAKUSKA:=1; // достать банку с огурцами
end;

бывают случаи когда нам нужно или - если это равно чему-то или если вон то равно чему-то. в этом случае нам поможет or:
if (STAKAN=0) or (ZAKUSKA=0) then begin // если стакан пуст или нет закуски, то начать следующие операции
STAKAN:=1; // налить
ZAKUSKA:=1; // достать банку с огурцами
end;

со всеми вариантами if - если - есть важная деталь. в самом if сравнение следует писать без двоеточия! это наиболее частая ошибка новичков. пример неправильного синтаксиса:
if (STAKAN:=0) then begin

также следует помнить какого типа наша переменная STAKAN - цифровая или текстовая. если STAKAN изначально текстовая, то сравнить текст с цифрой не получится. нужен будет вариант с апострофом:
// если STAKAN текстовая переменная то
if (STAKAN=0) then begin // не правильно!
if (STAKAN='0') then begin // правильно.




задание третье:
нужен пример таймера. задача сложная :)
правильный ответ: Breadfan
немного промодифицируем (пронубируем, чтоб понятнее было), и добавим пошаговость таймеру:


var //var это блок, где объявляются переменные и определяется их тип.
Timer01: TTimer; // указываем что Timer01 это таймер (TTimer)
a:integer; // a - это цифровая переменная integer
// на будущее *:string; - текстовая переменная

procedure OnTimer01(Sender: TObject); // наша процедура по таймеру
begin
Timer01.interval := 1000+round(random()*1000); // каждый раз у нас будет рандомный промежуток времени от одной до двух секунд.
// нужно для "очеловечивания" нашего скрипта, чтобы не спалили злые админы :)
// random()*1000 - случайное число от 0 до 1000
// round(random()*1000) - округление того случайного числа до ближайшего целого.
// например рандом выбрал 352,2456575474 - нахрена нам эти знаки после запятой? вот и округляем.

case a of // проверка цифровой переменной a и отфутболивание на нужный пункт
// по сути наша а это метка для управления шагами в таймере.
// то есть через эту переменную а мы можем запросить конкретный шаг таймера, когда он тикнет в следующий раз

1:begin
buf:=''; // что-то мы записываем для отправки
SendtoserverEx(Name); // отправляем на сервер наш buf от конкретного игрока - Name
inc(a); // увеличение цифровой переменной a на +1,
// то есть переключение на следующий пункт таймера, когда таймер сработает на следующий раз
end;
2:begin
buf:='';
SendtoserverEx(Name);
inc(a);
end;
end;
end;

procedure Init; // при старте скрипта производятся следующие операции
begin
Timer01:=TTimer.Create(nil);
Timer01.OnTimer:=@OnTimer01;
Timer01.enabled:=true; // таймер включен
Timer01.interval:=1000; // начальный таймер у нас составляет 1 секунду
// все эти четыре строчки касаются только таймера
// но помимо таймера здесь могут быть и другие начальные данные, нужные для старта скрипта.
end;

procedure Free; //Вызывается при выключении скрипта
begin
Timer01.enabled:=false; // таймер отключаем
end;

begin
// тут код, который будет выполнятся по приходу каждого пакета
end.






задание четвертое:
нужны пакеты inventory update с пометкой что было куплено (на 2 предмета +шмотка -адена)
action - наведение таргета на любого нпс.
пакет useitem на использование любого предмета
которые мы потом разберем на составляющие :)

народ пошел нынче ленивый... самому придется приводить пример пакета инвентори апдейт и расписывать его содержимое.

итак! сам пакет:
27 02 00 02 00 04 00 E7 A0 1A 40 39 00 00 00 C6 EB 00 00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 14 A5 1A 40 C2 19 00 00 01 00 00 00 00 00 00 00 00 00 00 40 00 00 00 00 00 00

в поле л2пх видно его расшифровку. так что же нам полезно из той информации, что там расписано?
http://dmarket.pusku.com/images/l2ph.jpg
(эти имайж хостинги просто заепли удалять нужные картинки)
в кратце, при покупке лука, в инвентаре произошло два изменения. первое - исчезла одна аденка - цена стоимости лука, и появился сам лук. в количестве одна штука и не заточен.
нам интересен пункт ObjectId - в данном случае 1075488020 это есть уникальный номер лука на данном сервере игры. запомним, он нам понадобится. хотя точнее нам понадобится его хекс вариант 14 A5 1A 40 дабы не парится насчет всяких там преобразований...

изменяем четвертое задание: следует расписать точно также пакет с покупкой точки - что пришло, что ушло и найти ObjectId для заточки.

NLObP
25.12.2011, 01:26
кусочек кода, которым можно отправить что-то на сервер

//Пакет RequestItemList
buf:=hstr('0F');
SendToServerEx(Name);

SeregaZ
25.12.2011, 02:03
нечестно! конкурс для новичков, а не для корифеев программирования :)

Pinko
25.12.2011, 20:45
задание второе:
привести кусочек кода для оператора если - if
if (STAKAN=0) the // ежли стакан пуст
begin // налить

NLObP
25.12.2011, 21:29
end
else \\ стакан полон
begin
.. \\выпить и закусить=)
end;

SeregaZ
25.12.2011, 22:20
нет новичков... никому не интересно свой собственный скрипт наваять... все приходят за готовыми :(

ооо! предлагаю идею! при нажатии на кнопку "скачать скрипт" - вылазила программа с дибровым-галкиным - кто хочет стать миллионером с вопросами и вариантами ответов. если пользователь ответит на 3 из 4 - то скачка ему разрешается :)

SeregaZ
27.12.2011, 02:32
завтра придется самому ответить :) ну четвертое задание будет простое.

Breadfan
27.12.2011, 12:24
таймер, с рендомным интервалом:
var
TT1:ttimer;
res:integer;
min, max:integer;
procedure Init; //Вызывается при включении скрипта
begin
min:=500;
max:=7000;
TT1:=TTimer.Create(nil);
TT1.OnTimer:=@Mesg;
TT1.enabled:=True; //таймер вкл.
TT1.interval:=1000; //стартовое значение интервала
end;
procedure Free; //Вызывается при выключении скрипта
begin
TT1.enabled:=False;
end;
procedure Mesg; //проц-ра выполняющаяся по таймеру
begin

res:=min+int((max-min)*random); //где мин\макс - границы диапазона
TT1.interval:=res; //интервалу присваевается новое значение
SendMsg('Интервал: '+inttostr(TT1.interval)); //выводим интервал
end;
begin
end.
а заодно - удобнее было бы сделать stakan - булевым, используя его без всяких =0\=1

if (STAKAN=0) or (ZAKUSKA=0) then begin // если стакан пуст или нет закуски, то начать следующие операции
STAKAN:=1; // налить
ZAKUSKA:=1; // достать банку с огурцами
end; код неверен. если стакан налит но закуски нет - все равно нальет в стакан.

SeregaZ
27.12.2011, 16:51
if (STAKAN=0) or (ZAKUSKA=0) then begin // если стакан пуст или нет закуски, то начать следующие операции
STAKAN:=1; // обновить
ZAKUSKA:=1; // доложить огурцов в тарелку
end;

пофиксил :cool:

kolr
27.12.2011, 17:24
с таймером както так
var
Timer01: TTimer;
Timer02: TTimer;
Timer03: TTimer;


procedure OnTimer01(Sender: TObject);
begin
{делаем дела}
Timer01.enabled:=false;
end;


procedure OnTimer02(Sender: TObject);
begin

{делаем дела}
Timer02.enabled:=false;
Timer03.enabled:=true;
end;
procedure OnTimer03(Sender: TObject);
begin

{делаем дела}
Timer03.enabled:=false;
end;


procedure Init;
begin
Timer01:=TTimer.Create(nil);
Timer01.OnTimer:=@OnTimer01;
Timer01.enabled:=false;
Timer01.interval:=500;

Timer02:=TTimer.Create(nil);
Timer02.OnTimer:=@OnTimer02;
Timer02.enabled:=false;
Timer02.interval:=500;

Timer03:=TTimer.Create(nil);
Timer03.OnTimer:=@OnTimer03;
Timer03.enabled:=false;
Timer03.interval:=3700;
end;

procedure Free;
begin
Timer01.free;
Timer02.free;
Timer03.free;
end;

SeregaZ
27.12.2011, 17:36
kolr, комментов в коде нет. не айс :) у Breadfan лучше :) понятнее.

в твоем случае добавь, что у тебя включаются таймеры один за другим.

срезюмирую ответ чуть чуть попозже, тут l2ph и клиента нет :(

задание четвертое:
нужны пакеты inventory update с пометкой что было куплено (на 2 предмета +шмотка -адена)
action - наведение таргета на любого нпс.
пакет useitem на использование любого предмета
которые мы потом разберем на составляющие :)

Breadfan
28.12.2011, 06:31
поправил

dyh9l
28.12.2011, 12:41
Breadfan, разве если во фрии не освободить таймер от памяти оно не кританет при след запуске?

Breadfan
28.12.2011, 21:54
нет, как бы то странно не было

goodvin1709
05.01.2012, 02:37
У меня критовало

SeregaZ
05.01.2012, 06:49
видимо не в таймере дело, а в переменных, которые не освободились при отключении скрипта.

и какая версия л2пх?

goodvin1709
11.01.2012, 17:55
Если скрипт для заточки.
У меня было 3 таймера(точил в 3-4 окна) логало жуть.
поставил 2 таймера(сжал закупку точек и пушек в 1 процедуру и 1 таймер)
тоже логает но не так уже.
Кто может помочь напишыте в ПМ.(скрипт заточки с4 сервер).
тупит именно база инвентаря.

Добавлено через 1 час 26 минут
^^^^^^Все уже сам все переписал пашет на ура.

SeregaZ
11.01.2012, 18:09
goodvin1709, не проще ли было сделать три простых скрипта для трех окон, в каждом дописав юзфорконнекшион?
и какой у тебя принцип? я веду к купил одну и точит до заданной длинны :) твой какой? купил 79 луков и точит +1 каждый, пока все не будут заточены на единичку?

goodvin1709
11.01.2012, 18:20
У мну цыклом перебирает и находит необходимую пушку
Вот так я шукаю пушку
Procedure FindItemToEnchant ;//Ищем Пушку.
Var
I : Integer ;
Begin
ItemToEnchant := 0 ;//Обнуляем текущую для заточки пушку.
For i := 1 to InventoryS do //Перебор инвентаря.
Begin
If (ItemBase[i,1] = ItemID) and (ItemBase[i,3] < EnchantTarget) then //Если параметры ячейки массива подходят то выбираем ету пушку для заточки.
Begin
ItemToEnchant := ItemBase[i,2] ; //назначим затачимую вещь.
i:=InventoryS;//Выходим с цыкла.
End ;
End ;
End ;


поле этого беру ItemToEnchant и пихаю в заточку.
Также я делаю поиск для точки и пакетом вроде
buf := hstr('14') ;
WriteD(Scroll) ;
WriteD(0) ;
SendToServerEx(CharName) ;
Жду делаем 500
и вставляю пушку.
buf := hstr('58') ; //Пакет на клик.
WriteD(ItemToEnchant) ; //Указываем пушку.
SendToServerEx(CharName);
и вот так заточило дальше идет пакет 27 я проверяю что иммено сталось по UpdateType от этого пакета.
если надо очищаю,додаю,правлю массив.И снова поиск точки и пушки и снова пуск заточки.
P.S у меня 3 окна и 3 разных скрипта.
Но точит и поттормаживает.

supernewbie
11.01.2012, 18:45
goodvin1709, ваще-т никакого выхода из цикла там нет

Добавлено через 1 минуту
фастскрипт сам по себе медленный, циклы там ваще нежелательны
пиши плагин и всё будет зае чётко

goodvin1709
11.01.2012, 19:35
ага спасибо за совет но я еще плагины в общем не умею писать если бы вы товарищь выложили гайдик только нормальный как писать плагин был бы очень доволен и вам бы спасибо за него..)

supernewbie
11.01.2012, 19:49
дык всё ж в хелпе по пх написано, в разделе Плагины

goodvin1709
11.01.2012, 21:35
дайте пример пожалуйсто как втавить туда простую(любую) функцыю или процедуру,а то я чтото нефига там непонел.

supernewbie
11.01.2012, 22:45
ну вот сорцы плагина, добавляющего процедуру Play

goodvin1709
11.01.2012, 23:02
Дядя supernewbie я вам очень блогодарен.
Но я непонел чуток:

function OnCallMethod(const ConnectId, ScriptId: integer;const MethodName: String;var Params,FuncResult: Variant ): Boolean; stdcall;
begin
Result := false;
if MethodName='PLAY' then
begin
Play(params[0]);
Result:=true;
exit;
end;

Именно эту процедуру я непонел.

supernewbie
12.01.2012, 01:17
что там непонятного то, OnCallMethod вызывается когда пх ищет процедуру по имени, вызывает её с параметрами ConnectId - ид соединения(хендл сокета), дальше ScriptId - полюбому нужен для каких-нибудь пхашных апишек, MethodName - имя метода заглавными символами, Params - массив вариантов в варианте, FuncResult - то что вернется в скрипт, опять же может быть че угодно т.к. вариант, и возвращает boolean который отвечает за то чтобы пх угоманилась и не искала функцию, true - захендлили запрос, false - продалжай искать
ну эт как я понял, мб че-то не так, но это полюбому не существенно
собсна берем имя метода, сверяем с нашими именами, если есть совпадение - грим что захендлили и хендлим, в данном случае я смотрю что пх ищет метод с именем PLAY - проигрываю музон (хендлю), грю что всё путём, метод нашелся - Result:=true; , и сваливаю к чертям из функции - exit;

goodvin1709
12.01.2012, 03:04
supernewbie почему моя Функция нехрена не работает мм?.вот как делал:Фунцыя тесовая Str(N:Integer):String;
так вот тестил:

procedure Init;
begin
SendMSG(str(20));
end;
procedure Free;
begin
end;
begin
end.

Сам плагин:

library Strin;
uses
FastMM4 in 'fastmm\FastMM4.pas',
FastMM4Messages in 'fastmm\FastMM4Messages.pas',
variants,
usharedstructs in 'units\usharedstructs.pas',
Classes;

var
ps:TPluginStruct;
hwnd:cardinal;


Function Str(N:integer):String;
begin
Result:=VarToStr(N);
end;

procedure OnLoad; stdcall;
begin
hwnd:=AllocateHWnd(nil);
end;

procedure OnFree; stdcall;
begin
DeallocateHWnd(hwnd);
end;

function GetPluginInfo(const ver: cardinal): PChar; stdcall;
begin
Result:='My first function in dll';
end;

function SetStruct(const struct: PPluginStruct): Boolean; stdcall;
begin
ps:=struct^;
Result:=True;
end;

Procedure OnRefreshPrecompile; stdcall;
begin
ps.UserFuncs.Add('Function str(N:Integer):String');
end;

function OnCallMethod(const ConnectId, ScriptId: integer;
const MethodName: String; // имя функции в верхнем регистре
var Params, // параметры функции
FuncResult: Variant // результат функции
): Boolean; stdcall; // если вернёт True то дальнейшая
// обработка функции прекратиться
begin
Result := false;
if MethodName='str' then
begin
FuncResult:=str(params[0]);
Result:=True;
end;
end;

exports
GetPluginInfo,
SetStruct,
OnCallMethod,
OnRefreshPrecompile,
OnLoad,
OnFree;

begin
end.

supernewbie
12.01.2012, 03:47
ну епта, заглавными буквами же нах
на if MethodName='STR' then исправь и четко будет

mira
12.01.2012, 10:20
goodvin1709, ваще-т никакого выхода из цикла там нет

Добавлено через 1 минуту
фастскрипт сам по себе медленный, циклы там ваще нежелательны


ну если делать бикубическую интерполяцию пикселей на изображении и сортировки массивов [0..100500] то да. У меня весь цикл фс выполняетса за 0мс и ниче не грузит. Точнее не позволяет узнать gettickcount.

goodvin1709
12.01.2012, 13:14
Почему когда я пробывал работать с пакетами там всегда либо крит либо крит.что за даже демку пробывал всунуть сервно крит.раз 100 компилил
99% крипт или не пахало.

SeregaZ
12.01.2012, 18:37
а версия l2ph какая?

Pinko
18.08.2012, 01:11
SeregaZ,
поздно пить боржоми когда не работают почкки
ЭТО Я ПРО СЕБЯ !!!!!!!!!!!!!!!!!
таймер не
нужен наверно
надо посылать паккет от клиента после того как придет пакет от серва на потверждение твоего действия
вродетак
менее палево

SeregaZ
18.08.2012, 01:59
наоборот. в этом случае будет палевней - так как скорость намного увеличится. будет куда меньше 1 секунды. человек так не сможет :) по крайней мере ночь точить :) сам понаблюдай - открывай диалоги и вальяжно по менюшкам жми - как раз будет примерно 1 секунда, чуть больше, чуть меньше.
а если сразу по приходу пакета открытия меню открывать следующий пункт - скорость будет куда выше, чем 1 секунда.

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

с другой стороны если пофиг на палево - то твой подход куда лучше в плане достижения нужной степени заточки. так как скорость будет выше, сам скрипт надежнее. и если мой вариант заточит 1-2 лука +20 за ночь, то твой думаю сможет 3-4 успеть точнуть. конечно еще зависит от шансов на конкретном сервере :)

Pinko
20.08.2012, 22:39
в идеале конечно сделать сначала проверку на приход открытия меню, потом рандомную паузу от 1 до 2 секунд. в этом случае мы обезопасим клиент от вылетов из-за лагов.
вот это я имел ввиду .

kpa9pt
20.08.2012, 22:44
А я просто похвастаюсь!!!)))
Написал себе скрипт на х10 сервере, точил щиты Б грейда, за ночь сточило 5к точек (покупая щиты в люксоре и скидывая на +7 в вх).
Вышло гдето порядку 60+ щитов на +7.
А в итоге щит на +10, единственный на сервере).
Могу выложить конекретные обработчики событий при точке, если кому то нужно

Roman32
25.08.2012, 12:09
На х10 5к точек?оО

kpa9pt
25.08.2012, 13:04
На х10 5к точек?оО

Да, там есть задрот играющий с открытия (5 лет) у него 1к чаров с лишним с кубиками и он тратит пол дня на открытие кубиков) и точек у него всяких немеренно, ну и я скупил все б арморки что у него были)

Pinko
25.08.2012, 22:13
kpa9pt,
Выложи . Пригодится .

kpa9pt
26.08.2012, 22:31
kpa9pt,
Выложи . Пригодится .

Тема называется нубский скрипт, если кто-то заинтересован в частях обработки для заточек или движения к нпс или покупок чего либо через мульти сел, могу по выкладывать, а вот рабочий скрипт не вижу я тут тех кому он нужен.
Вот забью окончательно на ла2, выложу сюда тьму скриптов полезных, для олимпа, пвп и т д:)...некоторые просто невероятно полезные...

dyh9l
26.08.2012, 23:36
kpa9pt, один хер, те кому они были бы полезны, не смогут разобраться как их юзать, а тот кто сможет - сам напишет :D

kpa9pt
27.08.2012, 00:39
kpa9pt, один хер, те кому они были бы полезны, не смогут разобраться как их юзать, а тот кто сможет - сам напишет :D

Лан, завтра мб напишу статью сюда про скрипт заточки выложу куски и всё по шагам разберу, всёравно там мало кому такой нужен будет скрипт, мало кто точит б щиты покупая в люксоре их и доставая из вх точки в видде 5к штук)

Pinko
28.08.2012, 23:13
МОЖНО достать из ВОЗДУХА
хи се sXAXAs

kpa9pt
02.09.2012, 17:43
Итак как обещал скрипт пошагово на авто заточку Щитов Б грейда из люксора.

З.Ы.: Писал довольно давно и не выйдет очень красиво в (духе здесь и сейчас) написать описание.
З.Ы2.: Тогда я относился скептически к объявлению переменных в процедуре и поэтому там с ними просто дикий "анал карнавал".
З.Ы3.: Сейчас я понимаю что скрипт можно было бы написать намного проще красивее и лучше но переписывать уже поздно поэтому то что есть:

Писать буду в стиле с чего начать и как продолжить.

Шаг 1.

Нужно записать процедуру для отправки пакета заточки щита, чтобы дальше в циклах обработки её вызывать. Вот она:



procedure UseItem(ItemID:integer);
begin
buf:=#$19;
Writed(ItemID);
Writed(0);
SendToServerEx(name);
end;

procedure Enchant(Id:integer);
begin
buf:=#$D0;
Writeh(76);
Writed(Id);
SendToServerEx(name);
end;

procedure Ench(ID:integer);
begin
buf:=#$5F;
Writed(ID);
Writed(0);
SendToServerEx(name);
end;


Три шага заточки: юзнуть точку, выбрать щит и заточить.

Шаг 2.

Итак, вещь точится и теперь дальше нужно как-то отслеживать уровень её заточки чтобы знать когда остановиться.
А также кол-во заточек в инвентаре т.к. мой несчастный гном сразу 5к не мог взять , был дикий перевес и я периодически доставал их из WareHouse.
Это видно в пакете Itemlist или в пакете InventaryUpdate - пишем их процедуры которые будут вызываться всякий раз как приходит их пакет.


procedure Itemlist;
begin
j:=0;
Itemlist:=readh(4);
list1:=6;
for i:=1 to Itemlist do
begin
reading:=false;
if (Readd(list1+4)=ItemforEnchID) then
begin
Items[1,j]:=Readd(list1);//OID
Items[2,j]:=Readh(list1+26);//Enchlvl
inc(j);
reading:=true;
end;
if (Readd(list1+4)=Scroll) then
begin
ScrollID:=Readd(list1);
ScrollCount:=Readd(list1+8);
reading:=true;
end;
if reading then
begin
inc(list1,64);
end
else
begin
inc(list1,68);
end;
end;
end;



procedure InventaryUpdate;
begin
j:=0;
Itemlist2:=Readh(2);
list2:=6;
for v:=1 to Itemlist2 do
begin
recording2:=false;
for j:=0 to 96 do
begin
list2:=6+(v-1)*70;
if (Items[1,j]=Readd(list2)) then
begin
case Readh(list2-6) of
1://Add
begin

end;
2://Mode
begin
Items[2,j]:=Readh(list2+26);
end;
3://Dell
begin
Items[1,j]:=0;
Items[2,j]:=0;
end;
end;
recording2:=true;
end
else
begin

end;
end;
if (Readd(list2-4)=ScrollID) then
begin
case Readh(list2-6) of
1://Add
begin

end;
2://Mode
begin
ScrollCount:=readd(list2+8);
end;
3://Dell
begin
ScrollID:=0;
ScrollCount:=0;

end;
end;
recording2:=true;
end;
list2:=6+(v-1)*70;
end;
end;

kpa9pt
02.09.2012, 17:44
Шаг 3.

Дальше допустим у нас закончились щиты или заточки, тогда надо писать процедуры на покупку щитов и доставание заточек и там же скидывание готовых на нужный уровень (например на 7) на склад.

Итак первое это будто мы уже около нпс люксора.


procedure Shield;
begin
buf:=#$1F;
Writed(NPC2id);
Writed(MyX);
Writed(MyY);
Writed(MyZ);
Writec(0);
SendToServerEx(name);

buf:=#$1F;
Writed(NPC2id);
Writed(MyX);
Writed(MyY);
Writed(MyZ);
Writec(0);
SendToServerEx(name);
end;


И второе это то когда мы у WareHouse Keeper или как его там.


procedure WH;
begin
buf:=#$1F;
Writed(NPCid);
Writed(MyX);
Writed(MyY);
Writed(MyZ);
Writec(0);
SendToServerEx(name);

buf:=#$1F;
Writed(NPCid);
Writed(MyX);
Writed(MyY);
Writed(MyZ);
Writec(0);
SendToServerEx(name);

firstnpc:=true;
end;


Ну это всеголиш начало диалогов с этими NPC. Сам процес покупки щитов или складывания их на клад происходит когда приходит пакет "HTML от нпс".

Вот его обработка:


procedure HTML;
begin
If (Readd(2)=NPCid) and firstnpc then
begin
buf:=#$22;
Writes('pochi001a.htm');
SendToServerEx(name);
firstnpc:=false;
end;
If (Readd(2)=NPCid) and npcscroll then
begin
buf:=#$22;
Writes('pochi001a.htm');
SendToServerEx(name);
npcscroll:=false;
end;
if (Readd(2)=NPCid) and (ReadS(6)='<html><body>Warehouse Keeper Pochi:<br><center><a action="bypass -h deposit">Deposit an item. (Private Warehouse)</a><br><a action="bypass -h withdraw">Withdraw an item. (Private Warehouse)</a><br><br><a action="link pochi001.htm">Return</a></center><br><br>Смотритель Склада Почи:<br><center><a action="bypass -h deposit">Сдать предмет на хранение. (Личный Склад)</a><br><a action="bypass -h withdraw">Забрать предмет. (Личный Склад)</a><br><br><a action="link pochi001.htm">Вернуться</a></center></body></html>') then
begin
if scrollcount<>0 then
begin
buf:=#$23;
WriteS('deposit');
SendToServerEx(name);
end
else
begin
buf:=#$23;
WriteS('withdraw');
SendToServerEx(name);
end;
end;
If (Readd(2)=NPC2id) then
begin
for n:=1 to 40 do
begin
buf:=#$B0;
Writed(2);
Writed(13);
Writeq(1);
writeh(0);
Writed(0);
Writed(0);
Writeh(65534);
writeh(0);
writeh(0);
writeh(0);
writeh(0);
writeh(0);
writeh(0);
writeh(0);
sendToServerEx(name);
end;
fromwh:=false;
buf:=#$14;
sendtoserverex(name);
end;
pck:='';
buf:=#$14;
SendToServerEx(name);
end;


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

Вот две процедуры обработки, где скидываются вещи и берутся:


procedure put;
begin
j:=0;
Itemlist3:=readh(12);
list3:=14;
MaxGoodItems:=0;
for o:=1 to Itemlist3 do
begin
if (lvlENCHANT=Readd(list3+30)) then
begin
GoodItems[j]:=Readd(list3+68);
inc(j);
inc(MaxgoodItems);
end;
list3:=14+o*72
end;

TimerToGO.enabled:=true;
pck:='';
buf:=#$14;
sendtoserverex(name);
end;

procedure output;
begin
Itemlist4:=Readh(12);
List4:=14;
for l:=1 to Itemlist4 do
begin
if (Scroll=Readd(list4+4)) then
begin
ScrollOID:=Readd(list4+68);
//exit;
end;
inc(list4,72);
end;

TimerToGO2.enabled:=true;
pck:='';
buf:=#$14;
sendtoserverex(name);
end;


Опять таки, тут не всё, остальное в двух таймерах интервалов 5 сек:


procedure OnTimerToGO(Sender:Tobject);
begin
WHput;
TimerToGo.enabled:=false;
buf:=#$14;
sendtoserverex(name);
end;

procedure OnTimerToGO2(Sender:Tobject);
begin
WHoutput;
TimerToGo2.enabled:=false;
buf:=#$14;
sendtoserverex(name);
end;


Ну и наконец:


procedure WHput;
begin
if GoodItems[0]<>0 then
begin
buf:=#$3B;
Writed(MaxGoodItems);
for b:=0 to (MaxGoodItems-1) do
begin
Writed(GoodItems);
Writed(1);
Writed(0);
end;
SendToserverEx(name);
end;
buf:=#$56;
Writed(33);
Writed(0);
Writec(0);
SendToserverEx(name);

gofromWH;
fromwh:=true;
end;

procedure WHoutput;
begin
if Scrollcount=0 then
begin
buf:=#$3C;
Writed(1);
Writed(ScrollOID);
Writed(400);
Writed(0);
SendToServerEx(name);
end;

gofromwh;

end;


[B]Шаг 4.

Напишем процедуры перемещения от склада к нпс люксора и наоборот.

З.Ы.: Написаны они ужасно))


procedure goWH;
begin
buf:=#$14;
SendToServerEx(name);
if (Loc1x-70<MyX) and (MyX<Loc1x+70) and (Loc1y-70<Myy) and (Myy<Loc1y+70) and (Loc1z-70<Myz) and (Myz<Loc1z+70) then
begin
MoveBackwardToLocation(Loc2x,loc2y,loc2z);
end;
if (Loc2x-70<MyX) and (MyX<Loc2x+70) and (Loc2y-70<Myy) and (Myy<Loc2y+70) and (Loc2z-70<Myz) and (Myz<Loc2z+70) then
begin
MoveBackwardToLocation(loc3x,loc3y,loc3z);
end;
if (Loc3x-70<MyX) and (MyX<Loc3x+70) and (Loc3y-70<Myy) and (Myy<Loc3y+70) and (Loc3z-70<Myz) and (Myz<Loc3z+70) then
begin
MoveBackwardToLocation(loc4x,loc4y,loc4z);
end;
if (Loc4x-70<MyX) and (MyX<Loc4x+70) and (Loc4y-70<Myy) and (Myy<Loc4y+70) and (Loc4z-70<Myz) and (Myz<Loc4z+70) then
begin
WH;
end;

end;

procedure gofromWH;
begin
buf:=#$14;
SendToServerEx(name);
if (Loc4x-70<MyX) and (MyX<Loc4x+70) and (Loc4y-70<Myy) and (Myy<Loc4y+70) and (Loc4z-70<Myz) and (Myz<Loc4z+70) then
begin
MoveBackwardToLocation(loc3x,loc3y,loc3z);
end;
if (Loc3x-70<MyX) and (MyX<Loc3x+70) and (Loc3y-70<Myy) and (Myy<Loc3y+70) and (Loc3z-70<Myz) and (Myz<Loc3z+70) then
begin
MoveBackwardToLocation(loc2x,loc2y,loc2z);
end;
if (Loc2x-70<MyX) and (MyX<Loc2x+70) and (Loc2y-70<Myy) and (Myy<Loc2y+70) and (Loc2z-70<Myz) and (Myz<Loc2z+70) then
begin
MoveBackwardToLocation(loc1x,loc1y,loc1z);
end;
if (Loc1x-70<MyX) and (MyX<Loc1x+70) and (Loc1y-70<Myy) and (Myy<Loc1y+70) and (Loc1z-70<Myz) and (Myz<Loc1z+70) then
begin
Shield;
end;

end;

procedure MoveBackwardToLocation(x:integer;y:integer;z:integ er);
begin
buf:=#$0F;
WriteD(x);
WriteD(y);
WriteD(z);
Writed(MyX);
Writed(MyY);
Writed(MyZ);
Writed(1);
SendToServerEx(name);
end;

kpa9pt
02.09.2012, 17:44
Шаг 5.

Ну и наконец процедура для того чтобы это дело всё точилось и он соображал когда надо бежать за точками или щитами


procedure OnTimerEnch(Sender:Tobject);
begin
for jj:=0 to (lvlENCHANT-1) do
begin
for ii:=0 to 96 do
begin
if (Items[2,ii]=jj) and (Items[1,ii]<>0) and (Scrollid<>0) and (ScrollCount<>0) then
begin
UseItem(ScrollID);
Enchant(Items[1,ii]);
Ench(Items[1,ii]);
exit;
end;
end;
end;
if (Scrollcount=0) then
begin
wantscroll;
end;
if (jj=(lvlENCHANT-1)) and (ii=96) and not fromwh then
begin
goWH;
end;
if (jj=(lvlENCHANT-1)) and (ii=96) and fromwh then
begin
gofromWH;
end;
end;


P.S.: Скрипт запускается по OldSchool соц действиями, написал вроде бы всё что надо было. Кто жаждет разобраться пишите вопросы сюда.
P.S.: Скрипт писался на rpg-club на хрониках GF или HF уже не помню.