PDA

Просмотр полной версии : ОТПТИМИЗАЦИЯ БОТА!


skymanrus
03.01.2008, 15:58
всем привет ещё раз :)
в общем написал я скрипт бота и по идее все должно прекрасно работать
и в принципе так почти и есть но вот одна проблема есть:
скрипт пашет очень медленно!! :(
клиент виснет вааще :(
я его уже замучился оптимизировать
тестировал его только на сервере http://www.fogofwar.ru (http://www.fogofwar.ru) и работоспособность на других серверах не гарантирую
не подскажете что тут можно изменить для увеличения скорости работы скрипта?



var
m,mlk, vare:TMemo;
frm:TForm;
heal, HPuse, spoilid: string;
MaxHP, MyZpos, cvaZ, spoil, CurHP, i, t, ID, xpos, ypos, skill, MyID, HPbutt, MEsit, MEup, but, sud, bst, RADV, cvaX, attackIDMinID, attackk, attackID, cvaY, zpos, SummaAR, MyXpos, MyYpos, rezu, MaxX, MaxID, MinID, MinX: integer;
sit, povtor, tame, gdo, npc : Boolean;
MobsID: array[1..100] of integer;
MobsRAS: array[1..100] of integer;
MobsX: array[1..100] of integer;
MobsY: array[1..100] of integer;
MobsZ: array[1..100] of integer;
NPCid: array[1..100] of integer;
hohodf: array[1..100] of Boolean;
timer1: TTimer;

procedure Init; //УПРАВЛЯЮЩИЕ ПЕРЕМЕННЫЕ
begin
RADV:=2000; // радиус круга кача!
spoil:=1; // юзать споил?! 1-да 0-нет
HPbutt:=70; // при каком количестве хп в % юзать бутылку лечения
MEsit:=55; // при каком количестве хп в % надо сесть и подкопить хп
MEup:=90; // при каком количестве хп в % надо встать после отдыха
frm := TForm.Create(nil);
frm.Caption := 'BOT Info!';
frm.BorderStyle := bsSizeable;
frm.Position := poScreenCenter;
frm.Width:=470;
frm.Height:=450;
m:=TMemo.Create(frm);
m.parent:=frm;
m.align:=alLeft;
m.ReadOnly:=true;
m.ScrollBars:=0;
m.Width:=470;
m.Height:=370;
m.Lines.Add(' БОТ НЕ ПОДКЛЮЧЁН К СЕРВЕРУ!');
mlk:=TMemo.Create(frm);
mlk.parent:=frm;
mlk.align:=alBottom;
mlk.ReadOnly:=true;
mlk.ScrollBars:=0;
mlk.Width:=470;
mlk.Height:=100;
mlk.Lines.Add('...');
vare:=TMemo.Create(frm);
vare.parent:=frm;
vare.align:=alRight;
vare.ReadOnly:=true;
vare.ScrollBars:=0;
vare.Width:=180;
vare.Height:=100;
frm.Show;
heal:=HStr('45 00 00 00 00 00 00 00 00 00 '); // СИДЕТЬ!!!

timer1:=TTimer.Create(nil);
timer1.OnTimer:=@OnTimer; //
timer1.enabled:=false; // таймер по умолчанию включен и бот тоже
timer1.interval:=1000; // через каждые 1сек будем обновлять базу данных

for i:= 1 to 100 do
begin
hohodf[i]:=false;
end;
end;

procedure playBD;
begin
m.Lines.Clear;
vare.Lines.Clear;
vare.Lines.Add('MaxHP :'+IntToStr(MaxHP)+' макс хп');
vare.Lines.Add('CurHP :'+IntToStr(CurHP)+' сейчас хп');
vare.Lines.Add('MyID :'+IntToStr(MyID)+' мой ид');
vare.Lines.Add('MyXpos :'+IntToStr(MyXpos)+' мои x');
vare.Lines.Add('MyYpos :'+IntToStr(MyYpos)+' мои y');
vare.Lines.Add('MyZpos :'+IntToStr(MyZpos)+' мои z');
vare.Lines.Add('HPuse: '+HPuse+' скил хп');
vare.Lines.Add('RADV :'+IntToStr(RADV)+' круг кача');
vare.Lines.Add('spoilid: '+spoilid+' заспойленый');
vare.Lines.Add('cvaX :'+IntToStr(cvaX)+' центр к');
vare.Lines.Add('cvaY :'+IntToStr(cvaY)+' центр к');
vare.Lines.Add('cvaZ :'+IntToStr(cvaZ)+' центр к');
vare.Lines.Add('skill :'+IntToStr(skill)+' юзал скил');
vare.Lines.Add('spoil :'+IntToStr(spoil)+' споил?');
vare.Lines.Add('but :'+IntToStr(but)+' бутылки');
vare.Lines.Add('sud :'+IntToStr(sud)+' сидеть');
vare.Lines.Add('bst :'+IntToStr(bst)+' встать');
vare.Lines.Add('ID :'+IntToStr(ID)+' кто ходит');
vare.Lines.Add('xpos :'+IntToStr(xpos)+' кто ходит');
vare.Lines.Add('ypos :'+IntToStr(ypos)+' кто ходит');
vare.Lines.Add('zpos :'+IntToStr(zpos)+' кто ходит');
vare.Lines.Add('sit :'+VarToStr(sit)+' сижу?');
vare.Lines.Add('HPbutt :'+IntToStr(HPbutt)+' %хп');
vare.Lines.Add('MEsit :'+IntToStr(MEsit)+' %хп');
vare.Lines.Add('MEup :'+IntToStr(MEup)+' %хп');
vare.Lines.Add('attackIDMinID :'+IntToStr(attackIDMinID)+' ближний');
vare.Lines.Add('attackID :'+IntToStr(attackID)+' ближний');
vare.Lines.Add('attackk :'+IntToStr(attackk)+' цикл атак');
vare.Lines.Add('SummaAR :'+IntToStr(SummaAR)+' всего в бд');
vare.Lines.Add('rezu :'+IntToStr(rezu)+' рез ближ');
vare.Lines.Add('MaxX :'+IntToStr(MaxX));
vare.Lines.Add('MaxID :'+IntToStr(MaxID));
vare.Lines.Add('MinX :'+IntToStr(MinX));
vare.Lines.Add('MinID :'+IntToStr(MinID));
vare.Lines.Add('povtor :'+VarToStr(povtor));
vare.Lines.Add('tame :'+VarToStr(tame)+' выч %хп');
vare.Lines.Add('gdo :'+VarToStr(gdo)+' центр окр');

if (MaxHP<>0) then
begin
m.Lines.Add('близкий МОБ id:'+IntToStr(MinID)+' дистанция'+IntToStr(MinX));
m.Lines.Add('MOЁ HP:'+IntToStr(MaxHP)+'-'+IntToStr(CurHP)+' цикл'+IntToStr(attackk));
if (HPuse='') then
m.Lines.Add(' ЮЗАТЬ БУТЫЛКИ?: НЕТ!');
if (HPuse<>'') then
m.Lines.Add(' ЮЗАТЬ БУТЫЛКИ?: ДА!');
if (sit=false) then
m.Lines.Add(' БОТ СТОИТ!');
if (sit=true) then
m.Lines.Add(' БОТ СИДИТ!');
for i:= 1 to 100 do
begin
if (MobsID[i]<>0) then
begin
if (attackIDMinID<>i) then
m.Lines.Add('--'+IntToStr(i)+' ИД МОБА:'+IntToStr(MobsID[i])+' растояние:'+IntToStr(MobsRAS[i])+' атакует:'+VarToStr(hohodf[i])+' x:'+IntToStr(MobsX[i])+' y:'+IntToStr(MobsY[i])+' z:'+IntToStr(MobsZ[i]) );
if (attackIDMinID=i) then
m.Lines.Add('>'+IntToStr(i)+' ИД МОБА:'+IntToStr(MobsID[i])+' растояние:'+IntToStr(MobsRAS[i])+' атакует:'+VarToStr(hohodf[i])+' x:'+IntToStr(MobsX[i])+' y:'+IntToStr(MobsY[i])+' z:'+IntToStr(MobsZ[i]) );
end;
end;
end;
if (MaxHP=0) then m.Lines.Add(' ИДЕТ ЗАГРУЗКА БОТА!!!');
end;


procedure Free;
begin
DelALL;
end;

procedure StatsUpdate;
begin
if (ReadD(10)=9) and (pck[18]=#$0A) then
begin
CurHP:=ReadD(14);
MaxHP:=ReadD(22);
if (MaxHP<>0) and (tame=false) then // вычисляем процентное соотношение хп
begin
but:=Round((MaxHP/100)*HPbutt); // при каком количестве хп юзать бутылку лечения
sud:=Round((MaxHP/100)*MEsit); // при каком количестве хп надо сесть и подкопить хп
bst:=Round((MaxHP/100)*MEup); // при каком количестве хп надо встать после отдыха
tame:=true;
end;
end;
end;

procedure rastoyanie(xpos1, ypos1, xpos2, ypos2:integer); //возвращает переменную rezu которая является растоянием между 2 точками
begin
rezu:= Round(Sqrt(((xpos1-xpos2)*(xpos1-xpos2))+((ypos1-ypos2)*(ypos1-ypos2))));
end;

procedure SelectT(sel:integer); //выбрать моба
begin
buf:=#$A6;
WriteD(sel);
WriteD(0);
SendToClient;
end;

procedure DelElArr(ele:integer); //удаляет моба!
begin
MobsID[ele]:=0;
MobsRAS[ele]:=0;
MobsX[ele]:=0;
MobsY[ele]:=0;
MobsZ[ele]:=0;
hohodf[ele]:=false;
end;

procedure DelALL; //обнуляем всю базу!
begin
for i:= 1 to 100 do
begin
NPCid[i]:=0;
MobsID[i]:=0;
MobsRAS[i]:=0;
MobsX[i]:=0;
MobsY[i]:=0;
MobsZ[i]:=0;
hohodf[i]:=false;
end;
heal:='';
HPuse:='';
spoilid:='';
MaxHP:=0;
MyZpos:=0;
cvaZ:=0;
spoil:=0;
CurHP:=0;
i:=0;
t:=0;
ID:=0;
xpos:=0;
ypos:=0;
sit:=false;
skill:=0;
MyID:=0;
HPbutt:=0;
MEsit:=0;
MEup:=0;
but:=0;
sud:=0;
bst:=0;
RADV:=0;
cvaX:=0;
attackIDMinID:=0;
attackk:=0;
attackID:=0;
cvaY:=0;
zpos:=0;
SummaAR:=0;
MyXpos:=0;
MyYpos:=0;
rezu:=0;
MaxX:=0;
MaxID:=0;
MinID:=0;
MinX:=0;
povtor:=false;
tame:=false;
gdo:=false;
npc:=false;
timer1.Free;
//m.Free;
//mlk.Free;
//frm.Free;
end;

procedure GetMaxX(arra:array of integer); //возвращает в переменную MaxX максимальное значение массива а в MaxID номер этого элемента
begin
MaxX:=0;
MaxID:=0;
for i:= 1 to 100 do
begin
if (arra[i]>=MaxX) then
begin
MaxX:=arra[i];
MaxID:=i;
end;
end;
end;

procedure ETOpovtor(chislo: integer; arra:array of integer); //возвращает переменную povtor и если она равна 1 значит chislo уже есть в массиве!
begin
povtor:=false;
for t:= 1 to 100 do
begin
if (arra[t]=chislo) then
begin
povtor:=true;
end;
end;
end;


procedure GetMinX(arra:array of integer); //возвращает в переменную MinX минимальное значение массива а в MinID номер этого элемента
begin
MinX:=5000;
MinID:=0;
for i:= 1 to 100 do
begin
if (arra[i]<=MinX) and (arra[i]<>0) then
begin
MinX:=arra[i];
MinID:=i;
end;
end;
end;

procedure attackt(mobus:integer);
begin
buf:=#$04;
WriteD(MobsID[mobus]);
WriteD(MobsX[mobus]);
WriteD(MobsY[mobus]);
WriteD(MobsZ[mobus]);
buf:=buf+#$00;
SendToServer;
end;

procedure Summ(sum:array of integer); //возвращает переменную SummaAR с количеством полных(не пустых) ячеек
var
Summa: integer;
begin
Summa:=0;
for i:= 1 to 100 do
begin
if (sum[i]<>0) then
begin
Summa:=Summa+1;
end;
end;
SummaAR:=Summa;
end;

procedure OnTimer(Sender: TObject); // ВЫДЕЛЕНИЕ И АТАКА МОБА!!!!!!!!!!!!!
begin

if (MinID>0) then
begin
if (attackk=0) then
begin
SelectT(MobsID[MinID]);
attackt(MinID);
attackID:=MobsID[MinID];
attackIDMinID:=MinID;
mlk.Lines.Add('! '+IntToStr(ID));
end;
if (attackk=20) then attackt(attackIDMinID);
if (attackk=50) then attackt(attackIDMinID);
if (spoil=1) and (skill=0) then
begin
buf:=hstr('04')+IntToStr(MobsID[MinID])+IntToStr(MobsX[MinID])+IntToStr(MobsY[MinID])+IntToStr(MobsZ[MinID])+hstr('00');
spoilid:=IntToStr(MobsID[MinID])+IntToStr(MobsX[MinID])+IntToStr(MobsY[MinID])+IntToStr(MobsZ[MinID]);
SendToServer;
buf:=hstr('2F FE 00 00 00 00 00 00 00 00'); //юзаем споил
SendToServer;
end;
if (CurHP<but) then
begin
if (HPuse<>'') then
begin
buf:=HPuse;
SendToServer;
end;
end;
Summ(hohodf);
if (CurHP<sud) and (SummaAR=0) and (sit=false) then
begin
mlk.Lines.Add(' все блин я отдыхаю!');
buf:=heal;
SendToServer;
sit:=true;
end;
if (CurHP>bst) and (sit=true) then
begin
mlk.Lines.Add(' пора за работу!');
buf:=heal;
SendToServer;
sit:=false;
end;
attackk:=attackk+1;
end;
end;

procedure AddBD(id, posx, posy, posz:integer;); //добавляем моба в базу данных
begin
rastoyanie(MyXpos, MyYpos, posx, posy);
for i:= 1 to 100 do //перебираем базу и ищем свободную ячейку в ней
begin
if (MobsID[i]=0) then
begin //запоминаем моба в свободную ячейку
ETOpovtor(id, MobsID);
if (povtor=false) then
begin
MobsID[i]:=id; //ид моба
MobsRAS[i]:=rezu; //растояние до этого моба
MobsX[i]:=posx;
MobsY[i]:=posy;
MobsZ[i]:=posz;
mlk.Lines.Add('!-'+IntToStr(i)+'-id-'+IntToStr(MobsID[i])+'-ras-'+IntToStr(MobsRAS[i]));
break;
end;
end;
end;
end;

procedure ISnpc(id: integer;);
begin
npc:=false;
for i:= 1 to 100 do
begin
if (NPCid[i]=id) then
begin
npc:=true;
end;
end;
end;

begin // MAIN !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

if FromClient and (pck[1]=#$14) and (HPuse='') then // была использованная какая то вещь предположительно бутылка хп
begin
HPuse:=pck;
mlk.Lines.Add('ID бутылок записан в BD:'+HPuse);
end;

if FromServer and (pck[1]=#$76) and (ReadD(2)=MyID) then //я юзнул какаой то скилл
begin
mlk.Lines.Add(' юзнул скилл!');
skill:=1;
end;

if FromServer and (pck[1]=#$0E) and (MyID=ReadD(2)) then StatsUpdate; //обновление информации о хп

if FromServer and (pck[1]=#$05) and (ReadD(6)=MyID) then // меня ударили
begin
sit:=false;
mlk.Lines.Add('КТОТ ОБНОГЛЕЛ!!');
ETOpovtor(ReadD(2), MobsID); // чтоб проц не перегружать
if (povtor=false) then
begin
AddBD(ReadD(2), ReadD(15), ReadD(19), ReadD(23));
end;
for i:= 1 to 100 do
begin
if (MobsID[i]=ReadD(2)) then //если моб записан в базе данных
begin
mlk.Lines.Add('АТАКА!!!'+IntToStr(i)+'-'+IntToStr(attackIDMinID));
MobsRAS[i]:=1;
hohodf[i]:=true; // стал агрессор
if (timer1.enabled=false) then // если я только зашел в игру и на меня напали
begin
attackIDMinID:=i;
timer1.enabled:=true;
end;
if (attackIDMinID<>0) and (hohodf[attackIDMinID]=false) then
attackIDMinID:=i;
break;
end;
end;
end;

if FromServer and (MyXpos<>0) and (pck[1]=#$0C) then
begin
rastoyanie(MyXpos, MyYpos, ReadD(14), ReadD(18));
if (rezu<=200) then
begin
mlk.Lines.Add('чет упало!!!');
timer1.enabled:=false;
buf:=#$04;
WriteD(ReadD(6));
WriteD(ReadD(14));
WriteD(ReadD(18));
WriteD(ReadD(22));
buf:=buf+#$00;
SendToServer;
mlk.Lines.Add(' ТОРМОЗ! чет упало!!!');
delay(1000);
timer1.enabled:=true;
end;
end;

if FromClient and (pck[1]=#$1B) then
begin
if (ReadD(2)=6) then
begin
cvaX:=MyXpos;
cvaY:=MyYpos;
cvaZ:=MyZpos;
mlk.Lines.Add('! БОТ ВКЛЮЧЕН координаты ОБНОВЛЕНЫ!!');
timer1.enabled:=true;
end;
if (ReadD(2)=5) then
begin
timer1.enabled:=false;
mlk.Lines.Add('! БОТ ВЫКЛЮЧЕН!!!');
end;
end;

if FromServer and (pck[1]=#$04) then //получаю пакет с инфой о моём чаре
begin
MyID:=ReadD(18); //получаю ид моего чара
MyXpos:=ReadD(2); //получаю координату х моего чара
MyYpos:=ReadD(6); //получаю координату у моего чара
MyZpos:=ReadD(10); //получаю координату z моего чара
//sit:=0;
if (gdo=false) then // задаем центр окружности кача
begin
cvaX:=ReadD(2);
cvaY:=ReadD(6);
gdo:=true;
end;
end;

if FromClient and (pck[1]=#$48) then //обновляем ВСЕ растояния в BD если мы сошли с места
begin
MyXpos:=ReadD(2); //получаю координату х моего чара
MyYpos:=ReadD(6); //получаю координату у моего чара
MyZpos:=ReadD(10); //получаю координату z моего чара
//sit:=0;
for i:= 1 to 100 do
begin
if (MobsID[i]<>0) then
begin
if (true<>hohodf[i]) then
begin
rastoyanie(MyXpos, MyYpos, MobsX[i], MobsY[i]);
MobsRAS[i]:=rezu;
end;
end;
end;
end;

if FromServer and (pck[1]=#$01) and (ReadD(2)<>MyID) then //если на серваке ктото перемещается
begin
ID:=ReadD(2); // ктото рыпнулся с места надо это записать...
xpos:=ReadD(6);
ypos:=ReadD(10);
zpos:=ReadD(14);
ISnpc(ReadD(2));
rastoyanie(cvaX, cvaY, ReadD(6), ReadD(10));
if (npc=false) and (rezu<=RADV) then
begin
AddBD(ID, xpos, ypos, zpos);
end;
end;

if FromServer and (pck[1]=#$06) then //моб сдох! выкидываем его из базы and (attackID=ReadD(2))
begin
if (pck[22]=#$01) then
begin
mlk.Lines.Add(' свипаю!');
buf:=hstr('04')+spoilid+hstr('00');
SendToServer;
buf:=hstr('2F 2A 00 00 00 00 00 00 00 00');
SendToServer;
spoilid:='';
mlk.Lines.Add(' ТОРМОЗ! ОН УМЕР!!!');
delay(700);
end;
for i:= 1 to 100 do
begin
if (MobsID[i]=ReadD(2)) then
begin
skill:=0;
DelElArr(i);
attackk:=0;
mlk.Lines.Add('БОБИК СДОХ!! :'+IntToStr(i));
mlk.Lines.Add(' ТОРМОЗ! внатуре умер!!!');
// delay(100);
break;
end;
end;
end;

GetMaxX(MobsRAS);
GetMinX(MobsRAS);
Summ(MobsRAS);

if (SummaAR>=90) or (MaxX>5000) then //если у нас больше 90 ячеек с мобами надо удалить самых дальних от нас
begin
mlk.Lines.Add('мусор удалён:'+IntToStr(MaxID)+' :'+IntToStr(MaxX)+' сумма'+IntToStr(SummaAR)+'-');
DelElArr(MaxID);
end;

if FromServer and (pck[1]=#$16) and (MyID<>0) then
begin
if (ReadD(10)=0) then
begin
for i:= 1 to 100 do
begin
if (NPCid[i]=0) then
begin
ETOpovtor(ReadD(2), NPCid);
if (povtor=false) then
begin
NPCid[i]:=ReadD(2);
break;
end;
end;
end;
mlk.Lines.Add('добавил NPC!');
end;
if (ReadD(10)=1) and (pck[120]=#$00) then
begin
rastoyanie(cvaX, cvaY, ReadD(14), ReadD(18));
if (rezu<=RADV) then
begin
AddBD(ReadD(2), ReadD(14), ReadD(18), ReadD(22));
end;
end;
end;

if FromServer and (pck[1]=#$03) and (MyID<>0) then
begin
for i:= 1 to 100 do
begin
if (NPCid[i]=0) then
begin
ETOpovtor(ReadD(18), NPCid);
if (povtor=false) then
begin
NPCid[i]:=ReadD(18);
mlk.Lines.Add('ИГРОК ДОБАВЛЕН!-'+IntToStr(i)+'--'+IntToStr(NPCid[i]));
break;
end;
end;
end;
end;

if (SummaAR=0) and (timer1.enabled=true) then
begin
buf:=#$01;
WriteD(cvaX);
WriteD(cvaY);
WriteD(cvaZ);
WriteD(0);
WriteD(0);
WriteD(0);
buf:=buf+#$01+#$00+#$00+#$00;
SendToServer;
end;

playBD;
end. // END MAIN



сразу скажу функции delay() тут причем я их пробывал убирать пашет так же
ставил timer1.interval:=100; грузит ещё дольше а толку меньше :(
в общем уже 4-5 день над ним мучеюсь :)
помогите народ :)

Добавлено спустя 4 минуты 44 секунды:
сразу скажу что в не оптимизированной версии этого скрипта 1000 строк что почти в 2 раза больше этого скрипта и работал он в 20 раз быстрее не смотря на некоторые глюки

Добавлено спустя 15 часов 23 минуты 27 секунд:
короче я понял что бота тормозят сильно циклы которые проходят в холостую и постоянно повторяющиеся вызовы из главного исполняющего begin
щас переписываю все по новой :)
если будут ещё замечания то я буду очень рад выслушать ваше мнение !

NLObP
04.01.2008, 00:57
Интересный скрипт. Пробовал его с модификацией на локальном сервере Интерлюдии. Тормозит, мне кажется, из-за циклов. Заметил, что если в деревне есть движущийся NPC, то тормоза обеспечены, при просчете перемещений.
Ха, не заметил сразу твоих комментариев в конце. Буду пробовать модифицировать твой скрипт.

Предварительная модификация скрипта. Можно запускать для нескольких чаров.
В деревне где бродят NPC не тормозит. Скрипт подходит для гнома или воина. Есть еще не устраненные глюки.
//Bot by Skymanrus
//modified by NLObP для Интерлюдии

//************************************************** *************
const
name='Clare'; //имя чара для которого включен скрипт
max=500; //максимальное значение массива

//************************************************** *************
var
m,mlk, vare:TMemo;
frm:TForm;
heal, HPuse, spoilid: string;
MaxHP, MyZpos, cvaZ, spoil, CurHP, i, t, ID, xpos, ypos, skill, MyID, HPbutt, MEsit, MEup, but, sud, bst, RADV, cvaX, attackIDMinID, attackk, attackID, cvaY, zpos, SummaAR, MyXpos, MyYpos, rezu, MaxX, MaxID, MinID, MinX: integer;
sit, povtor, tame, gdo, npc : Boolean;
last : integer; //последняя запись в массиве, для ускорения скрипта
MobsID: array[1..max] of integer;
MobsRAS: array[1..max] of integer;
MobsX: array[1..max] of integer;
MobsY: array[1..max] of integer;
MobsZ: array[1..max] of integer;
NPCid: array[1..max] of integer;
hohodf: array[1..max] of Boolean;
timer1: TTimer;
timer2: TTimer;

//************************************************** *************
procedure Init; //УПРАВЛЯЮЩИЕ ПЕРЕМЕННЫЕ
begin
last:=1; //начальное значение
RADV:=2000; // радиус круга кача!
spoil:=1; // юзать споил?! 1-да 0-нет
HPbutt:=70; // при каком количестве хп в % юзать бутылку лечения
MEsit:=55; // при каком количестве хп в % надо сесть и подкопить хп
MEup:=90; // при каком количестве хп в % надо встать после отдыха
frm := TForm.Create(nil);
frm.Caption := 'BOT Info!';
frm.BorderStyle := bsSizeable;
frm.Position := poScreenCenter;
frm.Width:=650;
frm.Height:=700;
m:=TMemo.Create(frm);
m.parent:=frm;
m.align:=alLeft;
m.ReadOnly:=true;
m.ScrollBars:=0;
m.Width:=470;
m.Height:=370;
m.Lines.Add(' БОТ НЕ ПОДКЛЮЧЁН К СЕРВЕРУ!');
mlk:=TMemo.Create(frm);
mlk.parent:=frm;
mlk.align:=alBottom;
mlk.ReadOnly:=true;
mlk.ScrollBars:=0;
mlk.Width:=570;
mlk.Height:=100;
mlk.Lines.Add('...');
vare:=TMemo.Create(frm);
vare.parent:=frm;
vare.align:=alRight;
vare.ReadOnly:=true;
vare.ScrollBars:=0;
vare.Width:=180;
vare.Height:=100;
frm.Show;
heal:=HStr('45 00 00 00 00 00 00 00 00 00 '); // СИДЕТЬ!!!

//атака и прочее
timer1:=TTimer.Create(nil);
timer1.OnTimer:=@OnTimer1; //
timer1.enabled:=false; // таймер по умолчанию включен и бот тоже
timer1.interval:=1000; // через каждые 1сек будем обновлять базу данных

//вывод в форму
timer2:=TTimer.Create(nil);
timer2.OnTimer:=@OnTimer2; //
timer2.enabled:=true; // таймер по умолчанию включен и бот тоже
timer2.interval:=1000; // через каждые 1сек будем обновлять базу данных

for i:= 1 to max do begin
hohodf[i]:=false;
end;
end;

//************************************************** *************
procedure playBD;
begin
m.Lines.Clear;
vare.Lines.Clear;
vare.Lines.Add('MaxHP :'+IntToStr(MaxHP)+' макс хп');
vare.Lines.Add('CurHP :'+IntToStr(CurHP)+' сейчас хп');
vare.Lines.Add('MyID :'+IntToStr(MyID)+' мой ид');
vare.Lines.Add('MyXpos :'+IntToStr(MyXpos)+' мои x');
vare.Lines.Add('MyYpos :'+IntToStr(MyYpos)+' мои y');
vare.Lines.Add('MyZpos :'+IntToStr(MyZpos)+' мои z');
vare.Lines.Add('HPuse: '+HPuse+' скил хп');
vare.Lines.Add('RADV :'+IntToStr(RADV)+' круг кача');
vare.Lines.Add('spoilid: '+spoilid+' заспойленый');
vare.Lines.Add('cvaX :'+IntToStr(cvaX)+' центр к');
vare.Lines.Add('cvaY :'+IntToStr(cvaY)+' центр к');
vare.Lines.Add('cvaZ :'+IntToStr(cvaZ)+' центр к');
vare.Lines.Add('skill :'+IntToStr(skill)+' юзал скил');
vare.Lines.Add('spoil :'+IntToStr(spoil)+' споил?');
vare.Lines.Add('but :'+IntToStr(but)+' бутылки');
vare.Lines.Add('sud :'+IntToStr(sud)+' сидеть');
vare.Lines.Add('bst :'+IntToStr(bst)+' встать');
vare.Lines.Add('ID :'+IntToStr(ID)+' кто ходит');
vare.Lines.Add('xpos :'+IntToStr(xpos)+' кто ходит');
vare.Lines.Add('ypos :'+IntToStr(ypos)+' кто ходит');
vare.Lines.Add('zpos :'+IntToStr(zpos)+' кто ходит');
vare.Lines.Add('sit :'+VarToStr(sit)+' сижу?');
vare.Lines.Add('HPbutt :'+IntToStr(HPbutt)+' %хп');
vare.Lines.Add('MEsit :'+IntToStr(MEsit)+' %хп');
vare.Lines.Add('MEup :'+IntToStr(MEup)+' %хп');
vare.Lines.Add('attackIDMinID :'+IntToStr(attackIDMinID)+' ближний');
vare.Lines.Add('attackID :'+IntToStr(attackID)+' ближний');
vare.Lines.Add('attackk :'+IntToStr(attackk)+' цикл атак');
vare.Lines.Add('Last :'+IntToStr(Last)+' последняя в бд');
vare.Lines.Add('SummaAR :'+IntToStr(SummaAR)+' всего в бд');
vare.Lines.Add('rezu :'+IntToStr(rezu)+' рез ближ');
vare.Lines.Add('MaxX :'+IntToStr(MaxX));
vare.Lines.Add('MaxID :'+IntToStr(MaxID));
vare.Lines.Add('MinX :'+IntToStr(MinX));
vare.Lines.Add('MinID :'+IntToStr(MinID));
vare.Lines.Add('povtor :'+VarToStr(povtor));
vare.Lines.Add('tame :'+VarToStr(tame)+' выч %хп');
vare.Lines.Add('gdo :'+VarToStr(gdo)+' центр окр');
if (MaxHP<>0) then begin
m.Lines.Add('Ближайший МОБ: id='+IntToStr(MinID)+' дистанция='+IntToStr(MinX));
m.Lines.Add('MOЁ HP:'+IntToStr(MaxHP)+'-'+IntToStr(CurHP)+' цикл атаки:'+IntToStr(attackk));
if (HPuse='') then m.Lines.Add(' ЮЗАТЬ БУТЫЛКИ?: НЕТ!');
if (HPuse<>'') then m.Lines.Add(' ЮЗАТЬ БУТЫЛКИ?: ДА!');
if (sit=false) then m.Lines.Add(' БОТ СТОИТ!');
if (sit=true) then m.Lines.Add(' БОТ СИДИТ!');
for i:= 1 to last do begin
if (MobsID[i]<>0) then begin
if (attackIDMinID<>i) then m.Lines.Add('--'+IntToStr(i)+' ID МОБА:'+IntToStr(MobsID[i])+' растояние:'+IntToStr(MobsRAS[i])+' атакует:'+VarToStr(hohodf[i])+' x:'+IntToStr(MobsX[i])+' y:'+IntToStr(MobsY[i])+' z:'+IntToStr(MobsZ[i]));
if (attackIDMinID=i) then m.Lines.Add('->'+IntToStr(i)+' ID МОБА:'+IntToStr(MobsID[i])+' растояние:'+IntToStr(MobsRAS[i])+' атакует:'+VarToStr(hohodf[i])+' x:'+IntToStr(MobsX[i])+' y:'+IntToStr(MobsY[i])+' z:'+IntToStr(MobsZ[i]));
end;
end;
end;
if (MaxHP=0) then m.Lines.Add(' ИДЕТ ЗАГРУЗКА БОТА!!! Срочно используй аптечку!!!');
end;

//************************************************** *************
procedure Free;
begin
DelALL;
end;

//************************************************** *************
procedure StatsUpdate;
var
i: integer;
begin
for i:=0 to ReadD(6)-1 do begin
case pck[i*8+10] of
#$09: CurHP:=ReadD(i*8+14);
#$0A: MaxHP:=ReadD(i*8+14);
end;
end;
if (MaxHP<>0) and (tame=false) then // вычисляем процентное соотношение хп
begin
but:=Round((MaxHP/100)*HPbutt); // при каком количестве хп юзать бутылку лечения
sud:=Round((MaxHP/100)*MEsit); // при каком количестве хп надо сесть и подкопить хп
bst:=Round((MaxHP/100)*MEup); // при каком количестве хп надо встать после отдыха
tame:=true;
end;
end;

//************************************************** *************
function rastoyanie(xpos1, ypos1, xpos2, ypos2:extended):integer; //возвращает переменную rezu которая является растоянием между 2 точками
begin
result:= Round(Sqrt(((xpos1-xpos2)*(xpos1-xpos2))+((ypos1-ypos2)*(ypos1-ypos2))));
end;

//************************************************** *************
procedure SelectT(sel:integer); //выбрать моба
begin
//MyTargetSelected
buf:=#$A6;
WriteD(sel);
WriteH(0);
SendToClientEx(Name);
end;

//************************************************** *************
procedure DelElArr(ele:integer); //удаляет моба!
begin
MobsID[ele]:=0;
MobsRAS[ele]:=0;
MobsX[ele]:=0;
MobsY[ele]:=0;
MobsZ[ele]:=0;
hohodf[ele]:=false;
end;

//************************************************** *************
procedure DelALL; //обнуляем всю базу!
begin
for i:= 1 to max do begin
NPCid[i]:=0;
MobsID[i]:=0;
MobsRAS[i]:=0;
MobsX[i]:=0;
MobsY[i]:=0;
MobsZ[i]:=0;
hohodf[i]:=false;
end;
heal:='';
HPuse:='';
spoilid:='';
MaxHP:=0;
MyZpos:=0;
cvaZ:=0;
spoil:=0;
CurHP:=0;
i:=0;
t:=0;
ID:=0;
xpos:=0;
ypos:=0;
sit:=false;
skill:=0;
MyID:=0;
HPbutt:=0;
MEsit:=0;
MEup:=0;
but:=0;
sud:=0;
bst:=0;
RADV:=0;
cvaX:=0;
attackIDMinID:=0;
attackk:=0;
attackID:=0;
cvaY:=0;
zpos:=0;
last:=0;
SummaAR:=0;
MyXpos:=0;
MyYpos:=0;
rezu:=0;
MaxX:=0;
MaxID:=0;
MinID:=0;
MinX:=0;
povtor:=false;
tame:=false;
gdo:=false;
npc:=false;
timer1.Free;
timer2.Free;
m.Free;
mlk.Free;
frm.Free;
end;

//************************************************** *************
procedure GetMinMaxX(arra:array of integer);
//возвращает в переменную MinX - мин и MaxX - макс значение массива, а в MinID, MaxID номер этого элемента
begin
MinX:=5000;
MinID:=0;
MaxX:=0;
MaxID:=0;
for i:= 1 to last do begin
if (arra[i]<=MinX) and (arra[i]<>0) then begin
MinX:=arra[i];
MinID:=i;
end;
if (arra[i]>=MaxX) then begin
MaxX:=arra[i];
MaxID:=i;
end;
end;
end;

//************************************************** *************
procedure ETOpovtor(chislo: integer; arra:array of integer);
//возвращает переменную povtor и если она равна 1 значит chislo уже есть в массиве!
begin
povtor:=false;
for t:= 1 to last do begin
if (arra[t]=chislo) then povtor:=true;
end;
end;

//************************************************** *************
procedure attackt(mobus:integer);
begin
buf:=#$04;
WriteD(MobsID[mobus]);
WriteD(MobsX[mobus]);
WriteD(MobsY[mobus]);
WriteD(MobsZ[mobus]);
WriteC(0);
SendToServerEx(Name);
end;

//************************************************** *************
procedure Summ(sum:array of integer);
//возвращает переменную SummaAR с количеством полных(не пустых) ячеек
var
Summa: integer;
begin
Summa:=0;
for i:= 1 to max do begin
if (sum[i]<>0) then inc(Summa);
end;
SummaAR:=Summa;
end;

//************************************************** *************
procedure OnTimer1(Sender: TObject); //ВЫДЕЛЕНИЕ И АТАКА МОБА!!!!!!!!!!!!!
begin
if (MinID>0) then begin
if (attackk=0) then begin
SelectT(MobsID[MinID]);
attackt(MinID);
attackID:=MobsID[MinID];
attackIDMinID:=MinID;
mlk.Lines.Add('! '+IntToStr(ID));
end;
if (attackk=5) or (attackk=20) then begin
attackt(attackIDMinID);
end;
if (spoil=1) and (skill=0) then begin
buf:=hstr('04')+IntToStr(MobsID[MinID])+IntToStr(MobsX[MinID])+IntToStr(MobsY[MinID])+IntToStr(MobsZ[MinID])+hstr('00');
spoilid:=IntToStr(MobsID[MinID])+IntToStr(MobsX[MinID])+IntToStr(MobsY[MinID])+IntToStr(MobsZ[MinID]);
SendToServerEx(Name);
buf:=hstr('2F FE 00 00 00 00 00 00 00 00'); //юзаем споил
SendToServerEx(Name);
end;
if (CurHP<but) then begin
if (HPuse<>'') then begin
buf:=HPuse;
SendToServerEx(Name);
end;
end;
Summ(hohodf);
if (CurHP<sud) and (SummaAR=0) and (sit=false) then begin
mlk.Lines.Add(' все блин я отдыхаю!');
buf:=heal;
SendToServerEx(Name);
sit:=true;
end;
if (CurHP>bst) and (sit=true) then begin
mlk.Lines.Add(' пора за работу!');
buf:=heal;
SendToServerEx(Name);
sit:=false;
end;
inc(attackk);
end;
end;

//************************************************** *************
procedure OnTimer2(Sender: TObject); //ВЫДЕЛЕНИЕ И АТАКА МОБА!!!!!!!!!!!!!
begin
//---------- вынес из основного цикла
GetMinMaxX(MobsRAS);
Summ(MobsRAS);

if (SummaAR>=round(max*0.9)) or (MaxX>5000) then begin
//если у нас занято более 90% ячеек с мобами надо удалить самых дальних от нас
mlk.Lines.Add('мусор удалён:'+IntToStr(MaxID)+' :'+IntToStr(MaxX)+' сумма'+IntToStr(SummaAR)+'-');
DelElArr(MaxID);
end;

//идем в центр если нет мобов
if (SummaAR=0) and (timer1.enabled=true) and (cvax<>0) then begin
buf:=#$01;
WriteD(cvaX);
WriteD(cvaY);
WriteD(cvaZ);
WriteD(myxpos);
WriteD(myypos);
WriteD(myzpos);
WriteD(0);
SendToServerEx(Name);
end;

playBD;
end;

//************************************************** *************
procedure AddBD(id, posx, posy, posz:integer;); //добавляем моба в базу данных
begin
// rastoyanie(MyXpos, MyYpos, posx, posy);
for i:= 1 to last do begin //перебираем базу и ищем свободную ячейку в ней
if (MobsID[i]=0) then begin //запоминаем моба в свободную ячейку
ETOpovtor(id, MobsID);
if (povtor=false) then begin
MobsID[i]:=id; //ид моба
MobsRAS[i]:=rastoyanie(MyXpos, MyYpos, posx, posy); //растояние до этого моба
MobsX[i]:=posx;
MobsY[i]:=posy;
MobsZ[i]:=posz;
mlk.Lines.Add('!-'+IntToStr(i)+'-id-'+IntToStr(MobsID[i])+'-ras-'+IntToStr(MobsRAS[i]));
// last:=i;
break;
end;
end;
end;
//если нет свободного места ищем дальше
for i:= last to max do begin //перебираем базу и ищем свободную ячейку в ней
if (MobsID[i]=0) then begin //запоминаем моба в свободную ячейку
ETOpovtor(id, MobsID);
if (povtor=false) then begin
MobsID[i]:=id; //ид моба
MobsRAS[i]:=rezu; //растояние до этого моба
MobsX[i]:=posx;
MobsY[i]:=posy;
MobsZ[i]:=posz;
mlk.Lines.Add('!-'+IntToStr(i)+'-id-'+IntToStr(MobsID[i])+'-ras-'+IntToStr(MobsRAS[i]));
last:=i;
break;
end;
end;
end;
end;

//************************************************** *************
function ISnpc(id: integer;): boolean;
begin
result:=false;
for i:= 1 to max do if (NPCid[i]=id) then result:=true;
end;

//************************************************** ****************************
// вызывается при приходе каждого пакета, если скрипт включен
//************************************************** ****************************
begin // MAIN !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//************************************************** **************************
//не обрабатываем пустые пакеты
if pck='' then exit;

//************************************************** **************************
if (ConnectName=Name) and FromServer then begin
case pck[1] of
#$76: begin
if (ReadD(2)=MyID) then begin //я юзнул какой то скилл
mlk.Lines.Add(' юзнул скилл!');
skill:=1;
end;
end;
#$0E: begin
if (MyID=ReadD(2)) then StatsUpdate; //обновление информации о хп
end;
//MagicSkillUse 48, Attack 05
#$05, #$48: begin
if (ReadD(6)=MyID) then begin
//меня ударили
sit:=false;
mlk.Lines.Add('На нас напали враги!!');
ETOpovtor(ReadD(2), MobsID); // чтоб проц не перегружать
if (povtor=false) then AddBD(ReadD(2), ReadD(15), ReadD(19), ReadD(23));
for i:= 1 to last do begin
if (MobsID[i]=ReadD(2)) then begin //если моб записан в базе данных
mlk.Lines.Add('Атакую!!!'+IntToStr(i)+'-'+IntToStr(attackIDMinID));
MobsRAS[i]:=1;
hohodf[i]:=true; // стал агрессор
if (timer1.enabled=false) then begin //если я только зашел в игру и на меня напали
attackIDMinID:=i;
timer1.enabled:=true;
end;
if (attackIDMinID<>0) and (hohodf[attackIDMinID]=false) then attackIDMinID:=i;
break;
end;
end;
end;
end;
#$0C: begin
if (MyXpos<>0) then begin
//rastoyanie(MyXpos, MyYpos, ReadD(14), ReadD(18));
if (rastoyanie(MyXpos, MyYpos, ReadD(14), ReadD(18))<=200) then begin
mlk.Lines.Add('Выпала вещь!!!');
timer1.enabled:=false;
buf:=#$04;
WriteD(ReadD(6));
WriteD(ReadD(14));
WriteD(ReadD(18));
WriteD(ReadD(22));
WriteC(0);
SendToServerEx(Name);
mlk.Lines.Add(' Пробую поднять!!!');
delay(1000);
timer1.enabled:=true;
end;
end;
end;
#$04: begin
//пакет с инфой о моём чаре
i:=2;
MyXpos:=ReadD(i); //получаю координату х моего чара
MyYpos:=ReadD(i); //получаю координату у моего чара
MyZpos:=ReadD(i); //получаю координату z моего чара
//Запоминаем ИД
i:=18;
MyID:=ReadD(i); //получаю ид моего чара
//смещение переменное, зависит от имени (LenName*2+2)
i:=i+(Length(Name)*2+2)+48; //44 для С4
MaxHP:=ReadD(i);
CurHP:=ReadD(i);
if (gdo=false) then begin // задаем центр окружности кача
cvaX:=MyXpos;
cvaY:=MyYpos;
gdo:=true;
end;
end;
#$01: begin
if (MyID<>0) and (ReadD(2)<>MyID) then begin//если на серваке кто-то перемещается
i:=2;
ID:=ReadD(i); //кто-то рыпнулся с места надо это записать...
xpos:=ReadD(i);
ypos:=ReadD(i);
zpos:=ReadD(i);
//rastoyanie(cvaX, cvaY, xpos, ypos);
if not ISnpc(ID) and (rastoyanie(cvaX, cvaY, xpos, ypos)<=RADV) then AddBD(ID, xpos, ypos, zpos);
end;
end;
//принят пакет Die
//принят пакет DeleteObject , #$12
#$06: begin
//моб сдох! выкидываем его из базы and (attackID=ReadD(2))
if (pck[22]=#$01) then begin
mlk.Lines.Add(' свипаю!');
buf:=hstr('04')+spoilid+hstr('00');
SendToServerEx(Name);
buf:=hstr('2F 2A 00 00 00 00 00 00 00 00');
SendToServerEx(Name);
spoilid:='';
//// mlk.Lines.Add(' ТОРМОЗ! ОН УМЕР!!!');
//delay(700);
end;
for i:= 1 to last do begin
if (MobsID[i]=ReadD(2)) then begin
skill:=0;
DelElArr(i);
attackk:=0;
mlk.Lines.Add('БОБИК СДОХ!! :'+IntToStr(i));
//// mlk.Lines.Add(' ТОРМОЗ! внатуре умер!!!');
// delay(100);
if (i=last) and (last<>1) then dec(last);
break;
end;
end;
end;
#$03: begin
if (MyID<>0) and (ReadD(2)<>MyID) then begin //если это не я
for i:= last to max do begin
if (NPCid[i]=0) then begin
ETOpovtor(ReadD(18), NPCid);
if (povtor=false) then begin
NPCid[i]:=ReadD(18);
mlk.Lines.Add('ИГРОК ДОБАВЛЕН!-'+IntToStr(i)+'--'+IntToStr(NPCid[i]));
break;
end;
end;
end;
end;
end;
#$16: begin
if (MyID<>0) and (ReadD(2)<>MyID) then begin //если это не я
mlk.Lines.Add('Вижу NPC!');
if (ReadD(10)=0) then begin //если нельзя атаковать
for i:= last to max do begin
if (NPCid[i]=0) then begin
ETOpovtor(ReadD(2), NPCid);
if (povtor=false) then begin
NPCid[i]:=ReadD(2);
mlk.Lines.Add(' Запомнили, что NPCid='+IntToStr(ReadD(2))+' нельзя атаковать!');
break;
end;
end;
end;
end;
if (ReadD(10)=1) and (pck[120]=#$00) then begin //если можно атаковать
// rastoyanie(cvaX, cvaY, ReadD(14), ReadD(18));
// if (rezu<=RADV)
// then begin
AddBD(ReadD(2), ReadD(14), ReadD(18), ReadD(22));
// mlk.Lines.Add(' NPCid='+IntToStr(ReadD(2))+' запомнили в базе!');
// end else mlk.Lines.Add(' NPCid='+IntToStr(ReadD(2))+' вне радиуса действия!');
end;
end;
end;
end;
end;

//************************************************** **************************
if (ConnectName=Name) and FromClient then begin
case pck[1] of
#$14: begin
if (HPuse='') then begin // была использованная какая то вещь предположительно бутылка хп
HPuse:=pck;
mlk.Lines.Add('ID бутылок записан в BD:'+HPuse);
end;
end;
#$1B: begin
case ReadD(2) of
//социальное действие Yes для начала затачивания
6: begin
cvaX:=MyXpos;
cvaY:=MyYpos;
cvaZ:=MyZpos;
attackk:=0;
mlk.Lines.Add('! БОТ ВКЛЮЧЕН координаты ОБНОВЛЕНЫ!!');
timer1.enabled:=true;
end;
//социальное действие No для окончания
5: begin
timer1.enabled:=false;
mlk.Lines.Add('! БОТ ВЫКЛЮЧЕН!!!');
end;
//социальное действие Applaud
11: begin
if timer2.enabled=false
then timer2.enabled:=true
else timer2.enabled:=false;
attackk:=0;
mlk.Lines.Add('! ВКЛ/ВЫКЛ!!!');
end;
end;
end;
//ValidatePosition пакет от клиента с моими кординатами
#$48: begin
//обновляем ВСЕ растояния в BD если мы сошли с места
MyXpos:=ReadD(2); //получаю координату х моего чара
MyYpos:=ReadD(6); //получаю координату у моего чара
MyZpos:=ReadD(10); //получаю координату z моего чара
for i:= 1 to last do begin
if (MobsID[i]<>0) then begin
if (true<>hohodf[i]) then begin
//rastoyanie(MyXpos, MyYpos, MobsX[i], MobsY[i]);
MobsRAS[i]:=rastoyanie(MyXpos, MyYpos, MobsX[i], MobsY[i]);
end;
end;
end;
end;
end;
end;
end. // END MAIN

ЗЫЖ
Мне будет интересно посмотреть твой скрипт!
ЗЗЫЖ
Исправил критическую ошибку с расчетом расстояний

QaK
09.01.2008, 13:26
По поводу оптимизации: //обновляем ВСЕ растояния в BD если мы сошли с места
проще высчитать приращение "Моих" координат и соответственно добавить эти приращения ко всем координатам.
Массивы для хранения данных можно сделать динамическими типа
array of integer;
Установить длину массива:
SetLength(mas,length);
достум к элементам так же
mas[i]:=...
длина массива (ака переменная last)
length(mas);
Воть ...
З.Ы. skymanrus, молодец,мо-ло-дец, далеко пойдешь :)

xkor
20.01.2008, 15:54
длина массива (ака переменная last)
length(mas);
недумаю что length(mas) будет работать, length применяется вроде тока к строкам, функции для узнавания длинны массива я в фаст скрипте ненашел %)
а в остальном присоединяюсь к твоим советам)

QaK
21.01.2008, 12:55
А чем тебе string не динамический массив символов? :oops: =) Функция Length - дляна динамического массива, любого, и в Пакетхаке тож норм работает для любых array of <любой тип>.

vovanchik
27.01.2009, 19:57
недумаю что length(mas

одномерный норм работает, а вот двумерный что-то немогу сообразить.
вот так не пашет:
massivko: array of array of string; // мать его!!!

QaK
27.01.2009, 20:04
vovanchik, в скритах динамический 2х и более мерныйф массив не пашет.

NLObP
27.01.2009, 20:04
А если просто в два раза больше места занимать?

ERASE
27.01.2009, 20:15
massivko: array of array of string; // мать его!!!

Ээээм... Массив Массивов строк? оО Омг...

Двумерный - это матрица, а не вложенный, то есть...

massivko: array [1..3, 1..3] of string; //массив из 3х столбцов и 3х строк (содержимое - строки)

Может, ты имел что-то другое ввиду? Я мог не понять... :)

Про динамический не шарю...

Добавлено через 6 минут
в скритах динамический 2х и более мерныйф массив не пашет.

Почему? :( И будет ли пахать когда-нить?

ЗЫ. а статический?.. :)

vovanchik
27.01.2009, 20:30
о каком ускорении скрипта может идти реч если в скрипте каждый раз считывается (to ReadD(6)-1 do) кол-во итераций. Для ускорения рекомендую в итерации указывать конкретную переменну с уже извеснтным значением.

Добавлено через 33 секунды
Почему? И будет ли пахать когда-нить?

ЗЫ. а статический?..
Видать человеку поговорить нескем :)

Добавлено через 3 минуты
Может, ты имел что-то другое ввиду? Я мог не понять...
:) именно так создаётся динамический двумерный массив в паскале :), ну по крайней мере в Delphi

kuchka_hlama: array of array of string;

setlength(kuchka_hlama,length(kuchka_hlama)+1); //увеличение масива на 1

теперь у массива есть kuchka_hlama[0,0]

Добавлено через 7 минут
в скритах динамический 2х и более мерныйф массив не пашет.
а то что не пашет я уже понил :))) просто думал есть соображения.

vovanchik
27.01.2009, 20:31
А если просто в два раза больше места занимать?
на обработку масса лишнего проц времени уйдёт :) или проще говоря труднее оперировать

ERASE
27.01.2009, 20:32
Цитата:
Сообщение от ERASE
Почему? И будет ли пахать когда-нить?

ЗЫ. а статический?..

Видать человеку поговорить нескем

Нет, просто сейчас пишу скрипт, в нем в будущем надо будет кое-что прикрутить. Так вот это "кое-что" будет основано на динамическом двумерном массиве. Поэтому и спрашиваю. :)


Цитата:
Сообщение от ERASE
Может, ты имел что-то другое ввиду? Я мог не понять...

именно так создаётся динамический двумерный массив в паскале , ну по крайней мере в Delphi

kuchka_hlama: array of array of string;

setlength(kuchka_hlama,length(kuchka_hlama)+1); //увеличение масива на 1

теперь у массива есть kuchka_hlama[0,0]

Ну я ж говорю, про динамический не знаю, статический точно -

mas:array [1..n,1..n] of string;

alexsl
29.01.2009, 09:19
может поможет тебе,
только что наваял плагинчик:

// ************************************************** ***************************
// plugin для работы с БД
// alexsl / 29.01.09
// ************************************************** ***************************
library dbhelper;
// --- закоментить если компилируется под Delphi 2007 +
{$define ShareMM}
{$define AttemptToUseSharedMM}
// -----------------------------
{.$define RELEASE} // для совместимости с релизом пакетхака, при дебуге можно закоментировать
{$define DBDebug} //

uses
FastMM4,
SysUtils,
Windows,
Variants,
Dialogs,
Coding,
classes;


type
TL2Obj = class
private
FX: integer;
FID: integer;
FZ: integer;
FY: integer;
procedure SetID(const Value: integer);
procedure SetX(const Value: integer);
procedure SetY(const Value: integer);
procedure SetZ(const Value: integer);
public
property ID: integer read FID write SetID;
property X: integer read FX write SetX;
property Y: integer read FY write SetY;
property Z: integer read FZ write SetZ;
end;

TL2World = class
private
function GetCount: integer;
protected
FLIst: TLIst;
function GetOrCreate(AObjID: integer): TL2Obj;
function Get(AObjID: integer): TL2Obj;
public
constructor Create;
destructor Destroy; override;
property Count: integer read GetCount;
procedure Clear;
procedure Add(AObjID,AX,AY,AZ: integer);
procedure Move(AObjID,AX,AY,AZ: integer);
procedure Delete(AObjID: integer);
function Dist(FromObjID,ToObjID: integer): integer;
function DistEx(FromObjID,AX,AY,AZ: integer): integer;
// возвр. ближ. объект
function GetMinDistObj(AX,AY,AZ: integer): integer;
// возвр. ближ. объект в указанном Радиусе
function GetMinDistObjEx(AX,AY,AZ,Radius: integer): integer;
end;

var {version} {revision}
min_ver_a: array[0..3] of Byte = ( 3,4,1, 0 );
min_ver: Integer absolute min_ver_a; // минимальная поддерживаемая версия программы
ps: TPluginStruct;
// ppck: PPacket;
db: TL2World;


function GetPluginInfo(const ver: Integer): PChar; stdcall;
begin
if ver<min_ver then
Result:='Plugin к программе l2phx'+sLineBreak+
'Для версий 3.4.1+'+sLineBreak+
'У вас старая версия программы! Плагин не сможет корректно с ней работать!'
else
Result:='Plugin к программе l2phx'+sLineBreak+
'Для версий 3.4.1+'+sLineBreak+
'DB Helper (alexsl)';
end;

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

// Необязательно вызываемая функция. (может отсутствовать в плагине)
// Вызывается при выгрузке плагине
procedure OnFree; stdcall;
begin
if assigned(db) then
try
db.Free;
except
{$IFDEF DBDebug}
raise;
{$ENDIF}
end;
end;

// Необязательно вызываемая функция. (может отсутствовать в плагине)
// Вызывается при загрузке плагине
procedure OnLoad; stdcall;
begin
db := TL2World.Create;
end;

// Необязательно вызываемая функция. (может отсутствовать в плагине)
// Вызывается при вызове скриптовой функции обьявленной в RefreshPrecompile
function OnCallMethod(const MethodName: String; // имя функции в верхнем регистре
var Params, // параметры функции
FuncResult: Variant // результат функции
): Boolean; stdcall; // если вернёт True то дальнейшая
// обработка функции прекратиться
begin
Result:=False; // передаём обработку функции программе
if MethodName='DB_COUNT' then begin
Result:=True; // запрещаем дальнейшую обработку функции в программе
FuncResult:=db.Count;
end
else
if MethodName='DB_CLEAR' then begin
Result:=True; // запрещаем дальнейшую обработку функции в программе
db.Clear;
end
else
// добавить объект в базу
if MethodName='DB_ADD' then begin
Result:=True; // запрещаем дальнейшую обработку функции в программе
try
// ObjID, X, Y,Z
db.Add(Params[0],Params[1],params[2],params[3]);
except
{$IFDEF DBDebug}
raise;
{$ENDIF}
end;
end
else
// объект удален
if MethodName='DB_DELETE' then begin
Result:=True; // запрещаем дальнейшую обработку функции в программе
try
db.Delete(Params[0]);
except
{$IFDEF DBDebug}
raise;
{$ENDIF}
end;
end
else
// объект двигается, если нету в БД то создается автоматически
if MethodName='DB_MOVE' then begin
Result:=True; // запрещаем дальнейшую обработку функции в программе
try
db.Move(Params[0],Params[1],params[2],params[3]);
except
{$IFDEF DBDebug}
raise;
{$ENDIF}
end;
end
else
// растояние между объектами, если нет объекта/ов возвр. -1
if MethodName='DB_DIST' then begin
Result:=True; // запрещаем дальнейшую обработку функции в программе
try
// FromObjID, ToObjID
FuncResult:=db.Dist(Params[0],Params[1]);
except
{$IFDEF DBDebug}
raise;
{$ENDIF}
end;
end
else
// растояние между объектом и координатами
if MethodName='DB_DISTEX' then begin
Result:=True; // запрещаем дальнейшую обработку функции в программе
try
// ObjID, X,Y,Z
FuncResult:=db.DistEx(Params[0],Params[1],Params[2],Params[3]);
except
{$IFDEF DBDebug}
raise;
{$ENDIF}
end;
end
else
// возвр. ИД ближайщего объекта от заданных координат
// или -1 если нету
if MethodName='DB_MINDIST' then begin
Result:=True;
try
// X,Y,Z
FuncResult:=db.GetMinDistObj(Params[0],Params[1],Params[2]);
except
{$IFDEF DBDebug}
raise;
{$ENDIF}
end;
end
else
// возвр. ИД ближайщего объекта от заданных координат с учетом Радиуса
// или -1 если нету
if MethodName='DB_MINDISTEX' then begin
Result:=True;
try
// X,Y,Z, Radius
FuncResult:=db.GetMinDistObjEx(Params[0],Params[1],Params[2],Params[3]);
except
{$IFDEF DBDebug}
raise;
{$ENDIF}
end;
end;
end;


{ TL2World }

procedure TL2World.Add(AObjID, AX, AY, AZ: integer);
var
obj: TL2Obj;
begin
obj := TL2Obj.Create;
FLIst.Add(obj);
obj.ID:=AObjID;
obj.X:=AX;
obj.Y:=AY;
obj.Z:=AZ;
end;

procedure TL2World.Clear;
var
i: integer;
begin
for i:= FLIst.Count-1 downto 0 do
try
TL2Obj(FList[i]).Free;
FList.Delete(i);
except
{$IFDEF DBDebug}
raise;
{$ENDIF}
end;
end;

constructor TL2World.Create;
begin
FList:=TList.Create;
end;

procedure TL2World.Delete(AObjID: integer);
var
i: integer;
begin
for i:= FLIst.Count-1 downto 0 do
if TL2Obj(FList[i]).ID = AObjID then
try
TL2Obj(FList[i]).Free;
FList.Delete(i);
except
{$IFDEF DBDebug}
raise;
{$ENDIF}
end;
end;

destructor TL2World.Destroy;
begin
FList.free;
inherited;
end;

function TL2World.Dist(FromObjID, ToObjID: integer): integer;
begin
result := -1;
if assigned(Get(FromObjID)) and assigned(Get(ToObjID)) then
try
result := round(sqrt(Get(FromObjID).X-Get(ToObjID).X)+sqrt(Get(FromObjID).Y-Get(ToObjID).Y));
except
{$IFDEF DBDebug}
raise;
{$ENDIF}
end;
end;

function TL2World.DistEx(FromObjID, AX, AY, AZ: integer): integer;
begin
result := -1;
if assigned(Get(FromObjID)) then
try
result := round(sqrt(Get(FromObjID).X-AX)+sqrt(Get(FromObjID).Y-AY));
except
{$IFDEF DBDebug}
raise;
{$ENDIF}
end;
end;

function TL2World.Get(AObjID: integer): TL2Obj;
var
i: integer;
begin
result := nil;
for i:= FList.Count-1 downto 0 do
if TL2Obj(FList[i]).ID=AObjID then
begin
result := TL2Obj(FList[i]);
exit;
end;
end;

function TL2World.GetCount: integer;
begin
result := FList.Count;
end;

function TL2World.GetOrCreate(AObjID: integer): TL2Obj;
var
i: integer;
begin
for i:= FList.Count-1 downto 0 do
if TL2Obj(FList[i]).ID=AObjID then
begin
result := TL2Obj(FList[i]);
exit;
end;
result := TL2Obj.Create;
result.ID:=AObjID;
end;

function TL2World.GetMinDistObj(AX, AY, AZ: integer): integer;
var
i,dst: integer;
begin
result:=-1;
if count<=0 then
exit;

dst:=DistEx(0,AX,AY,AZ);
result:=TL2Obj(FList[0]).ID;

for i:=FList.Count-1 downto 0 do
begin
if DistEx(i,AX,AY,AZ)<=dst then
begin
result:=TL2Obj(FList[i]).ID;
dst:=DistEx(0,AX,AY,AZ);
end;
end;
end;

procedure TL2World.Move(AObjID, AX, AY, AZ: integer);
var
obj: TL2Obj;
begin
obj := GetOrCreate(AObjID);
obj.X:=AX;
obj.Y:=AY;
obj.Z:=AZ;
end;

function TL2World.GetMinDistObjEx(AX, AY, AZ, Radius: integer): integer;
var
id: integer;
begin
result := -1;
id:=GetMinDistObj(AX,AY,AZ);

if id=-1 then
exit;

if DistEx(id,AX,AY,AZ)>Radius then
result := -1;
end;

{ TL2Obj }

procedure TL2Obj.SetID(const Value: integer);
begin
FID := Value;
end;

procedure TL2Obj.SetX(const Value: integer);
begin
FX := Value;
end;

procedure TL2Obj.SetY(const Value: integer);
begin
FY := Value;
end;

procedure TL2Obj.SetZ(const Value: integer);
begin
FZ := Value;
end;

exports
GetPluginInfo,
SetStruct,
OnCallMethod,
onLoad,
onFree;

begin
end.


зы: еще не тестил :) но думаю будет работать
зыы: компилировал под D7