PDA

Просмотр полной версии : [Function] PlayerToActor



id228fanta
05.09.2015, 01:25
Описание:

Данная функция определяет, находится ли игрок в определённом радиусе от актёра.

Параметры:

Float:radi - радиус
playerid - ID игрока
actorid - ID актёра




stock PlayerToActor(Float:radi, playerid, actorid)
{
if(IsPlayerConnected(playerid))
{
new Float:posx, Float:posy, Float:posz,Float:oldposx, Float:oldposy, Float:oldposz,Float:tempposx, Float:tempposy, Float:tempposz;
GetPlayerPos(playerid, oldposx, oldposy, oldposz);
GetActorPos(actorid, posx, posy, posz);
tempposx = (oldposx -posx); tempposy = (oldposy -posy); tempposz = (oldposz -posz);
if (((tempposx < radi) && (tempposx > -radi)) && ((tempposy < radi) && (tempposy > -radi)) && ((tempposz < radi) && (tempposz > -radi))) return true;
}
return false;
}


Пример использования:


// Создаём актёра в OnGameModeInit
public OnGameModeInit()
{
new actorlool = CreateActor(.....);
}
// По команде узнаём расстояние от игрока до актёра.
CMD:itoactor(playerid, params[])
{
if(!PlayerToActor(10.0, 0, actorlool)) return SendClientMessage(playerid, -1, "Вы далеко от актёра!");
else SendClientMessage(playerid, -1, "Вы рядом с актёром!");
return true;
}



Автор: Oleg_Petrow

Daniel_Cortez
05.09.2015, 08:21
return 1;


return false;

Пример использования:


// PlayerToActor(радиус, ид игрока, ид актёра);
new actorlool = CreateActor(.....);
PlayerToActor(10.0, 0, actorlool);


Данная функция узнаёт расстояние между игроком и актёром.
Вы это серьёзно?

id228fanta
05.09.2015, 10:58
Вы это серьёзно?

Извиняюсь, просто ночь была, спать хотелось. Исправил.

Daniel_Cortez
05.09.2015, 11:53
Извиняюсь, просто ночь была, спать хотелось. Исправил.

Одну проблему исправили, остальные так и остались.


return 1;


return false;

Данная функция узнаёт расстояние между игроком и актёром.
Тут одно из трёх.
Либо вы сами не понимаете, как работает функция, но уже спешите запостить куда-нибудь так понравившийся кусок кода (такое чаще всего можно видеть на govno-info).
Либо вы не знаете русский язык и не умеете правильно изъяснять свои мысли.
Либо у вас до сих пор ночь.

И да, в чём профит возарата true/false вместо 1/0?

id228fanta
05.09.2015, 12:20
Ночь прошла, я просто мысль свою не так изъяснил. Исправил описание. Спасибо большое. И ещё раз извините.

L0ndl3m
05.09.2015, 12:21
Реализация ужасная, когда только увидел название темы подумал, что функция поворачивает игрока к актёру.
Например это можно было таким способом:


bool: IsPlayerInRangeOfActor(playerid, actorid, Float: range)
{
new
Float: x,
Float: y,
Float: z;

GetActorPos(actorid, x, y, z);
return IsPlayerInRangeOfPoint(playerid, range, x, y, z);
}

, использовав стандартную функцию IsPlayerInRangeOfPoint, либо же так:


bool: IsPlayerInRangeOfActor(playerid, actorid, Float: range)
{
new
Float: x,
Float: y,
Float: z;

GetActorPos(actorid, x, y, z);
return GetPlayerDistanceFromPoint(playerid, x, y, z) <= range;
}

, использовав также, стандартную функцию GetPlayerDistanceFromPoint.

А проверки на то, подключён ли игрок или же актёр к серверу нужно делать за границами функции.
Например:


if(IsPlayerConnected(0) && IsValidActor(1))
{
if(IsPlayerInRangeOfActor(0, 1, 5.0))
// актёр №1 рядом с игроком №0
else
// актёр №1 не находится рядом с игроком №0
}

дабы если вызывать данную функцию в цикле, будет много однотипных проверок, а это лишнее время на выполнение операции.

id228fanta
05.09.2015, 12:26
Реализация ужасная, когда только увидел название темы подумал, что функция поворачивает игрока к актёру.
Например это можно было таким способом:


bool: IsPlayerInRangeOfActor(playerid, actorid, Float: range)
{
new
Float: x,
Float: y,
Float: z;

GetActorPos(actorid, x, y, z);
return IsPlayerInRangeOfPoint(playerid, range, x, y, z);
}

, использовав стандартную функцию IsPlayerInRangeOfPoint, либо же так:


