26.09.2011, 14:46
(
Последний раз редактировалось White_116; 17.05.2013 в 13:08.
Причина: Новая версия.
)
Здравствуйте!
Представляю вашему вниманию "стример" точек.
Что же это такое спросите вы - это быстрое нахождение в какой из созданных точек находится игрок.
Создан специально чтобы искоренить медленную и не рациональную конструкцию вида:
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;
}
Область применения:
Quote:
- заменяем пикапы для домов/бизов на точки. - создание ворот - место заправки - возможность создать псевдочекпойнты или мины. - отслеживание в какой точке находится игрок, для захвата территории, пополнение очков и т.п. |
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);//Узнает в каких точках находится транспорт
Quote:
GetPlayerPoint(playerid, 0); Ищет самую близлежащую точку в которой находится игрок. GetPlayerPoint(playerid, 1); Ищет самую близлежащую точку даже если игрок не находится в ней. GetPlayerPoint(playerid, 2); Ищет до первой точки в которой находится игрок. GetPlayerMultiPoint(playerid, MP[], Size); Ищет все точки в которых находится игрок пока они не закончатся или не достигнут Size. |
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)
{
//...
}
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: 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.