Коллекция функций / макросов
#21

ФС. Автоматические ворота, которые открываются по гудку транспорта

PASTEBIN (чуть корявые отступы) | Исходник

4 штуки. 3 в доках ЛС и 1 у въезда в подземный гараж копов в центре ЛС.
Reply
#22

Quote:
Originally Posted by JesterX
Последнею функцию - счётчик, можно сделать экономней:

stock CountCehicles() {
new id = CreateVehicle(...);
return id--;
}
не факт что получишь то, что нужно, в примере это будет выглядеть так: ставим сто машин, и машину с ид=2 удаляем, тогда эта функция вернет 1, но у нас то их аш 99
Reply
#23

развелось много агитаторов, которым ну просто непременно нужно пропихнуть IP адрес в чат. У меня канеш стояла легкая защита от этого, но они нашли простой выход с запятыми вместо точек (:

предлагаю вашему вниманию функцию, которая как минимум на 80% точно определяет есть ли в указанном тексте любой нормальный ИП адрес

Код:
/*
	Вернет 1, если строка содержит любой нормальный ИП
*/

stock isTextHaveAnyIP ( string[] )
{
	for ( new pos, digits; string[pos] > 0; pos++ )
	{
		switch ( string[pos] )
		{
			case '0'..'9', 'o', 'O', 'о', 'О' :		{ if ( ++digits > 2 ) return 1; }
			case 30..47, 91..96, 123..183, 185..191 :	{ continue; }
			default :					{ digits = 0; }
		}
	}

	return 0;
}
Reply
#24

аналог swap в c++, меняет значения местами
Код:
stock swap(&x,&y)
{
  new c = x;
  x = y;
  y = c;
}
Reply
#25

Я тут немного потыкался, изобрел вот такую штуку. Может быть, не самое оптимизированное решение. Можно, например, прикрутить к Sniper Privilegy

ZMapCheckLOS(Float1, Float:y1, Float:z1, Float2, Float:y2, Float:z2) - функция вычисляет, просматривается ли путь от точки 1 к точке 2 или нет. x1,y1,z1 и x2,y2,z2 - координаты точек 1 и 2 соответственно.
У остальных функций объяснение в названии (я их приложил только потому что они используются).

Код:
stock ZMapCheckLOS(Float:x1, Float:y1, Float:z1, Float:x2, Float:y2, Float:z2)
{
	new Float: distance = GetDistanceBetweenPoints(x1, y1, z1, x2, y2, z1); // вычислить расстояние между точками в 2D
	new Float: rotation = GetRotationBetweenPoints(x1, y1, x2, y2);			// вычислить арктангенс между точками
	new Float: z_per_meter = (z2 - z1) / distance;	// это число = на сколько изменяется Z на каждый метр расстояния
	new Float: sin = floatsin(-rotation, degrees);
	new Float: cos = floatcos(-rotation, degrees);
	
	new Float: check_dist = 0.0;		// текущее расстояние пути проверки от точки 1 к точке 2
	
	while(check_dist < distance)
	{
		check_dist += 1.0;
		
		new Float:z_zmap;
		ZMapFindZ(x1 + (check_dist * sin), y1 + (check_dist * cos), z_zmap);
		
		// чтобы отследить визуально, где кончается "видимая" дистанция :)
		// CreateObject(1559, x1 + (check_dist * sin), y1 + (check_dist * cos), z1 + (check_dist * z_per_meter), 0, 0, 0);
		
		if(z1 + (check_dist * z_per_meter) < z_zmap)
		{
			return 0;
		}
	}
	return 1;
}

stock Float:GetDistanceBetweenPoints(Float:x1,Float:y1,Float:z1,Float:x2,Float:y2,Float:z2)
{
	x1 -= x2;
	y1 -= y2;
	z1 -= z2;
	return floatsqroot((x1 * x1) + (y1 * y1) + (z1 * z1));
}

stock Float:GetRotationBetweenPoints(Float:x1, Float:y1, Float:x2, Float:y2)
return Float:(180-atan2(x1-x2,y1-y2));
Reply
#26

for (new i;i < 2048;i++) {
if (IsValidMenu(Menu:i))
DestroyMenu(Menu:i);
if (IsValidObject(i))
DestroyObject(i);
if (IsValidPlayerObject(i,i))
DestroyPlayerObject(i,i);
DestroyPickup(i);
TextDrawDestroy(Text:i);
GangZoneDestroy(i);
Delete3DTextLabel(Text3D:i);
DeletePlayer3DTextLabel(i,PlayerText3D:i);
DestroyVehicle(i);
}
#if defined _streamer_included
DestroyAllDynamicObjects();
DestroyAllDynamicPickups();
DestroyAllDynamicCPs();
DestroyAllDynamicRaceCPs();
DestroyAllDynamicMapIcons();
DestroyAllDynamic3DTextLabels();
DestroyAllDynamicAreas();
#endif
ццц
чтоб не тррахатся с удалением в конце выхода из мода всех обьектов юзаных и т.д.
сразу всё удаляет и не мучается.
з.ы. дада, у меня именно в GameModeinit тупит getmaxplayers
изза этого я решил что он глючный
Reply
#27

Quote:
Originally Posted by [JIeXa
]
ццц
чтоб не тррахатся с удалением в конце выхода из мода всех обьектов юзаных и т.д.
сразу всё удаляет и не мучается.
з.ы. дада, у меня именно в GameModeinit тупит getmaxplayers
изза этого я решил что он глючный
Все обычные объекты, машины и т.д. и так уничтожаются при выгрузке мода.

Quote:
Originally Posted by [Saint
]
не знаю, знаете ли вы это, или нет вот всё же...

сегодня я чисто случайно нашел её 1 стандартную команду в sa-mp

/rs - создаёт в папке с игрой файл "rawpositions" (если игрок пешком) и "rawvehicles" (если игрок в транспорте)
Имхо, это для сохранения машин в формате для мода grand larceny.
Reply
#28

конечно боянчик, но чтобы оживить темку:
Код:
stock getPlayerName(playerid, del=0) {
	new name[MAX_PLAYER_NAME];
	GetPlayerName(playerid, name, MAX_PLAYER_NAME);
	if(del) name[strfind(name, "_")] = ' ';
	return name;
}
Reply
#29

Хочу поделиться одной полезной функцией, разработанной мною и Y_Less'ом пару месяцев назад, но не получившей широкого распространения (т.к. опубликована она была лишь в Code Optimisations). С ее помощью можно отправлять отформатированные сообщения игрокам без предварительного вызова format и необходимости содания промежуточного буфера для хранения строки - все это делается внутри нее. До этого реализовать подобную функциональность не получалось из-за проблем с передачей переменного списка аргументов от одной функции другой, теперь она наконец-то решена

Сама конструкция функции позволяет ее без труда изменять для написания других функций с применением данного метода (например, SendFormattedMessageForAll, db_queryf и т.п.).

Внимание! Добавление данной функции в код вашего скрипта может вызывать падение компилятора во время процесса его работы. Чтобы исправить это, необходимо обязательно где-нибудь (по идее неважно где) использовать format в текущем скрипте.

В коде интенсивно используются опкоды абстрактной машины PAWN для доступа к стеку и пр., их описание можно найти в официальной документации (а точнее: http://compuphase.com/pawn/Pawn_Implementer_Guide.pdf).

pawn Код:
//
stock SendFormattedMessage(playerid, color, fstring[], {Float, _}:...)
{
    // This is the number of parameters which are not variable that are passed
    // to this function (i.e. the number of named parameters).
    static const
        STATIC_ARGS = 3;
    // Get the number of variable arguments.
    new
        n = (numargs() - STATIC_ARGS) * BYTES_PER_CELL;
    if (n)
    {
        new
            message[128],
            arg_start,
            arg_end;

        // Load the real address of the last static parameter. Do this by
        // loading the address of the last known static parameter and then
        // adding the value of [FRM].
        #emit CONST.alt        fstring
        #emit LCTRL          5
        #emit ADD
        #emit STOR.S.pri        arg_start

        // Load the address of the last variable parameter. Do this by adding
        // the number of variable parameters on the value just loaded.
        #emit LOAD.S.alt        n
        #emit ADD
        #emit STOR.S.pri        arg_end

        // Push the variable arguments. This is done by loading the value of
        // each one in reverse order and pushing them. I'd love to be able to
        // rewrite this to use the values of pri and alt for comparison,
        // instead of having to constantly load and reload two variables.
        do
        {
            #emit LOAD.I
            #emit PUSH.pri
            arg_end -= BYTES_PER_CELL;
            #emit LOAD.S.pri      arg_end
        }
        while (arg_end > arg_start);

        // Push the static format parameters.
        #emit PUSH.S          fstring
        #emit PUSH.C          128
        #emit PUSH.ADR         message

        // Now push the number of arguments passed to format, including both
        // static and variable ones and call the function.
        n += BYTES_PER_CELL * 3;
        #emit PUSH.S          n
        #emit SYSREQ.C         format

        // Remove all data, including the return value, from the stack.
        n += BYTES_PER_CELL;
        #emit LCTRL          4
        #emit LOAD.S.alt        n
        #emit ADD
        #emit SCTRL          4

        return SendClientMessage(playerid, color, message);
    }
    else
    {
        return SendClientMessage(playerid, color, fstring);
    }
}

Пример использования: http://pastebin.com/NbRVdDGM

P.S: возможно еще придется отдефайнить BYTES_PER_CELL дабы убить ошибку:

pawn Код:
#define BYTES_PER_CELL (cellbits / 8)
Reply
#30

Как уменьшить использование GetPlayerName(); да и для удобства замечательно.

Cоздаём в начале массив
pawn Код:
new PlayerName[MAX_PLAYERS][MAX_PLAYER_NAME];
Потом, мы идём в OnPlayerConnect() и пихаем это:
pawn Код:
GetPlayerName(playerid, PlayerName[playerid], MAX_PLAYER_NAME);
Ну и думаю понятно как использовать
Например, вывести в чат ник игрока: SendClientMessage(playerid, 0xFFFFFFFF, PlayerName[playerid]);
Reply
#31

Вот ещё: Тоже самое, с оружиями
массив:
pawn Код:
new WeaponName[47][32];
в OnGameModeInit/OnFilterScriptInit
pawn Код:
for(new i; i<47; i++)
    {
    if(i == 0) WeaponName[i] = "Fists";
    else if(i == 18) WeaponName[i] = "Molotov";
    else if(i == 44) WeaponName[i] = "Nightvision Goggles";
    else if(i == 45) WeaponName[i] = "Thermal Goggles";
    else GetWeaponName(i, WeaponName[i], 32);
    }
Reply
#32

Функция сортировки масива из С++ (Пузырьковая сортировка)

#define SortArray(%1) \
for(new i = sizeof(%1) - 1; i >= 1; i--) \
for(new j = 0; j < i; j++) \
{ \
if(%1[j] > %1[j + 1]) \
{ \
new foo = %1[j]; \
%1[j] = %1[j + 1]; \
%1[j + 1] = foo; \
} \
}

Функция возведения числа в степень (написал от нехер делать)

stock degree(Float:number, degree_n)
{
new Float:number_org = number;

for(new i = 1; i < degree_n; i++)
number *= number_org;
return number;
}
Reply
#33

Для тех, кто пользуется, моими функциями s/i/fparam - я изменил код так, чтобы предов при компиляции не было.
Reply
#34

всё равно багают.
Reply
#35

Quote:
Originally Posted by ^Psy
всё равно багают.
в случае багов, будь добр дать больше инфы, иначе толку от твоих "все равно багают"..
Reply
#36

Давече понадобилось запихать в одну ячейку несколько разных переменных, настряпал вот эти функции, авось кому тоже пригодится:

pawn Код:
stock upackcell(&cell, value, bit_start, max_bits)
{
    new mask;

    if (bit_start > 0)
    {
        mask = (cellmax << (bit_start + max_bits - 1) |
          (cellmax >> (cellbits - bit_start)));
        cell &= mask;
        cell |= ~mask & (value << (bit_start));
    }
    else
    {
        mask = (cellmax << (max_bits - 1));
        cell &= mask;
        cell |= ~mask & value;
    }
    return value;
}

stock uunpackcell(cell, bit_start, max_bits)
{
    if (bit_start > 0)
        return ((cell & ~(cellmax << bit_start + max_bits - 1)) >> bit_start);
    else
        return (cell & ~(cellmax << bit_start + max_bits - 1));
}

stock spackcell(&cell, value, bit_start, max_bits)
{
    return upackcell(cell, ~value, bit_start, max_bits);
}

stock sunpackcell(cell, bit_start, max_bits)
{
    return ~uunpackcell(cell, bit_start, max_bits);
}
bit_start - номер первого бита ячейки (отсчет ведется с младшего)
max_bits - размер пакуемого/вытаскиваемого значения в битах

первая пара функций для беззнаковых значений, вторая - для чисел со знаком
Reply
#37

#define HidePlayerDialog(%1) ShowPlayerDialog(%1,-1,0,"","","","")
Убирает диалог
Reply
#38

Функция для создания спавнов из 1-й координаты.

pawn Код:
new random3[5];
new Float:random0 = (random3[gTeam[playerid]] * 3.14) / (8.0 / 2.0);
new Float:random1 = floatcos(random0) * 3.0;
new Float:random2 = floatsin(random0) * 3.0;

random3[gTeam[playerid]]++;
random3[gTeam[playerid]] = random3[gTeam[playerid]] % 8;
Пример использования:
pawn Код:
new gTeam[MAX_PLAYERS];
new Base = 1;

new Float: SetSpawn[2][4] ={
{1733.6282,1068.9877,10.8203,91.8597},
{1661.1990,911.2530,10.7113,3.2558}
};

public OnPlayerSpawn(playerid)
{
    SetPlayerBase(playerid);
    return 1;
}

public SetPlayerBase(playerid)
{
new Float:random0 = (random3[gTeam[playerid]] * 3.14) / (8.0 / 2.0);
new Float:random1 = floatcos(random0) * 3.0;
new Float:random2 = floatsin(random0) * 3.0;

random3[gTeam[playerid]]++;
random3[gTeam[playerid]] = random3[gTeam[playerid]] % 8;
if(Base == 1) {
if(gTeam[playerid] == T_DEF) {
SetPlayerPos(playerid, random1 + SetSpawn[0][0], random2 + SetSpawn[0][1], SetSpawn[0][2]);
SetPlayerFacingAngle(playerid, SetSpawn[0][3]);
}
if(gTeam[playerid] == T_ATT) {
SetPlayerPos(playerid, random1 + SetSpawn[1][0], random2 + SetSpawn[1][1], SetSpawn[0][2]);
SetPlayerFacingAngle(playerid, SetSpawn[1][3]);
}
}
return 1;
}
Reply
#39

Подкиньте функцию нахождения высшего значения из массива / переменной.

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

сортировка методом булика не очень подходит
Reply
#40

Quote:
Originally Posted by JesterX
Мой вариант, был придуман на 3 лабе по дисциплине программирование:
Код:
 fact(n) {
  if(n <= 1) return 1;
  return n * fact(n - 1);
 }
А разве это не будет бесконечным циклом? )
Reply


Forum Jump:


Users browsing this thread: 2 Guest(s)