Здравствуйте!
Представляю вашему вниманию "стример" точек.
Что же это такое спросите вы - это быстрое нахождение в какой из созданных точек находится игрок.
Создан специально чтобы искоренить медленную и не рациональную конструкцию вида:
PHP код:
stock IsPlayerIn(playerid)
{
for(new i = 0; i < sizeof(coords); i++)
if(IsPlayerInRangeOfPoint(playerid, 1.0, coords[i][0], coords[i][1], coords[i][2]))return 1;
return 0;
}
Основан он на зональной предварительной отсортировки, что придаёт значительную скорость обработки, так как откидывается большая часть лишних проверок.
Область применения:
- заменяем пикапы для домов/бизов на точки.
- создание ворот
- место заправки
- возможность создать псевдочекпойнты или мины.
- отслеживание в какой точке находится игрок, для захвата территории, пополнение очков и т.п.
Основные функции:
PHP код:
native IsValidPoint(pointid);// Существует ли точка
native CreatePoint(Float:x, Float:y, Float:z, Float:r, worldid=-1, interior=-1);// Cоздаёт точку (х, у, z, радиус, вирт.мир, интерьер). Вернёт ид точки, иначе ид ошибки.
native DestroyPoint(pointid);// Удаляет точку
native DestroyAllPoint();// Удаляет все точки
native SetPointPos(pointid, Float:x, Float:y, Float:z);//Переместить точку
native GetPointPos(pointid, &Float:x, &Float:y, &Float:z);//Узнать координаты точки
native SetPointRadius(pointid, Float:r);//Установить радиус точки
native GetPointRadius(pointid, &Float:r);//Узнать радиус точки
native SetPointInterior(pointid, interior);//Установить интерьер точки
native GetPointInterior(pointid);//Узнать интерьер точки
native SetPointVirtualWorld(pointid, worldid);//Установить вирт.мир точки
native GetPointVirtualWorld(pointid);//Узнать вирт.мир точки
native GetPlayerPoint(playerid, mode=0); //Узнает в какой точке находится игрок. Возвращает ид найденной точки.
native GetPlayerMultiPoint(playerid, MP[], Size);//Узнает в каких точках находится игрок. Возвращает количество найденных точек
native GetVehiclePoint(vehicleid, mode=0);//Узнает в какой точке находится транспорт (самую близлежащую, самую близлежащую с проверкой радиуса, самую первую которая входит в радиус)
native GetVehicleMultiPoint(vehicleid, MP[], Size);//Узнает в каких точках находится транспорт
GetPlayerPoint(playerid, 0); Ищет самую близлежащую точку в которой находится игрок.
GetPlayerPoint(playerid, 1); Ищет самую близлежащую точку даже если игрок не находится в ней.
GetPlayerPoint(playerid, 2); Ищет до первой точки в которой находится игрок.
GetPlayerMultiPoint(playerid, MP[], Size); Ищет все точки в которых находится игрок пока они не закончатся или не достигнут Size.
Небольшой Тест всего 40,000 точек, симуляция 1000 игроков. Ищется самая близлежащая точка. Для правильности теста нужно быть на сервере, возле нулевых координат!
Create W_Points 473 ms
GetW_Point 20 ms
Create StreamerPoints 35 ms
GetStreamerPoint 329 ms
GetClassicPoint 11479 ms
y_areas выдаёт для одного игрока ~5 ms, осталось домножить на 1000.
Внимание!
1) Настоятельно рекомендую не ставить радиус больше MAX_POINTS_SETKA_DLINA, так как при нахождения точки может возникнуть казус: вы входите в радиус но точка не определяется. Связано это с отсутствием ссылки на точку.
2) Поддержка интерьеров и виртуальных миров по умолчанию отключена. Для того чтобы включить выполняем следующие:
PHP код:
#define PointWorld //включаем вирт.мир
#define PointInterior //включаем интерьер
#include <W_PS> //подключаем инклуд
<<< Примеры >>>
Использование GetPlayerMultiPoint:
PHP код:
new pointarray[32];//создали массив куда пишем иды точек.
new kolichestvo=GetPlayerMultiPoint(playerid, pointarray, sizeof(pointarray));//поиск точек, вернёт количество найденных точек.
for(kolichestvo=kolichestvo-1; kolichestvo > -1; kolichestvo--)printf("pointid = %d",pointarray[kolichestvo]);
Псевдочекпойнт:
PHP код:
new Point[MAX_PLAYERS];//Куда нибудь в начало, хранит ид точки в которой находится игрок.
stock PointUpdate(playerid)//В любой таймер с перебором игроков
{
new newppoint=GetPlayerPoint(playerid);//Ищем самую близлежайшую точку в которой находится игрок
if(Point[playerid] != newppoint)//Если точка отличается от старой.
{
if(Point[playerid] != 0) OnPlayerLeavePoint(playerid, Point[playerid]);//Если мы были в точке
if(newppoint != 0) OnPlayerEnterPoint(playerid, newppoint);//Если новая точка точка.
Point[playerid]=newppoint;//Запомним точку
}
return 1;
}
stock OnPlayerLeavePoint(playerid, pointid)
{
//...
}
stock OnPlayerEnterPoint(playerid, pointid)
{
//...
}
Пример 3:
PHP код:
#include <a_samp>
#define MAX_POINTS (10)
#define MAX_POINTS_TO_STREAM (10)
#define PointWorld
#define PointInterior
#define DeBug
#include <W_PS>
#define Biznes (1)
#define Home (2)
new PointData[3][MAX_POINTS+1 char];
new BizKolvo;
new HomeKolvo;
new Timer;
new Point[MAX_PLAYERS];//Куда нибудь в начало, хранит ид точки в которой находится игрок.
//==============================================================================
public OnFilterScriptInit()
{
Timer=SetTimer("PointUpdate",100,1);
return 1;
}
public OnFilterScriptExit()
{
KillTimer(Timer);
return 1;
}
public OnPlayerCommandText(playerid, cmdtext[])
{
if(strcmp("/biz", cmdtext, true, 4) == 0)
{
CreateBiz(playerid);
return 1;
}
if(strcmp("/home", cmdtext, true, 5) == 0)
{
CreateHome(playerid);
return 1;
}
if(strcmp("/del", cmdtext, true, 4) == 0)
{
DestroyPoint(MAX_POINTS);
return 1;
}
if(strcmp("/pos", cmdtext, true, 4) == 0)
{
new Float:x,Float:y,Float:z;
GetPlayerPos(playerid, x,y,z);
SetPointPos(MAX_POINTS, x, y, z);
return 1;
}
return 0;
}
//==============================================================================
forward PointUpdate();
public PointUpdate()//В любой таймер с перебором игроков
{
for(new playerid; playerid < MAX_PLAYERS; playerid++)
if(IsPlayerConnected(playerid))
{
new newppoint=GetPlayerPoint(playerid);//Ищем самую близлежайшую точку в которой находится игрок
if(Point[playerid] != newppoint)//Если точка отличается от старой.
{
if(Point[playerid] != 0) OnPlayerLeavePoint(playerid, Point[playerid]);//Если мы были в точке
if(newppoint != 0) OnPlayerEnterPoint(playerid, newppoint);//Если новая точка точка.
Point[playerid]=newppoint;//Запомним точку
}
}
return 1;
}
stock OnPlayerLeavePoint(playerid, pointid)
{
new str[128];
if(PointData[0]{pointid} == Home) format(str,sizeof(str),"Вы покинули дом номер %d, хозяин %d",PointData[1]{pointid},PointData[2]{pointid});
else format(str,sizeof(str),"Вы покинули бизнес номер %d, хозяин %d",PointData[1]{pointid},PointData[2]{pointid});
return SendClientMessage(playerid,-1,str);
}
stock OnPlayerEnterPoint(playerid, pointid)
{
new str[128];
if(PointData[0]{pointid} == Home) format(str,sizeof(str),"Вы вошли в дом номер %d, хозяин %d",PointData[1]{pointid},PointData[2]{pointid});
else format(str,sizeof(str),"Вы вошли в бизнес номер %d, хозяин %d",PointData[1]{pointid},PointData[2]{pointid});
return SendClientMessage(playerid,-1,str);
}
stock CreateBiz(playerid)
{
new Float:x,Float:y,Float:z;
GetPlayerPos(playerid, x,y,z);
new p=CreatePoint(x,y,z, 10.0);
if(p < 1)
{
if(p == 0) printf("Привышено максимальное количество точек.");
if(p == -1)printf("Привышено максимальное количество точек в чанке.");
if(p == -2)printf("Поддержка вирт.миров отключена!");
if(p == -3)printf("Поддержка интерьеров отключена!");
return 0;
}
BizKolvo++;
PointData[0]{p}=Biznes;//Запомним тип точки
PointData[1]{p}=BizKolvo;//Запомни ид бизнеса
PointData[2]{p}=playerid;//Запомним владельца
return BizKolvo;
}
stock CreateHome(playerid)
{
new Float:x,Float:y,Float:z;
GetPlayerPos(playerid, x,y,z);
new p=CreatePoint(x,y,z, 10.0);
if(p < 1)
{
if(p == 0) printf("Привышено максимальное количество точек.");
if(p == -1)printf("Привышено максимальное количество точек в чанке.");
if(p == -2)printf("Поддержка вирт.миров отключена!");
if(p == -3)printf("Поддержка интерьеров отключена!");
return 0;
}
HomeKolvo++;
PointData[0]{p}=Home;//Запомним тип точки
PointData[1]{p}=HomeKolvo;//Запомни ид дома
PointData[2]{p}=playerid;//Запомним владельца
return HomeKolvo;
}
>> Скачать W_Points v2.3: SolidFiles
>> Просмотреть W_Points v2.3: Pastebin
>> Скачать W_Points v2.2: SolidFiles
>> Просмотреть W_Points v2.2: Pastebin
>> Скачать W_Points v2.1: SolidFiles
>> Просмотреть W_Points v2.1: Pastebin
W_Points v2.1:
-Добавлен поиск точек для транспорта.
-Исправлен баг в GetPlayerPoint(playerid, 2); связанный с лишним кодом.
W_Points v2.2:
-Исправлены мелкие ошибки.
-Новый метод поиска предложенный AirKite
W_Points v2.3:
Исправлено перемещение точки SetPointPos.