bool: IsPlayerInRangeOfActor(playerid, actorid, Float: range)
{
new
Float: x,
Float: y,
Float: z;

GetActorPos(actorid, x, y, z);
return GetPlayerDistanceFromPoint(playerid, x, y, z) <= range;
}

, использовав также, стандартную функцию GetPlayerDistanceFromPoint.

А проверки на то, подключён ли игрок или же актёр к серверу нужно делать за границами функции.
Например:


if(IsPlayerConnected(0) && IsValidActor(1))
{
if(IsPlayerInRangeOfActor(0, 1, 5.0))
// актёр №1 рядом с игроком №0
else
// актёр №1 не находится рядом с игроком №0
}

дабы если вызывать данную функцию в цикле, будет много однотипных проверок, а это лишнее время на выполнение операции.

Учту в дальнейшем. Спасибо.

Daniel_Cortez
05.09.2015, 16:47
Ночь прошла, я просто мысль свою не так изъяснил. Исправил описание. Спасибо большое. И ещё раз извините.
Вы так и не ответили на мой вопрос.

в чём профит возарата true/false вместо 1/0?



А проверки на то, подключён ли игрок или же актёр к серверу нужно делать за границами функции (...) дабы если вызывать данную функцию в цикле, будет много однотипных проверок, а это лишнее время на выполнение операции.
Во-первых, функции, прежде всего, нужны для удобства.
Если выносить какие-то проверки за пределы функции, то как ты вообще представляешь поддержку такого кода?
Вот представь себе, в SA:MP изменились детали работы функции GetActorPos и тебе придётся переписывать не только функцию PlayerToActor, но и смотреть все случаи её использования, ведь код проверок тоже придётся менять!
Поэтому просто глупо выносить какие-то куски кода за пределы функции ради пары микросекунд. Больше времени потратишь на поддержку.

Во-вторых, пренебрежение защитой может быть оправдано только если в рассматриваемом участке кода очень нужна производительность.
А если так нужна производительность, то зачем тогда вообще пользоваться сторонними функциями? Ведь в них тратится время на создание и уничтожение локальных переменных, да и на сам вызов функции с передачей аргументов через стек.
Можно обойтись одними лишь нативными функциями Pawn/SA:MP. Заодно и больше пространства для оптимизации: например, не придётся заново создавать переменные при каждой проверке актёра.

В-третьих, в SA:MP иногда даже не нужно вызывать отдельные функции для проверки аргументов.
Например, не нужно проверять ID игрока с помощью IsPlayerConnected - функция GetPlayerPos вернёт 0, если указан неправильный ID игрока.

В итоге, если у нас есть мега-критичный участок, на котором нужно проверить, находится ли игрок рядом с каким-то актёром, алгоритм можно реализовать так:


new actorid = INVALID_ACTOR_ID;
new Float:x, Float:y, Float:z;
for (new i = 0; i < MAX_ACTORS; ++i)
{
if(GetActorPos(i, x, y, z))
{
if(IsPlayerInRangeOfPoint(playerid, x, y, z))
{
actorid = i;
break;
}
}
}
if(actorid == INVALID_ACTOR_ID)
return SendClientMessage(playerid, -1, "Поблизости никого нет.");

Но только не вздумайте делать так везде - ваш проект может очень быстро превратиться в кашу из трудноподдерживаемого говнокода, в котором каждое элементарное действие расписано на 100 строк.

Seregamil
05.09.2015, 19:59
Автор: Oleg_Petrow

Ты серьезно?


stock PlayerToPoint(Float:radi, playerid, Float:x, Float:y, Float:z)
{
if(IsPlayerConnected(playerid))
{
new Float:oldposx, Float:oldposy, Float:oldposz;
new Float:tempposx, Float:tempposy, Float:tempposz;
GetPlayerPos(playerid, oldposx, oldposy, oldposz);
tempposx = (oldposx -x);
tempposy = (oldposy -y);
tempposz = (oldposz -z);
if (((tempposx < radi) && (tempposx > -radi)) && ((tempposy < radi) && (tempposy > -radi)) && ((tempposz < radi) && (tempposz > -radi))) return 1;
}
return 0;
}


stock PlayerToActor(Float:radi, playerid, actorid)
{
if(IsPlayerConnected(playerid))
{
new Float:posx, Float:posy, Float:posz,Float:oldposx, Float:oldposy, Float:oldposz,Float:tempposx, Float:tempposy, Float:tempposz;
GetPlayerPos(playerid, oldposx, oldposy, oldposz);
GetActorPos(actorid, posx, posy, posz);
tempposx = (oldposx -posx); tempposy = (oldposy -posy); tempposz = (oldposz -posz);
if (((tempposx < radi) && (tempposx > -radi)) && ((tempposy < radi) && (tempposy > -radi)) && ((tempposz < radi) && (tempposz > -radi))) return true;
}
return false;
}

