shape1
shape2
shape3
shape4
shape7
shape8

Оптимизация мода/скрипта

  • Автор темы Autor
  • Дата начала

Статус
Закрыто для дальнейших ответов.
A

Autor

Гость
Гость
Совет #1:

Используйте в скрипте/моде как можно меньше таймеров. Каждый таймер способствует постепенному нарастанию грыжи у сервера.

Совет #2:

Функции которые не используются в таймерах, помещайте в stock а не в public

Совет #3:

При создании массивов типа:

new string[256];

Подумайте заранее, какая самая большая строка может использоваться в массиве, и максимально уменьшите число в квадратных скобках.Макс. знчение для SendClientMessage 144.

Совет #4:

Соблюдайте табуляцию/выравнивание кода (лесенка) и не используйте функций типо tabsize.

Совет #5:

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

Пример:

new var1;
var1 = GetPlayerSkin(playerid);
if(var1 == 0) return SendClientMessage(playerid, 0xFF0000FF, "У вас скин CJ");

Лучше сделать так:

Код:
if(GetPlayerSkin(playerid) == 0) return SendClientMessage(playerid, 0xFF0000FF, "У вас скин CJ");
Совет #6:Если в переменной может быть значение только 0 или 1, используйте тип переменной bool.

Пример:

PlayerInfo[playerid][pDriving];
/* Права на машину, они либо есть, либо их нет.
Поэтому pDriving в enum'е лучше пометить типом bool:pDriving */
// С обычными переменными аналогично

Совет #7:Старайтесь меньше использовать такие константы как MAX_PLAYERS, MAX_VEHICLES и т.п.

Лучше сделать так:

#undef MAX_PLAYERS

#define MAX_PLAYERS 20

где 20 - новое значение константы

Совет #8:

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

Яркий пример: PlayerToPoint и IsPlayerRangeOfPoint

Совет #9:

В некоторых случаях лучше использовать switch нежели if/else

Пример:

if(var1 == 1) print("1");
else if(var1 == 2) print("2");
else if(var1 == 3) print("3");
else print("4");

Лучше записать так:

Код:
switch(var1)
{
    case 1: print("1");
    case 2: print("2");
    case 3: print("3");
    default: print("4");
}
Совет #10:Если возможно, лучше использовать имя клавиши, нежели её код.

Пример:

Клавиша Alt: KEY_WALK/1024

Лучше записать KEY_WALK.

Совет #11:

В большинстве случаев, использование паблика OnPlayerUpdate не оправдывает само себя, поэтому лучше с ним не злоупотреблятb.

Совет #12:

НИКОГДА не используйте цикл в цикле (последнее время частенько такое замечаю).

Пример:

for(new i = 0; i < MAX_PLAYERS; i++)
{
    for(new z = 0; z < MAX_PLAYERS; z++) // Этот цикл выполнится 500 по 500 (т.е. 500 раз по 500)
    {
    }
}

Совет #13:Если вы часто используете один и тот же код, лучше создать для него функцию.

Пользуясь этими советами, вы добьётесь большей эффективности скриптинга. Как в быстродействии, так и в визуальном восприятии кода.

А теперь пара приёмов "оптимизированного" кода.

1. Структура switch:

switch(var1)
{
    case 0: var1 = 1;
    case 1: var1 = 1;
    case 2: var1 = 1;
    case 3: var1 = 2;
    case 4: var1 = 2;
}

Лучше записать так:

Код:
switch(var1)
{
    case 0..2: var1 = 1;
    case 3,4: var1 = 2;
}
2. Часто в функциях/командах используется:

Код:
SendClientMessage(playerid, 0xFFFFFFFF, "Текст");
return 1;
"Функцию" return, можно использовать в составе с любой функцией которая возвращает 1 или 0 (истина или ложь).В нашем примере можно сделать так:

return SendClientMessage(playerid, 0xFFFFFFFF, "Текст");

2.1. Если функция возвращает true/else по условию:

