Некоторые полезные куски кода и функции для использования в своих скриптах:
Отправка сообщений в объявления:
Код:
// отправка сообщений в объявления
// видишь только ты
procedure SendMsg(msg:string);
begin
buf:=#$4A;
WriteD(0);
WriteD(10);
WriteS('');
WriteS(msg);
SendToClient;
end;
для использования:
Код:
SendMsg('Панеслася!!!');
Таймер со сквозным проходом
Если ставить sleep() то скрипт останавливается на время, но и пакеты тоже не принимаются и не отправляются, так вот эта функция позваляет избежать этого
Код:
//(c)dmitry501
var
tick: Integer;
procedure Init;
begin
end;
function Pause(Timewait: Integer):Boolean;
// сквозная проверка без остановки скрипта (c)dmitry501
var
t : integer;
begin
result := false;
t := Round(Time*86400);
if t > (tick + Timewait) then
begin
tick := t;
result := true;
end;
end;
пример использования
Код:
if (NoEarned=1) and pause(2) then //+ 2 секунды ожидания
begin
...........
end;
StrToHex преобразование
Код:
//(c) xkor
function StrToHex(packet: string):string;
var
i:integer;
tmp:byte;
function ByteToHex(b: byte): Char;
begin
if b<10 then result:=chr(b+$30)
else result:=chr(b+$37);
end;
begin
result:='';
for i:=1 to length(packet) do begin
tmp:=ord(packet[i]) div 16;
result:=result+ByteToHex(tmp);
tmp:=ord(packet[i]) - tmp*16;
result:=result+ByteToHex(tmp)+' ';
end;
end;
пример использования
Код:
hextr2:=hextostr(pck);
SHOWMESSAGE(hextr2);
__________________
Я здесь практически не появляюсь!, Skype - ikskor
кто тебе мешает 1 единственный скрипт перенести в топ про БООТА?
етот топ- мервый- поверь...
а то что там про инвентарь написано- то нужно переместить в топ- ДА БУДЕТ БОТ
леха ну реально.. то что можно уместить в приделах одной тему то нехуй плодить по разным топикам...
я думаю всетаки темка полезная, при написании скрипта не придется копаться в готовых и выдергивать из них нужные куски
я думаю, встроенные переменные и функции это именно ВСТРОЕННЫЕ. в этой теме есть удачные решения некоторых задач программирования, а готовые миниботы - это все таки ГОТОВЫЕ миниботы. не имеет смысла соединять эти темы - неразбериха получится.
Работа с инвентарем
скрипт умеет добавлять и удалять вещи из инвентаря, модифицировать их свойства. знает все свойства вещей, которые знает клиент (количество, уровень заточки, надета ли вещь и пр.)
поддерживает только 80 слотов, так что под чаров, имеющих мультипрофу, надо корректировать скрипт.
Код:
var
Inventory: array[0..79,0..9] of integer; // инвентарь (itemType1, ObjectID, ItemID, count, itemType2, CustType1, isEquipped, BodyPart, EnchantLevel, CustType2)
procedure InventoryCreate;
var
i,k: integer;
begin
for i:=0 to 79 do
if (i<ReadH(4)) then begin
Inventory[i,0]:=ReadH(i*28+6); // itemType1
Inventory[i,1]:=ReadD(i*28+8); // ObjectId
Inventory[i,2]:=ReadD(i*28+12); // ItemID
Inventory[i,3]:=ReadD(i*28+16); // count
Inventory[i,4]:=ReadH(i*28+20); // itemType2
Inventory[i,5]:=ReadH(i*28+22); // CustType1
Inventory[i,6]:=ReadH(i*28+24); // isEquipped
Inventory[i,7]:=ReadD(i*28+26); // BodyPart
Inventory[i,8]:=ReadH(i*28+30); // EnchantLevel
Inventory[i,9]:=ReadH(i*28+32); // CustType2
end else
for k:=0 to 9 do Inventory[i,k]:=0; // забиваем нулями
end;
procedure InventoryUpdate;
var
i,j,k: integer;
begin
for j:=0 to (ReadH(2)-1) do begin
case pck[j*30+4] of
#$01: k:=0; // add item, запишет на пустую ячейку
#$02: k:=ReadD(j*30+8); // mod item
#$03: begin // remove item, обнулит ячейки удаленного предмета
k:=ReadD(j*30+8);
for i:=0 to 79 do
if (Inventory[i,0]=k) then begin
for k:=0 to 9 do Inventory[i,k]:=0;
exit;
end;
end;
end;
for i:=0 to 79 do
if (Inventory[i,1]=k) then begin
Inventory[i,0]:=ReadH(j*30+6); // itemType1
Inventory[i,1]:=ReadD(j*30+8); // ObjectId
Inventory[i,2]:=ReadD(j*30+12); // ItemID
Inventory[i,3]:=ReadD(j*30+16); // count
Inventory[i,4]:=ReadH(j*30+20); // itemType2
Inventory[i,5]:=ReadH(j*30+22); // CustType1
Inventory[i,6]:=ReadH(j*30+24); // isEquipped
Inventory[i,7]:=ReadD(j*30+26); // BodyPart
Inventory[i,8]:=ReadH(j*30+30); // EnchantLevel
Inventory[i,9]:=ReadH(j*30+32); // CustType2
break;
end;
end;
end;
function GetInv(obj,up,down:integer): integer; // up и down не проверяются
var // 0-itemType1, 1-ObjectId, 2-ItemID, 3-count, 4-itemType2, 5-CustType1, 6-isEquipped, 7-BodyPart, 8-EnchantLevel, 9-CustType2
i: integer;
begin
for i:=0 to 79 do
if (Inventory[i,up]=obj) then begin
Result:=Inventory[i,down];
exit;
end;
Result:=-1;
end;
BEGIN
//--- INVENTORY BEGIN ---//
if FromServer then case pck[1] of
#$1B: InventoryCreate;
#$27: InventoryUpdate;
end;
//--- INVENTORY END ---//
END.
Использовать так:
Код:
// 0-itemType1, 1-ObjectId, 2-ItemID, 3-count, 4-itemType2, 5-CustType1, 6-isEquipped, 7-BodyPart, 8-EnchantLevel, 9-CustType2
GetInv(по чему будем искать, номер того по чему будем искать, номер того что надо найти);
ex: GetInv(6408,2,1) - вернет ObjectID свадебного платья, если онное лежит в инвентаре, иначе вернет -1
ex2: GetInv(6408,2,8) - вернет уровень заточки первого попавшегося в инвентаре свадебного платья, если свадебного платья нет, то вернет -1
=======================
процедура использования предмета
Код:
procedure UseItem(ItemObjID,shift:integer);
begin
buf:=#$14;
WriteD(ItemObjID);
WriteD(shift);
SendToServer;
end;
Добавлено спустя 3 часа 26 минут 2 секунды: Мониторинг статов чара (хп, мп, цп и координаты)
Код:
var
CharObjID,MyCorX,MyCorY,MyCorZ: integer;
MaxHP,CurHP,MaxMP,CurMP,MaxCP,CurCP: integer;
CharName: string;
procedure InitStats;
var
i: integer;
begin
CharObjID:=ReadD(18);
MyCorX:=ReadD(2);
MyCorY:=ReadD(6);
MyCorZ:=ReadD(10);
i:=22;
CharName:=ReadS(i);
i:=i+44;
MaxHP:=ReadD(i);
CurHP:=ReadD(i);
MaxMP:=ReadD(i);
CurMP:=ReadD(i);
i:=i+363;
MaxCP:=ReadD(i);
CurCP:=ReadD(i);
end;
procedure StatsUpdate;
var
i: integer;
begin
for i:=0 to ReadD(6)-1 do
case pck[i*8+10] of
#$09: CurHP:=ReadD(i*8+14);
#$0A: MaxHP:=ReadD(i*8+14);
#$0B: CurMP:=ReadD(i*8+14);
#$0C: MaxMP:=ReadD(i*8+14);
#$21: CurCP:=ReadD(i*8+14);
#$22: MaxCP:=ReadD(i*8+14);
end;
end;
procedure CorsUpdate;
begin
MyCorX:=ReadD(2);
MyCorY:=ReadD(6);
MyCorZ:=ReadD(10);
end;
BEGIN
//--- STATS BEGIN ---//
if FromServer and (pck[1]=#$04) then InitStats;
if FromServer and (pck[1]=#$0E) and (CharObjID=ReadD(2)) then StatsUpdate;
if FromClient and (pck[1]=#$48) then CorsUpdate;
//--- STATS END ---//
END.
соответственно
Код:
CharName - имя персонажа
MaxHP - максимальное кол-во хп
CurHP - текушее количество хп
по аналогии мп и цп
MyCorX (Y,Z) - текущие координаты (координаты берутся из пакетов ValidatePosition)
Добавлено спустя 47 минут 59 секунд: Таймер со сквозным проходом (mod)
позволяет задавать переменную, по которой будет проверяться время
Код:
function Wait(var tick: integer;Timewait: Integer): Boolean;
// сквозная проверка без остановки скрипта (c)dmitry501
// modifed by Sh00rGo
var
t: integer;
begin
result:=false;
t:=Round(Time*86400);
if t>(tick+Timewait) then begin
if tick>0 then result:=true;
tick:=t;
end;
end;
пример использования:
Код:
var
time1,time2: integer;
procedure Init;
begin
time1:=0;
time2:=1;
end;
procedure SendMsg(msg:string);
begin
buf:=#$4A;
WriteD(0);
WriteD(10);
WriteS('');
WriteS(msg);
SendToClient;
end;
function Wait(var tick: integer;Timewait: Integer): Boolean;
// сквозная проверка без остановки скрипта (c)dmitry501
// modifed by Sh00rGo
var
t: integer;
begin
result:=false;
t:=Round(Time*86400);
if t>(tick+Timewait) then begin
if tick>0 then result:=true;
tick:=t;
end;
end;
begin
if Wait(time1,2) then SendMsg('бу');
if Wait(time2,10) then SendMsg('ы');
end.
в данном случае "бу" будет отсылаться раз в 2 секунды, а "ы" - раз в 10 секунд. переменные time1 и time2 вручную лучше не модифицировать.
если передаваемая переменная tick равна 0, то таймер сработает с заданной задержкой после первого вызова функции, если равна 1, то сразу.
в примере - "ы" отошлется сразу после первого вызова функции, а "бу" через 2 секунды после первого вызова функции.
За это сообщение Shura1oplot нажился 8 спасибками от:
Мой вариант "инвентаризации", описание атрибутов объектов и действий над ними взял у Shura1oplot'a
Код:
//Инвентаризация by QaK
var 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
end;
procedure Free; //Вызывается при выключении скрипта
begin
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]:=ReadC(Counter);
inc(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]:=ReadC(Counter);
Counter:=Counter+2;
end;
end;
end;
//Пакет от сервера 1В - создаем или модифицируем весь инвентарь
procedure CreateItemBase;
var
i,j: integer;
begin
ItemCount:=ReadC(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:=ReadC(1);//Считываем количество изменяемых предметов
j:=4;
for i:=1 to count do
begin Action:=ReadC(j);//Считываем действие
inc(j);
{ADD} if Action=1 then
begin Inc(ItemCount);//Увеличиваем количество занятых слотов
ItemAction(j,ItemCount); //Добавляем предмет
end;
{Update}if Action=2 then for ij:=1 to ItemCount do //Ищем изменяемый предмет по ObjectID
If Inventory[ij,2]=ReadD((j-1)*30+8) then //Если нашли
begin ItemAction(j,ij); //Изменяем данные о нем
exit; //Больше проверять не надо - выходим из цикла
end;
{Delete}if Action=3 then begin for ij:=1 to ItemCount-1 do //Ищем удаляемый предмет
begin If Inventory[iji,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;
//Получить 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
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);
SendToServer;
exit; //Чтоб не использовать несколько предметов с одинаковым ItemID (например заточки)
end;
end;
//основная часть скрипта
//вызывается при приходе каждого пакета если скрипт включен
begin
if pck='' then exit;
if FromServer then
begin if (pck[1]=#$1B) then
begin CreateItemBase;
exit;
end;
if (pck[1]=#$27) then
begin UpdateItemBase;
exit;
end;
end;
end.
Помню этот небольшой скриптик принес мне просто бешеное богатсво на сервере где я играла, но поскольку я больше не играю, то выкладываю в массы :)
суть проста, программа ведет учет всех персов в округе, когда по вашему персу-торговцу кликают, она пишет в френдчат ему предложение купить стрелу и обешание за это рассказать анекдотик. за покупку программа конечно же как и обешала рассказывает анекдотик. как показывает практика, самая идеальная цена чтобы клиенты купили как можно больше ваших стрел, для х1 - это не более 3к, для х5 - 10к. а для привлечения внимания именно к вашему торговцу, в титуле (для этого вам надо быть в клане) постоянно мигает рожица и надпись "АНЕКДОТЫ". Все анекдоты грузяться с папки c:\l2jokes (в аттаче уже готовый архив с 237 анекдотами), каждый анекдот в отдельном файле, не более 255 символов.
Пользуйтесь на здоровье
Код:
// copyright (c) 2006, 2007 Puella
var curpos: byte;
TITLE_DATA2: array [0..16] of string;
const
jokes_max = 237;
var
f: TStringList;
jokes: array [1..jokes_max] of string;
jokes_real: integer;
IDs: array [1..2000] of cardinal;
Names: array [1..2000] of String;
count: Integer;
MyID: Cardinal;
MyName: String;
m: TMemo;
t: TTimer;
InTimer: Boolean;
procedure OnTimerProc;
begin
InTimer := true;
buf := #$55;
WriteS(MyName);
WriteS(TITLE_DATA2[curpos]);
SendToServer;
curpos := curpos + 1;
if curpos > 16 then curpos := 0;
InTimer := false;
end;
procedure Init;
var i: byte;
begin
randomize;
count := 0;
f := TStringList.Create;
jokes_real := 0;
for i := 1 to jokes_max do
begin
try
f.LoadFromFile('C:\l2jokes\' + IntToStr(i) + '.txt');
jokes_real := jokes_real + 1;
except
end;
jokes[jokes_real] := f.Text;
end;
f.free;
TITLE_DATA2[0] := '@(o_O)@';
TITLE_DATA2[1] := '@(O_o)@';
TITLE_DATA2[2] := '@(o_O)@';
TITLE_DATA2[3] := '@(O_o)@';
TITLE_DATA2[4] := '';
TITLE_DATA2[5] := 'ANEKDOTI';
TITLE_DATA2[6] := '';
TITLE_DATA2[7] := 'ANEKDOTI';
TITLE_DATA2[8] := '';
TITLE_DATA2[9] := 'ANEKDOTI';
TITLE_DATA2[10] := '';
TITLE_DATA2[11] := '@(o_O)@';
TITLE_DATA2[12] := '@(O_o)@';
TITLE_DATA2[13] := '@(o_O)@';
TITLE_DATA2[14] := '@(O_o)@';
TITLE_DATA2[15] := '@(o_O)@';
TITLE_DATA2[16] := '@(O_o)@';
curpos := 0;
t := TTimer.Create(nil);
t.Enabled := false;
t.Interval := 2000;
t.OnTimer := @OnTimerProc;
ShowTab;
m:=TMemo.Create(UserTab);
m.parent:=UserTab;
m.align:=alClient;
m.ReadOnly:=true;
m.ScrollBars:=ssBoth;
m.lines.add('Анекдотов загружено: ' + inttostr(jokes_real));
end;
procedure Free;
begin
m.Free;
HideTab;
t.OnTimer := nil;
t.Enabled := false;
t.Interval := 0;
t.Free;
end;
function FindPlayer(ObjID: cardinal): integer;
var k: cardinal;
begin
result := -1;
if Count > 0 then
for k := 1 to Count do
if IDs[k] = ObjID then
begin
result := k;
break
end;
end;
var
i, k: integer;
objid: cardinal;
name: string;
begin
if FromServer then
case pck[1] of
#$64:
begin
i := 2;
if ReadD(i) = 380 then {S1_PURCHASED_S3_S2_s}
begin
i := i + 4*2;
name := ReadS(i);
if (name = '') then
begin
// внесем в лог (blacklist)
m.Lines.Add(TimeToStr(now)+': '+name+' purchased (BLACKLISTED)');
end
else
begin
while (InTimer = true) do i := i;
buf := #$CC;
i := int(random * jokes_real) + 1;
WriteS(jokes[i]);
WriteS(name);
SendToServer;
if (Length(m.Lines.Text) > 60000) then m.Lines.Text := '<cleared>';
// внесем в лог
m.Lines.Add(TimeToStr(now)+': '+name+' purchased');
m.Lines.Add('> ' + jokes[i]);
end;
end
end;
#$03: // CharInfo
begin
i := 4 + 4 * 4 - 2;
objid := ReadD(i);
i := FindPlayer(ObjID);
if i = -1 then
begin
i := 4 + 4 * 5 - 2;
name := ReadS(i);
// blacklist
if (name = '') then
begin
// (none)
end
else begin
// добавление
count := count + 1;
IDs[count] := ObjID;
Names[count] := name;
//m.Lines.Add(IntToStr(count) + ' - ' + Format('%x', [ObjId])+' = '+ Names[count]);
end;
end;
end;
#$04: //UserInfo
begin
i := 2 + 4*4;
MyID := ReadD(i);
MyName := ReadS(i);
t.Enabled := true;
end;
#$12: // ObjectDelete
begin
i := 2;
objid := ReadD(i);
i := FindPlayer(objid);
if i <> -1 then
begin
IDs[i] := IDs[count];
Names[i] := Names[count];
count := count - 1;
end
end;
#$29: //TargetSeleted
begin
i := 2;
objid := ReadD(i);
if ReadD(i) <> MyID then exit;
i := FindPlayer(objid);
if i <> -1 then
begin
while (InTimer = true) do i := i;
buf := #$CC;
WriteS('Привет, '+names[i]+'! Я бот! Купи у меня стрел и я, в благодарность за это, расскажу тебе анекдот или стишок на тему LineAge2! ;)');
WriteS(names[i]);
SendToServer;
// внесем в лог
m.Lines.Add(TimeToStr(now)+': '+names[i]);
end
end;
end;
end.
Скрипт-то не плохой, да думаю бан за него долго ждать не придется....
ЗЫ Почитал анекдоты в архиве, отмороженные ЖЕСТЬ!
Юльчик не в обиду, не ты ж их придумывала)
Скрипт-то не плохой, да думаю бан за него долго ждать не придется....
ЗЫ Почитал анекдоты в архиве, отмороженные ЖЕСТЬ!
Юльчик не в обиду, не ты ж их придумывала)
я предварительно договорилась с администрацией об такой "изюминке" для сервера, так что никакого бана, даже наоборот две недели торговли и А грейд на х1 :))))) а анекдоты конечно не я придумывала, хотя с дюжину наверное там анекдотов понятных только игрокам нашего сервера и соответсвенно придуманных игроками.