Для тех, кто не в курсе: функция PlayerToPoint имеет большое признание среди аборигенов клана "Программисты Pawno", которые считают, что их ТРУ функции лучше нативных, в данном случае IsPlayerInRangeOfPoint.

id228fanta
06.09.2015, 10:32
Вы так и не ответили на мой вопрос.

true/false от 1/0 ничем не отличаются
Если только true/false используются в bool

Daniel_Cortez
06.09.2015, 10:34
true/false от 1/0 ничем не отличаются
Если только true/false используются в bool
И что же по вашему будет, если true/false "используются в bool"?

$continue$
06.09.2015, 12:27
И что же по вашему будет, если true/false "используются в bool"?

Сэкономить 3 байта.

Seregamil
06.09.2015, 13:12
true/false от 1/0 ничем не отличаются
Если только true/false используются в bool

Это только в pawn, в остальных ЯП вас компилятор жестко поимеет.

^_^
06.09.2015, 22:23
true/false от 1/0 ничем не отличаются
Если только true/false используются в bool
Жаль тебя разочаровывать но они отличаются. Тип boolean в Павн является лишь слабым тэгом (https://wiki.sa-mp.com/wiki/Scripting:tags) (bool:) и просто зарезервированном словом - ничего больше, соответственно переменная "типа" boolean в Павн занимает тот же объем памяти что и стандартная переменная (тэг _:) - 4 байта, а true/false являются макросами и опять же зарезервированными словами:

#define true bool:1
#define false bool:0
//true и false отличаются от обычных 0 (_:0) и 1 (_:1) и всегда имеют тэг bool
Как уже сказал Seregamil, в любом другом нормальном типизированном ЯП компилятор выдал бы ошибку о несоответствие типа возвращаемого значения и типа функции, но в Павн спасает его безтиповость. Как никак, использование true/false вместо 1 и 0 заставляют препроцессор, при каждой компиляций, искать во всем коде true/false и менять их на bool:1/bool:0, тем самым увеличивая время компиляции на несколько миллисекунд.

Daniel_Cortez
07.09.2015, 06:02
// C / C++
int main = false;

Стабильность работы такой программы не гарантирую, но компилятор (GCC) не то чтобы ошибки, ни одного варнинга не выдал.

$continue$
09.09.2015, 17:01
// C / C++
int main = false;

Стабильность работы такой программы не гарантирую, но компилятор (GCC) не то чтобы ошибки, ни одного варнинга не выдал.
А полный сурс?

Жаль тебя разочаровывать но они отличаются. Тип boolean в Павн является лишь слабым тэгом (https://wiki.sa-mp.com/wiki/Scripting:tags) (bool:) и просто зарезервированном словом - ничего больше, соответственно переменная "типа" boolean в Павн занимает тот же объем памяти что и стандартная переменная (тэг _:) - 4 байта, а true/false являются макросами и опять же зарезервированными словами:

#define true bool:1
#define false bool:0
//true и false отличаются от обычных 0 (_:0) и 1 (_:1) и всегда имеют тэг bool
Как уже сказал Seregamil, в любом другом нормальном типизированном ЯП компилятор выдал бы ошибку о несоответствие типа возвращаемого значения и типа функции, но в Павн спасает его безтиповость. Как никак, использование true/false вместо 1 и 0 заставляют препроцессор, при каждой компиляций, искать во всем коде true/false и менять их на bool:1/bool:0, тем самым увеличивая время компиляции на несколько миллисекунд.

Это только в pawn, в остальных ЯП вас компилятор жестко поимеет.
Хз, кто Вас там имеет :D
GCC что ли?
http://i.imgur.com/S62aP5P.png

NewGreen
09.09.2015, 17:18
Хз, кто Вас там имеет :D
GCC что ли?
http://i.imgur.com/S62aP5P.png
GCC - это не только C++
Попробуйте провернуть ваш трюк с bool/int в Java.

$continue$
09.09.2015, 17:23
GCC
Я вкурсе, как бы.

NewGreen
09.09.2015, 17:54
Я вкурсе, как бы.
Если вы, как бы, в курсе, тогда где аналогичные примеры, на другие языках которые входят в коллекцию GCC ?
Вы ведь сами утверждали что:

Хз, кто Вас там имеет :D
GCC что ли?

Daniel_Cortez
09.09.2015, 19:11
// C / C++
int main = false;

Стабильность работы такой программы не гарантирую, но компилятор (GCC) не то чтобы ошибки, ни одного варнинга не выдал.

А полный сурс?
Ты не поверишь...
http://habrahabr.ru/post/181021/