PDA

Просмотр полной версии : написал скрипт, а он как всегда


supernewbie
28.08.2010, 16:42
скажите, что не так в нем, написал как мог, и он даже работает (!!!!!!), но жуткие тормаза при его работе.

что же тут не так?(

alexteam
28.08.2010, 16:45
что же тут не так?(
копетан очевидность отвечает:

написал как мог

supernewbie
28.08.2010, 16:48
ну ты все же глянь)

J-Fobos
28.08.2010, 17:12
многа букаф и ноль коментов )) хз найдется ли герой который разберет это все :D

alexteam
28.08.2010, 17:33
переименовал тему.
так лучше.

supernewbie
28.08.2010, 17:46
ахахах)))))

QaK
28.08.2010, 20:23
Копетан очевидность утверждает: 18 массивов по 1500 элементов - это не есть гуд для быстродействия.

supernewbie
28.08.2010, 20:31
это ясно, но юзается только 1 или 2 фактически

//J-Fobos: тогда нужно 1 или 2 объявлять...

Breadfan
28.08.2010, 20:42
Да только в этом блоке charid[o]:=idchar;
charname[o]:=namechar;
clanchar[o]:=ReadD(310 + (length(namechar) * 2 + 2) + (length(titlechar) * 2 + 2));
charx[o]:=ReadD(2);
chary[o]:=ReadD(6);
charz[o]:=ReadD(10);
profa[o]:=ReadD(30 + (length(namechar) * 2 + 2));
chardead[o]:=ReadC(333 + (length(namechar) * 2 + 2) + (length(titlechar) * 2 + 2)); уже задействованы 8 таких массивов. Причем работает так: приходит char info ("if fromserver and (connectname=name) and (pck[1]=#$31) then") - и значит начнем цикл в 1,5к (!!!) повторений. Это при приходе КАЖДОГО чаринфо пакета...а сколько их там бегает постоянно туда-сюда? То же самое при удалении объекта случается...Фактически выходит что почти в любой момент времени у тебя будет крутиться один из таких вот 1,5к циклов. Можно немного жизнь облегчить используя переменную для хранения "потолкового" значения "о", и использовать вместо "for o:=1 to 1500 do" какойнть "for o:=1 to max do", но это все равно не лучший выход по-моему

ЗЫ: кстати: а чего скрипт вообще должен делать? Судя по блоку объявлений переменных - хантер-бот какой-то получается, для охоты на варов.

supernewbie
28.08.2010, 21:05
в чем разница между for o:=1 to max do и for o:=1 to 1500 do ?
как вообще реализуются такие массивы

Breadfan
28.08.2010, 23:17
Часть первая:const
MyFileName = 'c:\myfile.txt';
Var
name, CharNick, CharTitle, idx:string;
CharName, ProfName, ProfList: TStringList;
tmp, CharOID, CharClassID, CharClan, MyOID:integer;
charX, charY,charZ:integer;
function GetValue(ValName: string): string;
begin
result:=CharName.Values[ValName];
end;
function GetProf(ValName:string): string;
begin
result:=ProfName.Values[ValName];
end;
procedure SetValue(ValName: string; Value: string);
begin
CharName.Values[ValName]:=Value;
end;
procedure Init; //Вызывается при включении скрипта
var
i:integer;
begin
CharName:=TStringList.Create;
try
CharName.LoadFromFile(MyFileName);
except
end;
ProfList:=TStringList.Create;
ProfName:=TStringList.Create;
try
ProfName.LoadFromFile('classid.ini');
except
SendMsg('classid.ini не найден!');
exit;
end;
MyOID:=0;
end;
procedure Free;
begin
CharName.Clear;
CharName.Free;
CharName.SaveToFile(MyFileName);
end;

