Формула вычисления точки на векторе:
a + t*(b-a)
где а - начальная точка; b - конечная; t - коэффициент от -1 до 1.
Позволит в скрипте боту следовать не на рандомные координаты вокруг цели, а ему за спину.
Есть проблема с его отставанием при пробежке на большую дистанцию. То есть бот будет не добегать до вас на 10% (для большой дистанции это может быть 300 ярдов)
Вот собственно функция для организации следования:
Код:
procedure TargetMovedTo(tx, ty, tz : integer);
var nX, nY, nZ : integer;
begin
if not follow then exit;
if delta(MyX,MyY,tx,ty) < 150 then exit;
nX := Round(tx + dist * (MyX - tx));
nY := Round(ty + dist * (MyY - ty));
MoveTo(nx, ny, tz);
end;
Её нужно вызывать каждый раз когда мы перехватили координаты цели за которой следуем.
Вот тестовый скрипт, который вешает чара под ником Name за тем кто напишет в чат go
Оффтоп
program Follow;
const
Name='Superus';
TargetName='BigBoobs';
dist=0.2;
low=-1;
var
follow: boolean;
myX,myY,myZ: integer; //наши статы
MyOID, TargetOID: integer;
procedure Init; //Вызывается при включении скрипта
begin
follow := false;
end;
procedure Free; //Вызывается при выключении скрипта
begin
end;
procedure msg(msg:string); //отправка системных сообщений клиенту
begin
buf:=#$4A;
WriteD(0);
WriteD(10);
WriteS('');
WriteS(msg);
SendToClientEx(Name);
end;
procedure MoveTo(TargetX,TargetY,TargetZ:integer);
begin
//01=MoveBackwardToLocation:d(targetX)d(targetY)d(ta rgetZ)d(originX)d(originY)d(originZ)d(moveByMouse)
buf:=#$0F;
WriteD(targetx); //куда
WriteD(targety);
WriteD(targetz);
WriteD(MyX); //откуда
WriteD(MyY);
WriteD(MyZ);
WriteD(1); //используем 1-мышь 0-клавиатура
SendToServerEx(Name);
end;
procedure TargetMovedTo(tx, ty, tz : integer);
var nX, nY, nZ : integer;
begin
if not follow then exit;
if delta(myx,myy,tx,ty) < 150 then exit;
nX := Round(tx + dist * (MyX - tx));
nY := Round(ty + dist * (MyY - ty));
MoveTo(nx, ny, tz);
end;
//......................................
function delta(xpos1, ypos1, xpos2, ypos2:extended):integer;
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));
end;
//************************************************** *************
//обработка сообщений
//s32=UserInfo:d(X)d(Y)d(Z)d(Heading)d(ObjectID)...
procedure UserInfo; //обновление данных о себе
var
i:word;
begin
MyOID:=ReadD(18);
MyX:=ReadD(2);
MyY:=ReadD(6);
MyZ:=ReadD(10);
end;
//s31=CharInfo:d(X)d(Y)d(Z)d(Heading)d(ObjectID)...
procedure CharInfo();
var
j, toid: integer;
begin
if TargetName=ReadS(22) then
begin
TargetOID := ReadD(18);
TargetMovedTo(ReadD(2),ReadD(6),ReadD(10));
end;
end;
procedure CharMove();
var
j, toid: integer;
begin
if TargetOID=ReadD(2) then
begin
TargetMovedTo(ReadD(6),ReadD(10),ReadD(14));
end;
end;
procedure OnChatMsg();
var
j, chatID, playerID: integer;
playerName, Text: string;
begin
if ReadD(6)=3 then begin
j := 10;
playerName:=ReadS(j);
Text:=ReadS(j);
if (Text='go') or (Text='го') then
begin
TargetOID := ReadD(2);
follow := true;
msg('asd');
end;
end;
end;
//......................................
//основная часть скрипта
//вызывается при приходе каждого пакета если скрипт включен
begin
//не обрабатываем пустые пакеты
if pck='' then exit;
//************************************************** **************************
//серверные пакеты
if (ConnectName=Name) and FromServer then
case pck[1] of
#$32: UserInfo;
#$31: CharInfo;
#$4A: OnChatMsg;
#$2F: CharMove;
end;
//************************************************** **************************
//клиентские пакеты
if (ConnectName=Name) and FromClient then
case pck[1] of
//34=RequestSocialAction:d(Action:Get.Func09)
#$34: begin
end;
#$59:
begin
myX:=ReadD(2);
myY:=ReadD(6);
myZ:=ReadD(10);
end;
end;
if (ConnectName=TargetName) and FromClient then
case pck[1] of
//34=RequestSocialAction:d(Action:Get.Func09)
#$34: begin
end;
#$59:
begin
TargetMovedTo(ReadD(2),ReadD(6),ReadD(10));
end;
end;
end.