Код:
if(!strcmp("text", "text", true)) return 1;
else return 0;
Можно записать так:

Код:
!strcmp("text", "text", true)?true:false;
3. Использование псевдодинамических массивов для оптимизации циклов типа:

Код:
for(new i; i<MAX_PLAYERS; i++) { ... }
==============================================================================================Оптимизация циклов вида:

for(new i=0;i<MAX_PLAYERS;i++)
{ ... }

Не для кого не секрет, что MAX_PLAYERS определяется в a_samp.inc и равна 500.Раньше я использовал вот такую манипуляцию:

#if defined MAX_PLAYERS
#undef MAX_PLAYERS
#define MAX_PLAYERS 100
#else
#define MAX_PLAYERS 100
#endif

Это конечно давало некоторый прирост, но я пошел еще дальше!Первой идеей было использовать функцию GetMaxPlayers(), но это никак не помогло бы: на сервере могут быть всего 3 игрока, ид которых 0, 7 и 28, и циклу приходилось бы совершать 28 тактов.

К сожалению, в pawn нельзя создавать динамические массивы, поэтому я придумал использовать что-то вроде псевдодинамического массива для хранения идподключенных игроков. Создал глобальный масив:

new PLIDs[MAX_PLAYERS];

Далее я ввел переменную содержащую количество игроков на сервере:

Код:
new MaxPlayers = 0;
Код:
Очистим весь массив PLIDs при инициализации мода OnGameModInit:
Код:
for(new i=0;i<sizeof(PLIDs);i++){PLIDs[i] = -1;}
Теперь надо добавить в паблик OnPlayerConnect необходимые операции с глобальными переменными:

Код:
PLIDs[MaxPlayers] = playerid;
MaxPlayers++;
Все довольно просто - игрок подключается, и его ИД помещается в последнюю свободную ячейку массива PLIDs, ну а переменная MaxPlayers становится на единицу больше.С пабликом OnPlayerDisconnect все немного сложнее. Игрок выходит, тоесть слот в PLIDs который занимала его ИД надо очистить. Но мне не нужен пустой слот, поэтому я присваиваю ему значение самого последнего слота PLIDs, и вот последний уже очищаю:

for(new i=0;i<MaxPlayers;i++)
{
    if(PLIDs == playerid)
    {
        MaxPlayers--;
        PLIDs = PLIDs[MaxPlayers];
        PLIDs[MaxPlayers] = -1;
        break;
    }
}

Все, теперь вы можете оптимизировать массивы.Пример:

Пусть был массив:

for(new i=0;i<MAX_PLAYERS;i++)
{
    if(!IsPlayerConnected(i)){continue;}
    SendClientMessage(i, -1, "Message");
}

После оптимизации:

Код:
for(new i=0;i<MaxPlayers;i++)
{
    SendClientMessage(PLIDs[i], -1, "Message");
}
Плюсы данного метода:- отсутствуют лишние такты циклов

- не требуется проверять подключен ли игрок

Минусы:

- меняется порядок ИД игроков при выполнении циклов

==============================================================================================

4. Использование массива вместо функции GetPlayerName (либо ее аналога, GetPlayerNameEx) для узнавания никнейма игрока.

Для этого создаем глобальный двумерный массив:

new PlayerName[MAX_PLAYERS][MAX_PLAYER_NAME];

Далее в OnPlayerConnect'e записываем никнейм игрока в массив:

Код:
GetPlayerName(playerid, PlayerName[playerid], MAX_PLAYER_NAME);
При каждом изменении ника по сценарию мода также добавляем эту строку (например в команду /setname)При выходе игрока нужно очистить его ячейку в массиве:

Код:
PlayerName[playerid][0] = 0;
Пример использование:

Код:
format(str, 128, "Ник игрока под идом 5 '%s'", PlayerName[5]);
Автор: eFFect aka YoYo
 
Статус
Закрыто для дальнейших ответов.