На примере возьмём систему домов.
Система домов записана в ассоциативный массив
#define MAX_HOUSES 1000 enum h_data{ h_handle, // id дома h_pickup_enter, // пикап вход в дом h_pickup_exit, // пикап выход из дома h_x,// позиция пикапа h_y,// позиция пикапа h_z// позиция пикапа }; new house_data[MAX_HOUSE][h_data];
Возьмём штатную ситуацию: игрок подбирает пикап дома и мы как скриптеры начинаем проверять пикап вот таким способом
public OnPlayerPickUpDynamicPickup(playerid, pickupid) { for(new i; i<MAX_HOUSE; i++) { if(pickupid == house[i][h_pickup_enter]) { printf("Номер дома: %d", house_data[i][h_handle]); break; } } }
Если закинуть на тест вот такой код станет ясно, немного медленно...
public OnPlayerPickUpDynamicPickup(playerid, pickupid) { new bool:isfind; new tick = GetTickCount(); for(new loop; loop<10000; loop++) { for(new i; i<MAX_HOUSE; i++) { if(pickupid == house[i][h_pickup_enter]) { isfind = true; break; } } } printf("IsFind: %d", isfind); printf("Tick count standart: %d", GetTickCount()-tick); }
код выполнится 10.000 раз за 874 мл.сек - почти секунда!
IsFind: 1 Tick count standart: 874
И теперь перейдём к самой функции из за которой и затеялся данный карнавал!
Streamer_SetIntData(type, STREAMER_ALL_TAGS:id, data, value) type - тип объекта (объект,пикап,актёр...) STREAMER_TYPE_OBJECT (0) STREAMER_TYPE_PICKUP (1) STREAMER_TYPE_CP (2) STREAMER_TYPE_RACE_CP (3) STREAMER_TYPE_MAP_ICON (4) STREAMER_TYPE_3D_TEXT_LABEL (5) STREAMER_TYPE_AREA (6) STREAMER_TYPE_ACTOR (7) STREAMER_ALL_TAGS:id - id стримерского элемента. data - "переменная" список стандартных enum { E_STREAMER_AREA_ID, E_STREAMER_ATTACHED_OBJECT, E_STREAMER_ATTACHED_PLAYER, E_STREAMER_ATTACHED_VEHICLE, E_STREAMER_ATTACH_OFFSET_X, E_STREAMER_ATTACH_OFFSET_Y, E_STREAMER_ATTACH_OFFSET_Z, E_STREAMER_ATTACH_R_X, E_STREAMER_ATTACH_R_Y, E_STREAMER_ATTACH_R_Z, E_STREAMER_ATTACH_X, E_STREAMER_ATTACH_Y, E_STREAMER_ATTACH_Z, E_STREAMER_COLOR, E_STREAMER_DRAW_DISTANCE, E_STREAMER_EXTRA_ID, E_STREAMER_HEALTH, E_STREAMER_INTERIOR_ID, E_STREAMER_INVULNERABLE, E_STREAMER_MAX_X, E_STREAMER_MAX_Y, E_STREAMER_MAX_Z, E_STREAMER_MIN_X, E_STREAMER_MIN_Y, E_STREAMER_MIN_Z, E_STREAMER_MODEL_ID, E_STREAMER_MOVE_R_X, E_STREAMER_MOVE_R_Y, E_STREAMER_MOVE_R_Z, E_STREAMER_MOVE_SPEED, E_STREAMER_MOVE_X, E_STREAMER_MOVE_Y, E_STREAMER_MOVE_Z, E_STREAMER_NEXT_X, E_STREAMER_NEXT_Y, E_STREAMER_NEXT_Z, E_STREAMER_PLAYER_ID, E_STREAMER_PRIORITY, E_STREAMER_ROTATION, E_STREAMER_R_X, E_STREAMER_R_Y, E_STREAMER_R_Z, E_STREAMER_SIZE, E_STREAMER_STREAM_DISTANCE, E_STREAMER_STYLE, E_STREAMER_SYNC_ROTATION, E_STREAMER_TEST_LOS, E_STREAMER_TYPE, E_STREAMER_WORLD_ID, E_STREAMER_X, E_STREAMER_Y, E_STREAMER_Z } Но мы будем использовать E_STREAMER_CUSTOM. value - данные.
Так же можно использовать
native Streamer_GetFloatData(type, STREAMER_ALL_TAGS:id, data, &Float:result); // получить число с плавоющей точкой, Float тип native Streamer_SetFloatData(type, STREAMER_ALL_TAGS:id, data, Float:value); // установить число с плавоющей точкой, Float тип native Streamer_GetIntData(type, STREAMER_ALL_TAGS:id, data); // получить целое число native Streamer_SetIntData(type, STREAMER_ALL_TAGS:id, data, value); // установить целое число native Streamer_RemoveIntData(type, STREAMER_ALL_TAGS:id, data); // удалить "переменную" native Streamer_HasIntData(type, STREAMER_ALL_TAGS:id, data); // существует ли что то в "переменной" native Streamer_GetArrayData(type, STREAMER_ALL_TAGS:id, data, dest[], maxdest = sizeof dest); // получить массив native Streamer_SetArrayData(type, STREAMER_ALL_TAGS:id, data, const src[], maxsrc = sizeof src); // записать массив native Streamer_IsInArrayData(type, STREAMER_ALL_TAGS:id, data, value); // есть ли число в массиве native Streamer_AppendArrayData(type, STREAMER_ALL_TAGS:id, data, value); //добавить данные в массив native Streamer_RemoveArrayData(type, STREAMER_ALL_TAGS:id, data, value); // удалить значение value из массив native Streamer_HasArrayData(type, STREAMER_ALL_TAGS:id, data); //существует ли массив native Streamer_GetArrayDataLength(type, STREAMER_ALL_TAGS:id, data); //получить колличество элементов в массиве
Данная функция предназначена для изменения данных будь это позиция,тип,текстура, какого либо стрим объекта (объект,пикап,актёр..) но с версией 2.9.5 появилась функция E_STREAMER_CUSTOM которая даёт возможность нам как бы прикрепить переменную к объекту и зная id объекта мы сможем получить как из моего примера id дома, появляется повод отказаться от циклов.
E_STREAMER_CUSTOM(0xFF) 0xFF - это наша как бы адрес переменной для объекта она должна быть уникальна.
#define CUSTUM_HOUSEID 0xFF #define E_STREAMER_HOUSE_PICKUP_ENTER E_STREAMER_CUSTOM(CUSTUM_HOUSEID)
Модернизируем наш код...
#define CUSTUM_HOUSEID 0xFF #define E_STREAMER_HOUSE_PICKUP_ENTER E_STREAMER_CUSTOM(CUSTUM_HOUSEID) #define SetPickUpHouseHandle(%0,%1) Streamer_SetIntData(STREAMER_TYPE_PICKUP, %0, E_STREAMER_HOUSE_PICKUP_ENTER, %1) #define GetPickUpHouseHandle(%0) Streamer_GetIntData(STREAMER_TYPE_PICKUP, %0, E_STREAMER_HOUSE_PICKUP_ENTER) // STREAMER_TYPE_PICKUP - потому что мы работаем с пикапом; /// SetPickUpHouseHandle(pickupid,value) //....... house[i][h_pickup_enter] = CreateDynamicPickup(1273, 2, house[i][h_x],house[i][h_y], house[i][h_z]); SetPickUpHouseHandle(house[i][h_pickup_enter],i); //....... public OnPlayerPickUpDynamicPickup(playerid, pickupid) { if(GetPickUpHouseHandle(pickupid) != 0) // примечание дома должны начинаться с 1, а не 0. 0 - не валидный дом! { printf("Номер дома: %d", GetPickUpHouseHandle(pickupid)); return 1; } }
Стример будет выбрасывать вот такое предупреждение
*** Streamer Plugin: Streamer_GetIntData: Invalid data specified.
Это будет означать, что переменная не существует.
Перед использованием E_STREAMER_CUSTOM рекомендуют проверять существует ли вообще такой адрес Streamer_HasIntData.
Я просто отключу данное сообщение с помощью функции Streamer_ToggleErrorCallback(true); в GameModeInit или OnFilterScriptInit().
При тестировании сразу поймём, почему стоит использовать E_STREAMER_CUSTOM
new pickupid = house[998][h_pickup_enter]; new = tick = GetTickCount(); new bool:isfind; for(new loop; loop<10000; loop++) { if(GetPickUpHouseHandle(pickupid) == 998) { isfind = true; } } printf("IsFind: %d", isfind); printf("Tick count standart: %d", GetTickCount()-tick);
Результат
IsFind: 1 Tick count custom: 2
Самому не верится, что в 400 раз быстрее делаем выводы.
Если посмотреть мои работы, они очень сырые и возможно данная статья сырая, так как полного знания терминов адрес это или переменная, как назвать правильно - не знаю. Я с удовольствием прочитаю отзыв каждого из вас, внесу правки. Возможно данный способ уже все используют. Не общаюсь с про скриптерами, но пока примеров с данным функционалом не встречал.
Какой я вижу потанцевал в этом?
Потенциал огромен. По сути мы можем использовать динамическую память стримера которую предоставил Y_Lees очень легко и просто.
Мы можем дать возможность игрокам выбрасывать предметы создавать их как объект и эти объекты не придётся заносить в массив. А потом бегать по массиву и искать является ли он предметом или нет, что это за объект. В этот момент чувствую себя неандертальцем с палкой в руке. Объект - есть переменная.
Так же мы можем привязывать группу объектов к объекту (под объектом имею введу любой элемент стримера) и удалять их синхронно. Создавать пикапы из нескольких объектов(элементов) вносить правки и другое как сказал без массивов и циклов.
..... new Float:x, Float:y, Float:z, Float:distance; GetPlayerPos(playerid, x, y, z); new pickups[1]; Streamer_GetAllVisibleItems(playerid, STREAMER_TYPE_PICKUP, pickups); // получаем список видимых пикапов сортируются по дистанции 0-самый ближайший. будем использовать самый ближайший хватит единичного размера if(GetPickUpHouseHandle(pickups[0]) != 0) { Streamer_GetDistanceToItem(x,y,z, STREAMER_TYPE_PICKUP, pickups[0], distance, 3); // dimensions = 3 используем дистанцию по трём осям. можно убрать. стандарт - 3. if(distance < 3.0) { printf("Рядом дом: %d", GetPickUpHouseHandle(pickups[0])); } } } .....
Теперь нам не придётся бегать по массиву и проверять каждый дом находится ли он рядом с игроком или нет. Мы просто получам ближайший пикап - читаем id дома и всё!
Считаю эта функция стала самым мощным обновлением стримера!
Копирование запрещено
Автор я: pawlo/vawylon
Сообщение отредактировал PAWLO: 15 мая 2022 - 16:47