маленькая лепта в скриптоводстве, возможно кому-нибудь понадобится.
что делает:
- автоматически записывает в файл маршрут следования.
- можно загрузить данные пути из файла
- передвигается по маршруту.
Для начала, нужно создать маршрут(ы), запись происходит так:
1. соц. действ. Да - начать запись
2 соц. действ. Нет - остановить.
(записывает в файл все события от клиента на движение юзера, событе мув))
=== вот примерная структкра файла (x,y,z)=========
|19007|145255|-3151|
|19016|144485|-3130|
|19124|144579|-3128|
|19112|144059|-3103|
======================================
Следование по маршруту:
1. соц.дейст. Виктори
(определяется ближ. чекпоинт из массива данных MovePath и следует к данной точке, если достигнит ее то переходит к следующей в зависимости от направления.)
зы: есть мысль, допустим зациклить путь, чтобы бегал по маршруту и по ходу движения проверять на нападение на нас, если напали то приостонавить скрипт. тоды можно включить в паре с любым ботом "локомотив" представленные на данном форуме. В итоге получим место кача не круглое а допустим с более сложной геометрией или там отход на безопастную позицию для ребафа и ренегена манны или .....
зыы: интересно выслушать различные мнения по данному вопросу
delphi Код:
var
// movement data
MovePath, // данные по которому мы будем двигатся в данный момент
MyFile: TStringList; // данные для записи пути
PointsCount: integer;
SavePathEnabled: boolean;
MoveToPathEnabled: boolean;
MoveToForward: boolean;
MoveStepIndex: integer;
MoveTimer: TTimer;
MoveStepTime: integer;
// self states
myX,myY,myZ: integer;
myID: integer;
myHP,myMP,myMaxHP,myMaxMP: integer;
const
MyFileName = 'c:\myfile.txt';
MyNick = 'МойНик';
interlude = false;
debug = false;
procedure Init; //Вызывается при включении скрипта
begin
MoveTimer := TTimer.Create(nil);
MoveTimer.Enabled := False;
MoveTimer.Interval := 1000;
MoveTimer.OnTimer := @OnMove;
buf:=hstr('0F');
SendToServerEX(MyNick);
MyFile:=TStringList.Create;
MovePath:=TStringList.Create;
try
MyFile.LoadFromFile(MyFileName);
except
end;
//ShowMessage(inttostr(ExtractValue('|100|12345|300|',2))); // debug
end;
procedure Free; //Вызывается при выключении скрипта
begin
if MyFile<>nil then
begin
MyFile.Free;
end;
if MovePath<>nil then
MovePath.Free;
end;
function GetValue(ValName: string): string;
begin
result:=MyFile.Values[ValName];
end;
procedure SetValue(ValName: string; Value: string);
begin
MyFile.Values[ValName]:=Value;
end;
procedure StartRecord;
begin
if SavePathEnabled then
exit;
if MoveToPathEnabled then
begin
SendMsg('Во время следования по маршруту запись не возможна');
exit;
end;
MyFile.Clear;
PointsCount:=0;
SendMsg('Начата запись маршрута');
SavePathEnabled := True
end;
procedure StopRecord;
begin
if not SavePathEnabled then
exit;
MyFile.SaveToFile(MyFileName);
SendMsg('Запись маршрута завершена');
SavePathEnabled := False;
end;
procedure SendMsg(msg:string); // отправка системных сообщений клиенту
begin
buf:=#$4A;
WriteD(0);
WriteD(10);
WriteS('');
WriteS(msg);
SendToClientEx(MyNick);
end;
procedure ParseMoveClient;
var
i,x,y,z: integer; s: string;
begin
if not SavePathEnabled then
exit;
i:=2;
x:=readd(i);
y:=readd(i);
z:=readd(i);
inc(PointsCount);
s:='|'+inttostr(x)+'|'+inttostr(y)+'|'+inttostr(z)+'|';
MyFile.Add(s);
SendMsg('добавлен чекпоинт № '+inttostr(PointsCount));
end;
function delta(xpos1, ypos1, xpos2, ypos2:extended):integer; //возвращает переменную rezu которая является растоянием между 2 точками
var
dx,dy,summa: extended;
begin
dx:= xpos1-xpos2;
dy:= ypos1-ypos2;
summa:= dx*dx+dy*dy;
if summa = 0 then result:= 0 else result:= Round(sqrt(summa));
if debug then
SendMsg('delta='+inttostr(result));
{
try
result:= Round(Sqrt(((xpos1-xpos2)*(xpos1-xpos2))+((ypos1-ypos2)*(ypos1-ypos2))));
if debug then
SendMsg('delta='+inttostr(result));
except
result:=-1;
if debug then
SendMsg('error in delta');
end;
}
end;
function GetMinCheckPoint(PointsList: TStringList): integer;
var
i,m,min_dist: integer;
s: string;
x,y,z: integer;
begin
result:=-1;
min_dist:=-1;
if PointsList.Count<=1 then
exit;
for i:=0 to PointsList.count-1 do
begin
s:=PointsList[i];
y:=ExtractValue(s,2);
x:=ExtractValue(s,1);
if debug then
SendMsg(s+' x:='+inttostr(x)+' y:='+inttostr(y));
m:=delta(x,y,myx,myy);
if m>0 then
begin
if (result=-1) then
begin
min_dist:=m;
result:=i;
end
else
if m<min_dist then
begin
min_dist:=m;
result:=i;
end;
end;
end;
end;
//*********************************************
// основная процедура запуска на движение по маршруту
//*********************************************
procedure GoToPath(ToForward: boolean);
var
x,y,z,i: integer;
s: string;
begin
MoveToPathEnabled:= not MoveToPathEnabled;
MoveToForward:=ToForward;
if not MoveToPathEnabled then
begin
MoveTimer.Enabled:=False;
SendMsg('Следование по маршруту остановлено');
exit;
end;
//***********************
// берем путь из MyFile
MovePath.assign(MyFile);
//**********************
SendMsg('Пробуем выйти на путь...');
// сперва идем к ближайшему чекпоинту
i:= GetMinCheckPoint(MovePath);
if i<0 then
begin
SendMsg('чекпоинт не найден');
MoveToPathEnabled:=False;
end else
begin
SendMsg('найден ближайший чекпоинт бежим туды');
MoveToPathEnabled:=True;
MoveStepIndex:=i;
if debug then
SendMsg('checkpoint #'+inttostr(i));
s:=MovePath[MoveStepIndex];
x:=ExtractValue(s,1);
y:=ExtractValue(s,2);
z:=ExtractValue(s,3);
MoveTo(x,y,z);
end;
MoveTimer.Enabled:=True;
end;
procedure OnMove(Sender: TObject);
var
x,y,z: integer; s: string;
begin
if not MoveToPathEnabled then
begin
TTimer(Sender).Enabled:=False;
if debug then
SendMsg('OnMove disabled');
exit;
end;
try
// проверяем на существ. объекта
// при отладке всякое может быть
MovePath.Count;
except
TTimer(Sender).Enabled:=False;
exit;
end;
s:=MovePath[MoveStepIndex];
x:=ExtractValue(s,1);
y:=ExtractValue(s,2);
z:=ExtractValue(s,3);
if PosInRange(x,y,z,100) then
begin
if MoveToForward then
begin
if MoveStepIndex=MovePath.Count-1 then
begin
MoveToPathEnabled:=False;
SendMsg('Мы по идее в конечной точке');
exit;
end
else
begin
inc(MoveStepIndex);
end;
end
else
begin
if MoveStepIndex>0 then dec(MoveStepIndex)
else
begin
MoveToPathEnabled:=False;
SendMsg('Мы по идее в начальной точке');
exit;
end;
end;
// мы достигли чекпоинта идем далее
SendMsg('бежим к #'+inttostr(MoveStepIndex));
s:=MovePath[MoveStepIndex];
x:=ExtractValue(s,1);
y:=ExtractValue(s,2);
z:=ExtractValue(s,3);
MoveTo(x,y,z);
end;
end;
function ExtractValue(sData: string;nIndex: integer): integer;
var
s: string;
i,j: integer;
begin
i:=0;j:=0;s:='';
s:=sData;
while j<nIndex do
begin
i:=pos('|',S);
if i>=0 then
begin
s:=copy(s,i+1,length(s)-i);
inc(j);
end
else
break;
end;
i:=pos('|',s);
if i>=0 then
s:=copy(s,1,i-1);
try
result:=strtoint(s);
except
end;
end;
//******************************************************************
//Bot by Skymanrus
//modified by NLObP специально для Владера, моего сына!
//ПЕРЕМЕЩЕНИЕ:
//Идти в точку с координатами x,y,z
//MOVETO(x,y,z)
procedure MoveTo(TargetX,TargetY,TargetZ:integer);
begin
//01=MoveBackwardToLocation:d(targetX)d(targetY)d(targetZ)d(originX)d(originY)d(originZ)d(moveByMouse)
buf:=#$01;
WriteD(targetx); //куда
WriteD(targety);
WriteD(targetz);
WriteD(MyX); //откуда
WriteD(MyY);
WriteD(MyZ);
WriteD(1); //используем 1-мышь 0-клавиатура
SendToServerEx(MyNick);
end;
//Ориентация на местности:
//Проверка находится ли заданная точка в пределах досягаемости. Если да, то выполняется кусок скрипта в фигурных скобках {}.
function PosInRange(targetx,targety,targetz,distanciya:integer):boolean;
begin
if delta(targetx, targety, MyX, MyY)<=distanciya
then result:=true else result:=false;
end;
procedure UserInfo; // обновление донных о себе
var
i:word;
begin
MyID:=ReadD(18);
MyX:=ReadD(2);
MyY:=ReadD(6);
MyZ:=ReadD(10);
if interlude then i:=i+48 else i:=i+44;
MyMaxHP:=ReadD(i);
MyHP:=ReadD(i);
MyMaxMP:=ReadD(i); // чисто информативно
MyMP:=ReadD(i);
end;
procedure StatusUpdate; // обновление данных о себе
var
i:integer;
begin
for i:=0 to ReadD(6)-1 do
case pck[i*8+10] of
#$09: MyHP:=ReadD(i*8+14);
#$0A: MyMaxHP:=ReadD(i*8+14);
#$0B: MyMP:=ReadD(i*8+14);
#$0C: MyMaxMP:=ReadD(i*8+14);
end;
end;
//***************************************************************
procedure OnConnect(WithClient: Boolean); //Вызывается при установке соединения
begin
end;
procedure OnDisonnect(WithClient: Boolean); //Вызывается при потере соединения
begin
end;
function iif(Bool: Boolean;aTrue: variant; aFalse: variant): variant;
begin
if Bool then
result:=aTrue
else
result:=aFalse;
end;
//основная часть скрипта
//вызывается при приходе каждого пакета если скрипт включен
var
i: integer;
begin
if FromClient and (ConnectName=MyNick)then
case pck[1] of
#$1B: // social
case pck[2] of
#$06: StartRecord; //Yes
#$05: StopRecord;//No
#$04: begin GoToPath(true); pck:=''; end;//attack!
end; //case
#$01: // move
ParseMoveClient;
#$48:
begin
myx:=ReadD(2);
myY:=ReadD(6);
myZ:=ReadD(10);
end;
end; // case
if FromServer and (ConnectName=MyNick) then
case pck[1] of
#$04: UserInfo;
#$0E: StatusUpdate;
end; // case
end.