Просмотр полной версии : пишем свой нубский скрипт для автоточки
сервер в дауне... и лежать будет незнамо сколько. решил я создать тему-конкурс о создании нубского скрипта для автоточки для любого сервера, где работает 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 для заточки.
кусочек кода, которым можно отправить что-то на сервер
  //Пакет RequestItemList
  buf:=hstr('0F');
  SendToServerEx(Name);
нечестно! конкурс для новичков, а не для корифеев программирования :)
задание второе:
привести кусочек кода для оператора если - if
if (STAKAN=0) the // ежли стакан пуст
begin // налить
end
else \\ стакан полон
begin
 .. \\выпить и закусить=)
end;
нет новичков... никому не интересно свой собственный скрипт наваять... все приходят за готовыми :(
ооо! предлагаю идею! при нажатии на кнопку "скачать скрипт" - вылазила программа с дибровым-галкиным - кто хочет стать миллионером с вопросами и вариантами ответов. если пользователь ответит на 3 из 4 - то скачка ему разрешается :)
завтра придется самому ответить :) ну четвертое задание будет простое.
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; код неверен. если стакан налит но закуски нет - все равно нальет в стакан.
if (STAKAN=0) or (ZAKUSKA=0) then begin // если стакан пуст или нет закуски, то начать следующие операции
   STAKAN:=1;            // обновить
   ZAKUSKA:=1;          // доложить огурцов в тарелку
end;
пофиксил :cool:
с таймером както так
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;
kolr, комментов в коде нет. не айс :) у Breadfan лучше :) понятнее.
в твоем случае добавь, что у тебя включаются таймеры один за другим.
срезюмирую ответ чуть чуть попозже, тут l2ph и клиента нет :( 
задание четвертое:
нужны пакеты inventory update с пометкой что было куплено (на 2 предмета +шмотка -адена) 
action - наведение таргета на любого нпс. 
пакет useitem на использование любого предмета
которые мы потом разберем на составляющие :)
Breadfan
28.12.2011, 06:31
поправил
Breadfan, разве если во фрии не освободить таймер от памяти оно не кританет при след запуске?
Breadfan
28.12.2011, 21:54
нет, как бы то странно не было
goodvin1709
05.01.2012, 02:37
У меня критовало
видимо не в таймере дело, а в переменных, которые не освободились при отключении скрипта.
и какая версия л2пх?
goodvin1709
11.01.2012, 17:55
Если скрипт для заточки.
У меня было 3 таймера(точил в 3-4 окна) логало жуть.
поставил 2 таймера(сжал закупку точек и пушек в 1 процедуру и 1 таймер)
тоже логает но не так уже.
Кто может помочь напишыте в ПМ.(скрипт заточки с4 сервер).
тупит именно база инвентаря.
Добавлено через 1 час 26 минут
^^^^^^Все уже сам все переписал пашет на ура.
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 исправь и четко будет
goodvin1709, ваще-т никакого выхода из цикла там нет
Добавлено через 1 минуту
фастскрипт сам по себе медленный, циклы там ваще нежелательны
ну если делать бикубическую интерполяцию пикселей на изображении и сортировки массивов [0..100500] то да. У меня весь цикл фс выполняетса за 0мс и ниче не грузит. Точнее не позволяет узнать gettickcount.
goodvin1709
12.01.2012, 13:14
Почему когда я пробывал работать с пакетами там всегда либо крит либо крит.что за даже демку пробывал всунуть сервно крит.раз 100 компилил 
99% крипт или не пахало.
SeregaZ, 
поздно пить боржоми когда не работают почкки
ЭТО Я ПРО СЕБЯ !!!!!!!!!!!!!!!!!
таймер не
нужен наверно 
надо посылать паккет от клиента после того как придет пакет от серва на потверждение твоего действия
 вродетак 
менее палево
наоборот. в этом случае будет палевней - так как скорость намного увеличится. будет куда меньше 1 секунды. человек так не сможет :) по крайней мере ночь точить :) сам понаблюдай - открывай диалоги и вальяжно по менюшкам жми - как раз будет примерно 1 секунда, чуть больше, чуть меньше.
а если сразу по приходу пакета открытия меню открывать следующий пункт - скорость будет куда выше, чем 1 секунда.
в идеале конечно сделать сначала проверку на приход открытия меню, потом рандомную паузу от 1 до 2 секунд. в этом случае мы обезопасим клиент от вылетов из-за лагов.
с другой стороны если пофиг на палево - то твой подход куда лучше в плане достижения нужной степени заточки. так как скорость будет выше, сам скрипт надежнее. и если мой вариант заточит 1-2 лука +20 за ночь, то твой думаю сможет 3-4 успеть точнуть. конечно еще зависит от шансов на конкретном сервере :)
в идеале конечно сделать сначала проверку на приход открытия меню, потом рандомную паузу от 1 до 2 секунд. в этом случае мы обезопасим клиент от вылетов из-за лагов.
вот это я имел ввиду .
А я просто похвастаюсь!!!)))
Написал себе скрипт на х10 сервере, точил щиты Б грейда, за ночь сточило 5к точек (покупая щиты в люксоре и скидывая на +7 в вх).
Вышло гдето порядку 60+ щитов на +7.
А в итоге щит на +10, единственный на сервере).
Могу выложить конекретные обработчики событий при точке, если кому то нужно
На х10 5к точек?оО
Да, там есть задрот играющий с открытия (5 лет) у него 1к чаров с лишним с кубиками и он тратит пол дня на открытие кубиков) и точек у него всяких немеренно, ну и я скупил все б арморки что у него были)
kpa9pt, 
Выложи . Пригодится .
kpa9pt, 
Выложи . Пригодится .
Тема называется нубский скрипт, если кто-то заинтересован в частях обработки для заточек или движения к нпс или покупок чего либо через мульти сел, могу по выкладывать, а вот рабочий скрипт не вижу я тут тех кому он нужен.
Вот забью окончательно на ла2, выложу сюда тьму скриптов полезных, для олимпа, пвп и т д:)...некоторые просто невероятно полезные...
kpa9pt, один хер, те кому они были бы полезны, не смогут разобраться как их юзать, а тот кто сможет - сам напишет :D
kpa9pt, один хер, те кому они были бы полезны, не смогут разобраться как их юзать, а тот кто сможет - сам напишет :D
Лан, завтра мб напишу статью сюда про скрипт заточки выложу куски и всё по шагам разберу, всёравно там мало кому такой нужен будет скрипт, мало кто точит б щиты покупая в люксоре их и доставая из вх точки в видде 5к штук)
МОЖНО достать из ВОЗДУХА 
хи  се sXAXAs
Итак как обещал скрипт пошагово на авто заточку Щитов Б грейда из люксора.
З.Ы.: Писал довольно давно и не выйдет очень красиво в (духе здесь и сейчас) написать описание.
З.Ы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;
Шаг 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;
Шаг 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 уже не помню.
vBulletin® v3.6.11, Copyright ©2000-2025, Jelsoft Enterprises Ltd. Перевод: zCarot