Скрипт начал писать для того, чтобы поднатаскать себя в понимании l2phx. Может кому и пригодится....
Бот не умеет мочить моба и подбирать с него дроп, НО он автоматом находит в инвентаре бутылки с хилкой и хиляется ими, а также юзает соски под грейд удочки, если находит.
Для показа меню нада написать 'f' в пати чат, без кавычек.
delphi Код:
//Автоматизация ловли рыбы by VerWolF
//Скрипт ловит рыбу и хиляется когда вылавливает монстра.
//Работа проверена на L2C6 Protocol 750 la2.theabyss.ru x3
//Необходимо затариться удочкой и крючками, выучить соответствующие скиллы,
//потеплей одется :D желательно в хэви, ловить советую какким-н толстозадым гномом.
//Бот сам находит соски в инвентаре, которые подходят под грейд удочки и автоматически их использует.
//Бот сам находит Банки для хила в инвентаре и автоматически их использует, когда его атакует моб.
//Бот распознает 3 вида банок для хила: обычные, GHP и QHP и юзает их в соответствии с ситуацией.
//Рыба будет ловиться как с сосками, так и без них, без,
//соответственно, дольше...
//Если вас забанили, то автор ответственности не несет!
//Используйте скрипт на ваш страх и риск!
//Для работы нужно задать константе NAME чара, которым будете рыбачить.
const
fish='2F 20 05 00 00 00 00 00 00 00';
pump='2F 21 05 00 00 00 00 00 00 00';
reel='2F 22 05 00 00 00 00 00 00 00';
NAME='Popka';//Имя чара, который рыбачит.
HPBottleID=1061; //ID бутылок с хилкой
GHPBottleID=1539;
QHPBottleID=1540;
{необходимо уточнить ItemID для своего сервера!!!
1060=Lesser Healing Potion
1061=Healing Potion
1539=Greater Healing Potion
1540=Quick Healing Potion}
HealInterval=15000; //Интервал, через который будет питься бутылко. 15сек. На QHP не распространяется.
FishingIterval=100; //Задержка между закидованием удочки.
HTML='<html><body><center>'+
'<img src="L2UI_CH3.herotower_deco width=256 height=32>'+
'<img src="L2UI.SquareWhite" width=280 height=1>'+
'<img src="L2UI.SquareBlank" width=260 height=4><br>'+
'<font color="04fbfb">.::FiShInG v0.3 by VerWolF::.</font><br>'+
'<font color="04fbfb">.::[Написано на основе кода QaK и NLObP]::.</font><br>'+
'<button value="Start Fishing!" action="bypass -h StartFishing" width=100 height=15 back="sek.cbui94" fore="sek.cbui92">'+
'<button value="Stop Fishing" action="bypass -h StopFishing" width=100 height=15 back="sek.cbui94" fore="sek.cbui92">'+
'<img src="L2UI.SquareWhite" width=260 height=1>'+
'<img src="L2UI.SquareBlank" width=260 height=4><br>'+
'</center></body></html>';
//======================================================================================================================
var
FishCycleTimer : TTimer;
HealReuseTimer : TTimer;
Status : Boolean;
CharObjID : Integer;
SocialID : Integer;
bypass : String;
MaxHP : Integer;
CurrentHP : Integer;
FSoulshotID : Integer;
FSoulshotObjID : Integer;
ItemCount : Integer; //количество занятых слотов/количество вещей
Inventory: array[1..250,1..10]of integer; //массив инвентаря
//инвентарь
//1 - ItemType1
//2 - ObjectID
//3 - ItemID
//4 - ItemCount
//5 - ItemType2
//6 - CustType1
//7 - IsEquipped
//8 - BodyPart
//9 - EnchantLevel
//10 - CustType2
procedure Init; //Вызывается при включении скрипта
begin
MaxHP:=0;
CurrentHP:=0;
FSoulshotID:=0;
FSoulshotObjID:=0;
ItemCount:=0;
CharObjID:=0;
Status:=false;
FishCycleTimer:=TTimer.Create(nil);
FishCycleTimer.OnTimer:=@OnFishCycleTimer;
FishCycleTimer.enabled:=false;
FishCycleTimer.interval:=FishingIterval;
HealReuseTimer:=TTimer.Create(nil);
HealReuseTimer.OnTimer:=@OnHealReuseTimer;
HealReuseTimer.enabled:=false;
HealReuseTimer.interval:=HealInterval;
Say('Для вывода меню набрать в пати-чате букву f');
end;
procedure Free; //Вызывается при выключении скрипта
begin
FishCycleTimer.Free;
HealReuseTimer.Free;
end;
//процедура для отображения диалога управления ботом.
procedure ShowHTML( _html : string );
begin
buf:=#$00f;
WriteD(5);
WriteS(_HTML);
SendToClientEX(NAME);
end;
//посылаем сообщение, которое видно только в окне бота
//можно использовать для отладки
procedure Say(msg:string);
begin
buf:=hstr('4A 00 00 00 00');
WriteD(2);
WriteS(NAME);
WriteS(msg);
SendToClientEx(NAME);
end;
//процедура считывания параметров одного предмета
procedure ItemAction(var Counter:integer; CurrentSlot:integer);
//Counter - Позиция считываемая из пакета, модифицируется функциями ReadC,ReadD
//CurrentSlot - Индекс в массиве Inventory (от 1 до 250)
var
c1:integer;
begin
for c1:=1 to 10 do
begin //Если значение однобайтное
if (c1=1)or(c1=5)or(c1=6)or(c1=7)or(c1=9) then begin
Inventory[CurrentSlot,c1]:=ReadH(Counter);
end;
//Если значение четырехбайтное
if (c1=2)or(c1=3)or(c1=4)or(c1=8) then begin
Inventory[CurrentSlot,c1]:=ReadD(Counter);
end;
//Если значение последнее
if c1=10 then begin
Inventory[CurrentSlot,c1]:=ReadH(Counter);
Counter:=Counter+8;
end;
end;
end;
//Пакет от сервера 1В - создаем или модифицируем весь инвентарь
procedure CreateItemBase;
var
i,j: integer;
begin
ItemCount:=ReadH(4);//Считываем количество вещей в инвентаре
j:=6;
for i:=1 to ItemCount do ItemAction(j,i);
end;
//Пакет от сервера 27 - действия (доавить/изменить/удалить) над одним/несколькими предметами
procedure UpdateItemBase;
var
i,ij,ijk:integer; //простые счетчики для перебора значений
j:integer; //Текущая позиция, откуда считываем значения из пакета
count:integer; //Количество изменяемых предметов
Action: integer; //Действие над предметом
k:boolean; //Нашли ли мы удаляемый предмет?
begin
k:=false;
count:=ReadH(2);//Считываем количество изменяемых предметов
j:=4;
for i:=1 to count do begin
Action:=ReadH(j);//Считываем действие
case Action of
1:begin //ADD
Inc(ItemCount);//Увеличиваем количество занятых слотов
ItemAction(j,ItemCount); //Добавляем предмет
end;
2:begin //UPDATE
for ij:=1 to ItemCount do //Ищем изменяемый предмет по ObjectID
If Inventory[ij,2]=ReadD((j-1)*30+8) then begin //Если нашли
ItemAction(j,ij); //Изменяем данные о нем
exit; //Больше проверять не надо - выходим из цикла
end;
end;
3:begin //DELETE
for ij:=1 to ItemCount-1 do begin //Ищем удаляемый предмет
If Inventory[ijk,2]=ReadD((j-1)*30+8) then k:=true; //Если нашли,фиксируем это
If k then //если найден удаляемы объект
for ijk:=1 to 10 do //то сдвигаем элементы массива-инвентаря
Inventory[ij,ijk]:=Inventory[ij+1,ijk];
end;
Dec(ItemCount);//Уменьшаем количество занятых слотов
end;
end;
end;
end;
//Получить ObjectID предмета, зная его ItemID
function GetInfo(ItemID:integer):integer;
var
c1:integer;
begin Result:=-1;
for c1:=1 to ItemCount do
if (ItemID=Inventory[c1,3]) then begin
Result:=Inventory[c1,2];
exit;//Если нашли - выходим из цикла
end;
end;
//Проверяем, одет ли предмет по ItemID
function IsEquipped(ItemID:integer):integer;
var
c1:integer;
begin Result:=-1;
for c1:=1 to ItemCount do
if (ItemID=Inventory[c1,3]) and (Inventory[c1,7]=1) then begin
Result:=1;
exit;
end;
end;
//Использовать предмет с заданным ItemID
procedure UseItem(ItemID:integer);
var
c1:integer;
begin
for c1:=1 to ItemCount do
if (ItemID=Inventory[c1,3]) then begin
buf:=#$14;
WriteD(Inventory[c1,2]);
WriteD(0);
SendToServerEX(NAME);
exit; //Чтоб не использовать несколько предметов с одинаковым ItemID (например заточки)
end;
end;
//Используем рыбное соско.....
procedure UseSoulshot(ObjID:integer);
begin
buf:=#$14;
WriteD(ObjID);
WriteD(0);
SendToServerEX(NAME);
end;
//Процедура для отсылки пакета о начале или окончании рыбалки.
//Также определяет по одетой на чара удочке ID и ObjectID сосок,
//которые нада юзать и юзает их в дальнейшем автоматически.
{ Проверьте эти значения для своего сервера!!!
6529=Baby Duck Rod (NG) 6535=Fishing Shot: non-grade
6530=Albatross Rod (D) 6536=Fishing Shot: D-grade
6531=Pelican Rod (C) 6537=Fishing Shot: C-grade
6532=KingFisher Rod (B) 6538=Fishing Shot: B-grade
6533=Cygnus Pole (A) 6539=Fishing Shot: A-grade
6534=Triton Pole (S) 6540=Fishing Shot: S-grade
}
procedure Fishing;
var
i : Integer;
begin
if (FSoulshotID=0) and (FSoulshotObjID=0) then begin
for i:=6529 to 6534 do
begin
if IsEquipped(i)=1 then begin
FSoulshotID:=(i+6);
FSoulshotObjID:=GetInfo(FSoulshotID);
if (FSoulshotObjID<>-1) then begin
Say('Соски будут использоваться автоматически.');
end
else begin
FSoulshotID:=0;
FSoulshotObjID:=0;
end;
end;
end;
end;
buf:=HStr(fish);
SendToServerEX(NAME);
end;
//юзаем Pumping вместе с соской
procedure Pumping;
begin
if (FSoulshotObjID<>-1) then UseSoulshot(FSoulshotObjID);
buf:=HStr(pump);
SendToServerEX(NAME);
end;
//юзаем Reeling вместе с соской
procedure Reeling;
begin
if (FSoulshotObjID<>-1) then UseSoulshot(FSoulshotObjID);
buf:=HStr(reel);
SendToServerEX(NAME);
end;
//пьем банко как только пройдет 15 секунд
procedure OnHealReuseTimer(Sender: TObject);
begin
if (CurrentHP < MaxHP) and (CurrentHP > (MaxHP/2)) then begin
UseItem(HPBottleID);
HealReuseTimer.enabled:=false;
exit;
end;
if (CurrentHP < (MaxHP/2)) and (CurrentHP > ((MaxHP/100)*10)) then begin
if (GetInfo(GHPBottleID)<>-1) then begin
UseItem(GHPBottleID);
HealReuseTimer.enabled:=false;
exit;
end;
if (GetInfo(HPBottleID)<>-1) then begin
UseItem(HPBottleID);
HealReuseTimer.enabled:=false;
exit;
end;
end;
if (CurrentHP < ((MaxHP/100)*10)) then begin
if (GetInfo(QHPBottleID)<>-1) then UseItem(QHPBottleID);
if (GetInfo(GHPBottleID)<>-1) then begin
UseItem(GHPBottleID);
HealReuseTimer.enabled:=false;
exit;
end;
if (GetInfo(HPBottleID)<>-1) then begin
UseItem(HPBottleID);
HealReuseTimer.enabled:=false;
exit;
end;
end;
end;
//начинаем рыбачить как только щелкнет таймер
procedure OnFishCycleTimer(Sender: TObject);
begin
Fishing;
FishCycleTimer.enabled:=false;
end;
//******************************************************************************
// Тело скрипта.
//******************************************************************************
begin
//не обрабатываем пустые пакеты
if pck='' then exit;
//Если скрипт ничего не знает о содержимом инвентаря, то вынуждаем его узнать о нем.
if ItemCount=0 then begin
buf:=#$0F;
SendToServerEX(NAME);
end;
//****************************************************************************
//РАЗБОР ПАКЕТОВ ОТ СЕРВЕРА:
if FromServer then begin
//создаем или обновляем описание предметов в инветаре.
case pck[1] of
#$1B:begin
CreateItemBase;
end;
#$27:begin
UpdateItemBase;
end;
end;
//Получаем пакет UserInfo, вынимаем оттуда свой ObjectID
if (pck[1]=#$04) and (ReadS(22)=ConnectName) and (CharObjID=0) then begin
CharObjID:=ReadD(18);
end;
//Хиляемся..... СНачала обычными банками, потом, когда хп меньше половины - GHP, а когда хп - 10% - QHP
if (pck[1]=#$0E) and (pck[6]=#$04) then begin
CurrentHP:=ReadD(14);
MaxHP:=ReadD(22);
if (CurrentHP < MaxHP) and (CurrentHP > (MaxHP/2)) and (HealReuseTimer.enabled=false) then begin
UseItem(HPBottleID);
HealReuseTimer.enabled:=true;
end;
if (CurrentHP < (MaxHP/2)) and (CurrentHP > ((MaxHP/100)*10)) and (HealReuseTimer.enabled=false) then begin
if (GetInfo(GHPBottleID)<>-1) then begin
UseItem(GHPBottleID);
HealReuseTimer.enabled:=true;
exit;
end;
if (GetInfo(HPBottleID)<>-1) then begin
UseItem(HPBottleID);
HealReuseTimer.enabled:=true;
end;
end;
if (CurrentHP < ((MaxHP/100)*10)) and (HealReuseTimer.enabled=false) then begin
if (GetInfo(QHPBottleID)<>-1) then UseItem(QHPBottleID);
if (GetInfo(GHPBottleID)<>-1) then begin
UseItem(GHPBottleID);
HealReuseTimer.enabled:=true;
exit;
end;
if (GetInfo(HPBottleID)<>-1) then begin
UseItem(HPBottleID);
HealReuseTimer.enabled:=true;
end;
end;
end;
//Рыбачим.....
if Status=true then begin
if (ReadH(1)=5886) and (pck[16]=#$00) and (ReadD(4)=CharObjID) then Pumping;
if (ReadH(1)=5886) and (pck[16]=#$01) and (ReadD(4)=CharObjID) then Reeling;
if (ReadH(1)=5374) and (ReadD(4)=CharObjID) then FishCycleTimer.enabled:=true;
end
else
exit;
end;
//РАЗБОР ПАКЕТОВ ОТ КЛИЕНТА:
if FromClient then begin
if (pck[1]=#$21) then begin
bypass:=ReadS(2);
case bypass of
'StartFishing':begin
if (Status=false) then begin
Status:=true;
Fishing;
end;
end;
'StopFishing':begin
if Status=true then Fishing;
Status:=false;
FishCycleTimer.enabled:=false;
end;
end;
end;
if (pck[1]=#$38) and (ReadS(2)='f') and (ReadD(6)=3) then ShowHTML(HTML);
end;
end.