procedure Free; //Вызывается при выключении скрипта
begin
ItemBase:=nil;
timer.Free;
end;
procedure SendMsg(msg:string);
begin
buf:=#$4A;
WriteD(0);
WriteD(10);
WriteS('');
WriteS(msg);
SendToClient;
end;
procedure CreateItemBase; //Создает базу ObjectID и ItemID, опять же не проверяет пакет на правильность для экономия ресурсов
var
i,j: integer;
begin
j:=4; //смещение для ListCount
ListCount:=ReadH(j); //количество итемов
//ItemList:w(window)w(ListCount)w(itemType1:0-wpn/rng/ear/nckl,1-arm/shld,4-itm/qitm/adn)h(ObjectId)i(ItemID)d(count)w(itemType2:0-wpn 1-shld/arm 2-rng/ear/nckl 3-qitm 4-adn 5-itm)w(CustType1)w(isEquipped)h(BodyPart)w(EnchantL evel)w(CustType2)
SetLength(ItemBase,ListCount*2); //размер массива должен быть в 2 раза больше, чем итемов
j:=8; //смещение для ObjectID
//Пробегаем по Инвентарю и сохраняем пары ObjectID - ItemID
for i:=0 to ListCount-1 do begin
ItemBase[i*2]:=ReadD(j); //ObjectID
ItemBase[i*2+1]:=ReadD(j); //ItemID
// SendMsg('ObjectID='+IntToStr(ItemBase[i*2])+' ItemID='+IntToStr(ItemBase[i*2+1]));
j:=j+20; //21?
end;
Dump;
end;
procedure UpdateItemBase; //Создает базу ObjectID и ItemID, опять же не проверяет пакет на правильность для экономия ресурсов
var
i, ii, tmp, j, Count, ObjID, ItID, UpdType: integer;
begin
Count:=ReadH(2); //количество итемов
//Пробегаем по Инвентарю и сохраняем пары ObjectID - ItemID
j:=4; //смещение для действия с предметом 1-добавлен 2-изменен 3-удален
// SendMsg('UpdateItemBase!');
for i:=0 to Count-1 do begin
UpdType:=ReadH(j);
j:=j+2;
ObjID:=ReadD(j);
ItID:=ReadD(j);
SendMsg('UpdType='+IntToStr(UpdType)+' ObjectID='+IntToStr(ObjID)+' ItemID='+IntToStr(ItID));
if (UpdType=3) then begin
for ii:=0 to ListCount-1 do begin
// SendMsg('Проход по ItemBase!');
//находим подходящий предмет
if (ItemBase[ii*2]=ObjID) then begin
ItemBase[ii*2]:=0;
ItemBase[ii*2+1]:=0;
SendMsg('Стираем данные! ObjectID='+IntToStr(ObjID)+' ItemID='+IntToStr(ItID));
end;
end;
end
else begin
for ii:=0 to ListCount-1 do begin
if (UpdType=1) and (ItemBase[ii*2]=0) then begin
ItemBase[ii*2]:=ObjID;
ItemBase[ii*2+1]:=ItID;
SendMsg('Вносим данные! ObjectID='+IntToStr(ObjID)+' ItemID='+IntToStr(ItID));
add:=false;
Dump;
exit;
end else if (UpdType=1) then add:=true;
end;
end;
// SendMsg('Проход по UpdateItem!');
j:=j+18; //следующее смещение для действия с предметом 1-добавлен 2-изменен 3-удален
end;
if add=true then begin
ListCount:=ListCount+1; //количество итемов
SetLength(ItemBase,ListCount*2); //размер массива должен быть в 2 раза больше, чем итемов
ItemBase[(ListCount-1)*2]:=ObjID;
ItemBase[(ListCount-1)*2+1]:=ItID;
SendMsg('Добавляем данные! ObjectID='+IntToStr(ObjID)+' ItemID='+IntToStr(ItID));
add:=false;
end;
Dump;
end;
procedure Dump; //показать базу
var
i,j: integer;
begin
for i:=0 to ListCount-1 do
SendMsg('i='+IntToStr(i)+': ObjID='+IntToStr(ItemBase[i*2])+' - ItemID='+IntToStr(ItemBase[i*2+1]));
end;
function GetObjID(ItemID:integer): integer; //Выдает ObjectID по его ItemID, если ItemID не найден в базе, выдает -1
var
i: integer;
begin
for i:=0 to ListCount-1 do
//находим первый подходящий предмет
if (ItemBase[i*2+1]=ItemID) then begin
Result:=ItemBase[i*2];
Exit;
end;
Result:=-1;
end;
procedure UseItem(ObjectID: integer);
begin
buf:=#$14;
WriteD(ObjectID);
WriteD(0);
SendToServer;
end;
procedure RequesEnchantItem(ObjectID: integer);
begin
buf:=#$58;
WriteD(ObjectID);
SendToServer;
end;
procedure TryEnchantWeapon;
begin
if GetObjID(Scroll)=-1 then begin
SendMsg('Нет такого скролла! Прервано!');
timer.enabled:=false;
exit;
end;
UseItem(GetObjID(Scroll));
SendMsg('Scroll='+IntToStr(GetObjID(Scroll)));
if GetObjID(Weapon)=-1 then begin
SendMsg('Нет такого оружия! Прервано!');
timer.enabled:=false;
exit;
end;
RequesEnchantItem(GetObjID(Weapon));
SendMsg('Заточили предмет! Weapon='+IntToStr(GetObjID(Weapon)));
end;
procedure OnTimerHP(Sender: TObject);
begin
TryEnchantWeapon;
end;
//************************************************** ****************************
// вызывается при приходе каждого пакета, если скрипт включен
//************************************************** ****************************
begin
//не обрабатываем пустые пакеты
if pck='' then exit;
//************************************************** **************************
//социальное действие yes для начало точки
if FromClient and (pck=HStr('1B 06 00 00 00')) then begin
SendMsg('Начинаем точить всё оружие!!!');
timer.enabled:=true;
end;
//социальное действие no для начало точки
if FromClient and (pck=HStr('1B 05 00 00 00')) then begin
SendMsg('Окончили точить всё оружие!!!');
timer.enabled:=false;
end;
//ItemList
if FromServer and (pck[1]=#$1B) then CreateItemBase; //создание базы предметов
if (length(ItemBase)=0) then exit; //если нет базы итемов, скрипт дальше не пустит
//если удалились предметы, стираем в базе предметов пары ObjectID - ItemID
if FromServer and (pck[1]=#$27) then UpdateItemBase; //Обновление базы, если принят пакет на удаление предмета
//************************************************** ***************
//Команды отладки
//************************************************** ***************
//пакет Say2
if FromClient and (pck[1]=#$38) then begin
Cmd:=ReadS(2);
case Cmd of
'1':
begin
pck:='';
Dump;
end;
'2':
begin
pck:='';
TryEnchantWeapon;
Dump;
end;
end;
exit;
end;
//************************************************** ***************
end.
//Автоматизация заточки предметов до необходимого уровня by NLObP
{Затачиваем поочереди все предметы с Weapon ID пока не переломаем или не заточим
Работа проверена на L2C4 Protocol 660 LocalServer "L2J FORTRESS"
Необходимо затариться оружием и заточками
Открываем инвентарь для инициализации скрипта
Социальное действие YES начать
Социальное действие NO остановиться
Скрипт распространяется как есть, и я не несу ответственности за то,
что ВЫ натворили у себя, его используя.}
const
Name='NLObP';
Scroll=957; // 957 - ItemID Crystall Scroll Enchant Weapon (Grade D)
Weapon=129; // 129 - ItemID Sword of Revolution
MaxEnchLvl=20; //max уровень заточки
max=250; //max количество предметов в базе
var
// WpnObjID: array[1..maxwpn,1..maxwpn] of integer; //Weapon ObjID
WpnBase: array[1..2,1..max] of integer; //Weapon ObjID,lvl
ScrlBase: array[1..max] of integer; //Scroll ObjID
add: boolean; //прошла заточка?
timer: TTimer;
CurEnchLvl, ColvoWpn, ColvoScrl, CurWpn, CurScrl: integer;
procedure Init; //Вызывается при включении скрипта
var
i:integer;
begin
//Enchant:=false;
CurEnchLvl:=0;
timer:=TTimer.Create(nil);
timer.OnTimer:=@OnTimerHP;
timer.enabled:=false;
timer.interval:=50; //время задержки
add:=false;
for i:=1 to max do begin
//очищаем масив
WpnBase[1,i]:=0;
WpnBase[2,i]:=0;
end;
//************************************************** ****************************
procedure CreateItemBase; //пакет 1B, Создает базу ObjectID по ItemID
var
i, ss, ww, j, ObjID, ItemID, lvl, ListCount: integer;
begin
ss:=1; //индекс в массиве скроллов
ww:=1; //индекс в массиве предметов
j:=4; //смещение для ListCount
ListCount:=ReadH(j); //количество итемов не должно превышать max!
if ListCount>max then ListCount:=max;
j:=8; //смещение для ObjectID
//Пробегаем по Инвентарю и сохраняем ObjectID соответствующие необходимым ItemID
for i:=1 to ListCount do begin
ObjID:=ReadD(j); //ObjectID
ItemID:=ReadD(j); //ItemID
j:=j+14;
Lvl:=ReadD(j); //Level
case ItemID of
scroll: begin
ScrlBase[ss]:=ObjID;
ss:=ss+1;
//Say('ColvoScrl='+IntToStr(ss));
end;
weapon: begin
WpnBase[1,ww]:=ObjID;
WpnBase[2,ww]:=lvl;
ww:=ww+1;
//Say('ColvoWpn='+IntToStr(ww));
end;
end;
j:=j+2;
end;
ColvoWpn:=ww-1;
ColvoScrl:=ss-1;
Say('>ColvoWpn='+IntToStr(ColvoWpn)+' ColvoScrl='+IntToStr(ColvoScrl)+' CurEnchLvl='+IntToStr(CurEnchLvl));
end;
//************************************************** ****************************
procedure UpdateItemBase; //пакет 27, Создает базу ObjectID по ItemID
var
i, ii, j, ss, ww, ObjID, ItemID, Lvl, ListCount, UpdType: integer;
begin
ListCount:=ReadH(2); //количество итемов
//Пробегаем по Инвентарю и сохраняем пары ObjectID - Lvl
j:=4; //смещение для действия с предметом 1-добавлен 2-изменен 3-удален
// Say('Апдейт базы!');
for i:=1 to ListCount do begin
UpdType:=ReadH(j);
j:=j+2;
ObjID:=ReadD(j);
ItemID:=ReadD(j);
j:=j+14;
Lvl:=ReadH(j);
// Say('Предмет! ObjectID='+IntToStr(ObjID)+' ItemID='+IntToStr(ItemID));
case UpdType of
1:case ItemID of
weapon: begin
ColvoWpn:=ColvoWpn+1;
//Say('Добавили предмет! ObjectID='+IntToStr(ObjID)+' ItemID='+IntToStr(weapon));
for ii:=1 to max do
if WpnBase[1,ii]=0 then begin WpnBase[1,ii]:=ObjID; WpnBase[2,ii]:=lvl; end;
end;
scroll: begin
ss:=ss+1;
//Say('Добавили скролл! ObjectID='+IntToStr(ObjID)+' ItemID='+IntToStr(scroll));
for ii:=1 to max do
if ScrlBase[ii]=0 then ScrlBase[ii]:=ObjID;
end;
end;
2:case ItemID of
weapon:
for ii:=1 to max do
if WpnBase[1,ii]=ObjID then WpnBase[2,ii]:=lvl;
scroll:
//Say('Внимание! Изменения в скролле!?');
end;
//удален
3:case ItemID of
weapon: begin
ColvoWpn:=ColvoWpn-1;
for ii:=1 to max do
if WpnBase[1,ii]=ObjID then begin WpnBase[1,ii]:=0; WpnBase[2,ii]:=0; end;
//Say('Удаляем предмет! ObjectID='+IntToStr(ObjID)+' ItemID='+IntToStr(weapon));
end;
scroll: begin
ColvoScrl:=ColvoScrl-1;
for ii:=1 to max do
if ScrlBase[ii]=ObjID then ScrlBase[ii]:=0;
//Say('Удаляем скролл! ObjectID='+IntToStr(ObjID)+' ItemID='+IntToStr(scroll));
end;
end;
end;
j:=j+2; //следующее смещение для действия с предметом 1-добавлен 2-изменен 3-удален
end;
Say('>>ColvoWpn='+IntToStr(ColvoWpn)+' ColvoScrl='+IntToStr(ColvoScrl)+' CurEnchLvl='+IntToStr(CurEnchLvl));
end;
//************************************************** ****************************
function GetNextWeapon: integer; //Выдает ObjID предмета, если не найден в базе, выдает -1,
//достигли макс уровня заточки -2, подбираем мин текущий уровень заточки -3
var
i: integer;
begin
Result:=-1;
if CurEnchLvl>=MaxEnchLvl then begin
Result:=-2;
exit;
end;
for i:=1 to max do begin
//находим первый подходящий предмет
if (WpnBase[1,i]<>0) and (WpnBase[2,i]=CurEnchLvl) then begin
Result:=WpnBase[1,i];
exit;
end;
end;
CurEnchLvl:=CurEnchLvl+1;
Result:=-3;
end;
//************************************************** ****************************
function GetNextScroll: integer; //Выдает ObjID скролла, если не найден в базе, выдает -1
var
i: integer;
begin
Result:=-1;
for i:=1 to max do begin
//находим первый подходящий предмет
if (ScrlBase[i]<>0) then begin
Result:=ScrlBase[i];
exit;
end;
end;
end;
//************************************************** ****************************
procedure RequesEnchantItem(ObjectID: integer);
begin
buf:=#$58;
WriteD(ObjectID);
SendToServerEx(Name);
end;
//************************************************** ****************************
procedure OnTimerHP(Sender: TObject);
var
wpn, scrl:integer;
begin
if ColvoScrl=0 then begin
Say('Кончились скроллы! Прервано!');
timer.enabled:=false;
exit;
end;
if ColvoWpn=1 then begin
Say('Остался последний предмет! Прервано!');
timer.enabled:=false;
exit;
end;
Scrl:=GetNextScroll;
if scrl=-1 then begin
Say('Нет такой заточки! Прервано!');
timer.enabled:=false;
exit;
end;
Wpn:=GetNextWeapon;
case wpn of
-1: begin
Say('Нет такого предмета! Прервано!');
timer.enabled:=false;
exit;
end;
-2: begin
Say('Достигли максимальный уровень заточки! Прервано!');
timer.enabled:=false;
exit;
end;
-3: begin
//Say('Подбираем текущий уровень заточки!');
timer.enabled:=true;
exit;
end;
end;
//************************************************
UseItem(Scrl);
RequesEnchantItem(Wpn);
//************************************************
Say('Заточили предмет! Weapon='+IntToStr(Wpn));
end;
//************************************************** ****************************
// вызывается при приходе каждого пакета, если скрипт включен
//************************************************** ****************************
begin
//************************************************** **************************
//не обрабатываем пустые пакеты
if pck='' then exit;
//************************************************** **************************
//социальное действие yes для начало точки
if FromClient and (ConnectName=Name) and (pck=HStr('1B 06 00 00 00')) then begin
CurEnchLvl:=0;
Say('Команда Старт!!!');
timer.enabled:=true;
end;
//************************************************** **************************
//социальное действие no для начало точки
if FromClient and (ConnectName=Name) and (pck=HStr('1B 05 00 00 00')) then begin
Say('Команда Стоп!!!');
timer.enabled:=false;
end;
//************************************************** **************************
//ItemList
if FromServer and (ConnectName=Name) and (pck[1]=#$1B) then CreateItemBase; //создание базы предметов
// if (ColvoWpn=0) or (ColvoScrl=0) then exit; //если нет базы итемов, скрипт дальше не пустит
//************************************************** **************************
//если удалились предметы, стираем в базе предметов пары ObjectID - ItemID
if FromServer and (ConnectName=Name) and (pck[1]=#$27) then UpdateItemBase; //Обновление базы, если принят пакет на удаление предмета
end.
Неизвестные вещи пишет без описания.
Добавлять вещи в itemsid.ini можно непосредственно во время игры, если скрипт включить, то описание добавленной вещи появиться в списке.
Если одежду (оружие) одеть/снять, то скрипт напишет в окне сообщений itemid этой вещи.
Для С4, надо внести изменения в procedure CreateItemBase;
...
было --> if interlude then inc(j,12) else inc(j,8);
надо --> if interlude then inc(j,12) else inc(j,4); //для С4 проверено, спасибо Mulder
Последний раз редактировалось NLObP, 05.07.2008 в 01:32.
Для С4, надо внести изменения в procedure CreateItemBase;
...
было --> if interlude then inc(j,12) else inc(j,8);
надо --> if interlude then inc(j,12) else inc(j,4); //для С4 проверено, спасибо Mulder
Изменил все как указано выше, все точит отлично до +4, после этого пишет заточка прервана, а все из-за того что оно видит в моем инвентаре неправильное количество заточек и оружия. Хотя в инвентаре 60 шт. заточек и 40 шт. оружия, программа видит только 4 шт. заточек и 3 шт. оружия, хотелось бы узнать с чем может быть это связано и как исправить, что бы программа видела правильное количество предметов в инвентаре.
PS: Заранее спасибо
Уважаемый NLObP, а как сделать чтоб перс сам докупал заточки?
Сделать что бы покупал можно, но это для каждого сервера будет немного по своему, поэтому делать не буду.
Посмотреть, как это сделать самому, можно в рыбалке и в теме алгоритмов.
Немного подскажу. Надо знать ID продавцов. Знать как продается - обычный магазин/мультиселл. Знать bypass из html-менюшки, который посылать для покупки. Нужно запоминать ListID в ответе продавца.
покупка состоит из следующих шагов:
1. таргет на продавце, пауза, снова таргет (c04=Action, c04=Action)
2. приходит s0F=NpcHtmlMessage:d(MessageID)s(HTML)d(d) - берем из него bypass требуемого пункта меню
3. шлем выбранный пункт из меню c21=RequestBypassToServer:s(Cmd)
4. приходит s11=BuyList:d(Money)h(ListID)w(ListCount)w(ItemTyp e1)h(ObjectID)i(ItemID)d(maxcnt)w(ItemType2)w(h)d( ItemBodyPart)... - берем ListID
5. FindItem(ID) найдем OID, Count нужной вещи по ID - это отдельная процедура поиска в инвентаре и здесь не требуется!
6. шлем c1F=RequestBuyItem:h(ListID)d(BuyCount)i(ItemID)d( Count)i(ItemID)d(Count)
На некоторых серверах не обязятельно подходить к продавцу, на других обязательно. Тоже самое с ListID - на некоторых можно 0 ставить.
Последний раз редактировалось NLObP, 03.08.2008 в 00:51.