begin
if fromserver and (pck[1]=#$31) then begin
idx:=StrtoHex(pck[18])+StrtoHex(pck[19])+StrtoHex(pck[20])+StrtoHex(pck[21]);
name:='OID: '+idx;
tmp:=18;
CharOID:=ReadD(tmp);
if ((GetValue(Name))='') then begin
CharX:=ReadD(2);
CharY:=ReadD(6);
CharZ:=ReadD(10);
CharNick:=ReadS(tmp);
ReadD(tmp);
ReadD(tmp);
CharClassId:=ReadD(tmp);
tmp:=tmp+276;
CharTitle:=ReadS(tmp);
CharClan:=ReadD(tmp);
name:='OID: '+idx;
SetValue(name,((CharNick)));
name:='Профессия основы: '+idx;
SetValue(name,(GetProf(inttostr(CharClassId))));
name:='Клан: '+idx;
SetValue(name,(inttostr(CharClan))); //тут значение вар\не вар прикрутить стоит
name:='Титул: '+idx;
SetValue(name,(CharTitle));
name:='CoordX: '+idx;
SetValue(name,(inttostr(CharX)));
name:='CoordY: '+idx;
SetValue(name,(inttostr(CharY)));
name:='CoordZ: '+idx;
SetValue(name,(inttostr(CharZ)));
CharName.SaveToFile(MyFileName);
end else begin
idx:=StrtoHex(pck[18])+StrtoHex(pck[19])+StrtoHex(pck[20])+StrtoHex(pck[21]);
name:='OID: '+idx;
If (GetValue(name)<>'') then begin
SendMsg('Ник: '+GetValue(name));
name:='Профессия основы: '+idx;
SendMsg('Профа: '+GetValue(name));
name:='Клан: '+idx;
SendMsg('Клан ИД: '+GetValue(name));
name:='Титул: '+idx;
if ((GetValue(name))<>'') then SendMsg('Титул: '+GetValue(name));
end;
end;
end;
if fromserver and (pck[1]=#$2F) then begin // and ((ReadD(2))<>MyOID)
idx:=StrtoHex(pck[2])+StrtoHex(pck[3])+StrtoHex(pck[4])+StrtoHex(pck[5]);
CharOID:=ReadD(2);
CharX:=ReadD(6);
CharY:=ReadD(10);
CharZ:=ReadD(14);
if ((GetValue('OID: '+idx))<>'') and (CharOID<>MyOID) and (MyOID<>0) then begin
try
name:='CoordX: '+idx;
SetValue(name,(inttostr(CharX)));
name:='CoordY: '+idx;
SetValue(name,(inttostr(CharY)));
name:='CoordZ: '+idx;
SetValue(name,(inttostr(CharZ)));
CharName.SaveToFile(MyFileName);
except
end;
end;
If (CharOID<>MyOID) and ((GetValue('OID: '+idx))<>'')then begin
SendMsg('Перс '+GetValue('OID: '+idx)+' бежит в X:'+GetValue('CoordX: '+idx)+' Y:'+GetValue('CoordY: '+idx)+' Z:'+GetValue('CoordZ: '+idx)+);
end else begin
If (CharOID=MyOID) then begin
SendMsg('Вы бежите в X:'+inttostr(CharX)+' Y:'+inttostr(CharY)+' Z:'+inttostr(CharZ));
end;
end;
end;
// end of part I (продолжение ниже)
После отключения скрипта - файл-лог очищается.

QaK
28.08.2010, 23:57
supernewbie, тебя чем одномерные динамические массивы неустраивают?

Breadfan
29.08.2010, 04:31
Часть вторая (продолжение, т.к. в один пост - не влез)://Start Part II
if fromserver and (pck[1]=#$08) then begin
idx:=StrtoHex(pck[2])+StrtoHex(pck[3])+StrtoHex(pck[4])+StrtoHex(pck[5]);
try
name:='OID: '+idx;
SendMsg('Удаляем '+GetValue(name));
CharName.Delete(CharName.IndexOfName(name));
name:='Профессия основы: '+idx;
CharName.Delete(CharName.IndexOfName(name));
name:='Клан: '+idx;
CharName.Delete(CharName.IndexOfName(name));
name:='Титул: '+idx;
CharName.Delete(CharName.IndexOfName(name));
name:='CoordX: '+idx;
CharName.Delete(CharName.IndexOfName(name));
name:='CoordY: '+idx;
CharName.Delete(CharName.IndexOfName(name));
name:='CoordZ: '+idx;
CharName.Delete(CharName.IndexOfName(name));
CharName.SaveToFile(MyFileName);
except
end;
//end;
end;
if fromserver and (pck[1]=#$32) and (MyOID<>ReadD(18)) then MyOID:=ReadD(18);
if fromserver and (pck[1]=#$22) and (MyOID=ReadD(2)) then begin //При приходе пакета
SendMsg('Очистка лога'); // TeleportToLocation - полная очистка лога
CharName.Clear; //для избавления от "хвостов"
CharName.SaveToFile(MyFileName);
end;
end.

Вдогонку:

Такого рода лог ведется: OID: C87D2048=Атилла
Профессия основы: C87D2048=Sword Muse
Клан: C87D2048=35
Титул: C87D2048=@
CoordX: C87D2048=146443
CoordY: C87D2048=-56114
CoordZ: C87D2048=-2776
OID: E56D4148=Stoum
Профессия основы: E56D4148=Warlock
Клан: E56D4148=103
Титул: E56D4148=Kamikaze team
CoordX: E56D4148=147838
CoordY: E56D4148=-55370
CoordZ: E56D4148=-2728 Формат лога: <Параметр>: <ОИД перса, которому принадлежит> = <значение параметра>. Онлайн сервера - 1к примерно (с торговыми ботами) - по гирану бег без лагов. Еслиб знать на кой ляд оно вообще надо - ТЗ так сказать, иметь - было бы легче.

supernewbie
29.08.2010, 06:32
а как ведется удаление\замена в этом логе?

Добавлено через 14 минут
при прогрузе начинается жуткий пиздец)

Breadfan
29.08.2010, 07:27
Удаление как раз в Part II находится, имена строк имеют ОИД перса, к которому они относятся, так что удаление\обновление - не проблема. Проблема то, что в логе после удаления периодически остаются хвосты вида CoordX: 99FB1048=149103
CoordY: 99FB1048=-55485
CoordZ: 99FB1048=-2760
CoordX: 3E281048=81310
CoordY: 3E281048=148034
CoordZ: 3E281048=-3464
CoordX: 3C281048=81248
CoordY: 3C281048=147949
CoordZ: 3C281048=-3464
CoordX: 1D281048=81676
CoordY: 1D281048=147906
CoordZ: 1D281048=-3464
CoordX: F1271048=81707
CoordY: F1271048=148007
CoordZ: F1271048=-3464
CoordX: 2FDE1048=83405
CoordY: 2FDE1048=148008
CoordZ: 2FDE1048=-3431
CoordX: 88F81048=82441
CoordY: 88F81048=147907
CoordZ: 88F81048=-3464
CoordX: 46E41048=82259
CoordY: 46E41048=147641
CoordZ: 46E41048=-3464
CoordX: 83CA1048=82346
CoordY: 83CA1048=147632 - без понятия чего это оно так (может быть не стоит постоянно вызывать сохранение StringList'а в файл), поставил дополнительную очистку лога при ТП, как временную меру....а там как руки дойдут/
Насчет флага вар\не вар - немного сложнее - в том клане варлист - пустой :D Наугад не смогу сделать. Вывод в лог сообщний SendMsg - на мой взгляд - лучше будет закомментировать.

supernewbie
29.08.2010, 08:23
че-то я не понимаю, как найти ник по иду в этом листе?

if fromserver and (pck[1]=#$B9) then SendMsg('У вас на таргете: '+GetValue(idx)); так не работает\

Breadfan
29.08.2010, 08:38
Перед последним end. - вставь

if fromserver and (pck[1]=#$B9) then begin
idx:=StrtoHex(pck[2])+StrtoHex(pck[3])+StrtoHex(pck[4])+StrtoHex(pck[5]);
name:='OID: '+idx;
SendMsg('В таргете '+GetValue(name));
end;

idx - "индекс" - это ОИД - только записаный наоборот, как в пакете, просто начинал с использования лишь 3ех байт, 4ый появился позже, а переделывать - пока лень, вот и все. Вполне возможно заменить к привычной форме idx:=inttostr(ReadD(j)); - только менять надо сразу по всему скрипту.

supernewbie
29.08.2010, 09:12
а) я поняяял)

mira
29.08.2010, 10:44
в чем разница между for o:=1 to max do и for o:=1 to 1500 do ?
как вообще реализуются такие массивы
моя реализация :
creatures - массив структур хранящих чаров
pciA-пакет чаринфо (если точнее его кусок)
bnew булево - чар уже имеетса в массиве или нет?
lastfree - индекс последней "дырки" образвовашейся по objectdelete
по возможности будем повторно использовать дырки если их нехватит то увеличим l2_maxcreatures (максимальный индекс используемый в массиве)
и добавим сверх



n:=0;
lastfree:=-1;
index:=-1;
mc:=ClientHeader.l2_maxcreatures;
while (n<mc) do begin // перебор масива от 0 до потолкового индекса
if creatures[n].ID=pciA.ID then begin
index:=n; // если такой както уже оказалса в массиве заканчиваем
bNew:=false;
break;
end;
if creatures[n].ID=0 then lastfree:=n; // опа "дырка"! запоминаем...
inc(n);
end;
if (index= -1)then begin //ничего не нашли? пробуем использовать "дырку"
index:=lastfree;
end;
if (index= -1)then begin { и дырки тоже нет? че делать
увеличиваем массив... и дописываем новую запись на вершину увеличив потолок}
index:=mc;
inc(ClientHeader.l2_maxcreatures);
end;

тут возможнв процедуры дефрагментации чтобы скинуть потолковое значение и код прилизать поидее.
у меня тормозов никаких нет правдо это выполняет RTL программы а не ФС
скрипт он хоть и фаст но он всеже скрипт )))

supernewbie
29.08.2010, 11:21
а вот эти точки и нижние отступы это имя массива или что-то еще?

Breadfan
29.08.2010, 22:40
Supernewbie: давно надо было привыкнуть что mira не в Phx пишет, он тебе лишь путь обозначивает, а не дает готовый скрипт для Phx

mira
30.08.2010, 09:49
ага всеголиш скопипастил код из проги показать пример. Да разница небольшая с пх тока пакеты ловятса в клиенте. Фс оптимизирован и реализует тока высокоуровневую логику бота разборы пакетов и управление масивами выполняет rtl программы.

Fer123
30.08.2010, 12:28
Вот мой вариант ведения базы с использованием TStringList и свойства CommaText. Это только для примера поэтому в базу записывается только имя, координаты и профа.

const
characterName='ArchDevil';
var
CharData,CharInfo : TStringList;
CharDataIndex : integer;
procedure Init; //Вызывается при включении скрипта
begin
UseForConnectName := characterName;
CharData:=TStringList.Create;
CharInfo:=TStringList.Create;
end;

procedure Free; //Вызывается при выключении скрипта
begin
CharData.Free;
CharInfo.Free;
end;

Procedure ShowData;
var i:integer;
begin
SendMsg('==============================');
for i:=0 to CharData.Count-1 do SendMsg(CharData[i]);
end;

//основная часть скрипта
//вызывается при приходе каждого пакета если скрипт включен
begin
if FromServer then
case pck[1] of
#$31: //char info. dobovlenie v bazy charov ili obnovlenie esli uzhe est'
begin
CharDataIndex:=CharData.IndexOfName(inttostr(ReadD (18)));
if CharDataIndex=-1 then //Esli -1 znach net v baze. ',' - simvol razdeleniya. Zanositsa v formate 0bjid=name, x, y, z, profa
CharData.Add(Format('%d=%s, %d, %d, %d, %d',[ReadD(18),ReadS(22),ReadD(2),ReadD(6),ReadD(10),Re adD(32+length(ReadS(22))*2)])) //dobovlenie v bazu
else
CharData[CharDataIndex]:=Format('%d=%s, %d, %d, %d, %d',[ReadD(18),ReadS(22),ReadD(2),ReadD(6),ReadD(10),Re adD(32+length(ReadS(22))*2)]); //obnovlenie
end;
#$2F: //obnovlenie coordinat charov s paketa movetolocation
begin
CharDataIndex:=CharData.IndexOfName(inttostr(ReadD (2)));
if CharDataIndex=-1 then exit //net v baze
else
begin
CharInfo.Clear; //commatext razlazhivaet stroky s simvolami ','
CharInfo.CommaText:=CharData.Values[inttostr(ReadD(2))]; //CharInfo[0]=Name CharInfo[1]=x
CharInfo[1]:=inttostr(ReadD(6)); //x //CharInfo[2]=y Charinfo[3]=z
CharInfo[2]:=inttostr(ReadD(10)); //y //CharInfo[4]=profa
CharInfo[3]:=inttostr(ReadD(14)); //z
CharData[CharDataIndex]:=inttostr(ReadD(2))+'='+CharInfo.CommaText; //posle obnovleniya obratno slazhivaem stroky i obnovlyaem v CharData
end;
end;
#$08: //Delete obj
begin
CharDataIndex:=CharData.IndexOfName(inttostr(ReadD (2)));
if CharDataIndex=-1 then exit else CharData.Delete(CharDataIndex);
end;
end;

if FromClient then //vivod bazi cherez SendMsg() pri socialnom deistvii
case pck[1] of
#$56: ShowData;
end;
end.