но, т.к. реализация тех, что видел, не совсем понравилась и решил сделать, как бы её делал я.
Система не хитрая, можно дополнять и дополнять.
/create_radar [скорость] [радиус] - создаём радар
/delete_radar - удаляем радар
/edit_radar - редактируем радар
При нарушении, просто выдаёт сообщение, добавьте своё наказание.
Понадобиться наличие:
streamer
Pawn.CMD
Единственное, что делал без базы данных, есть некие неудобства, там в принципе только поменять загрузку и немного переделать создание, редактирование, удаление,
как подправлю и не забуду, то отрефакторю с сохранением в БД.
Где const и new
#define COLOR_RADAR_TEXT 0xF6F6F6FF #define COLOR_RADAR_WARNING 0xFF6347FF const MAX_RADAR = 100, Float: MIN_DISTANCE_TO_RADAR = 5.0, Float: MAX_RADAR_SPEED = 150.0, Float: MIN_RADAR_SPEED = 5.0, Float: MAX_RADAR_RANGE = 50.0, Float: MIN_RADAR_RANGE = 5.0, INVALID_RADAR_ID = -1, RADAR_OBJECT = 18880; new RADAR_TEXT_INFO[] = "Камера\n{87CEEB}Максимально допустимая скорость: {FF9900}%.0f км.", RADAR_TEXT_WARNING[] = "[Нарушение скорости] Скорость: {87CEEB}%d [лимит %.0f]{F6F6F6}. %s"; enum E_RADAR_INFO { E_RADAR_AREA, bool: E_RADAR_ACTIVE, Float: E_RADAR_POS_X, Float: E_RADAR_POS_Y, Float: E_RADAR_POS_Z, Float: E_RADAR_POS_A, Float: E_RADAR_RANGE, Float: E_RADAR_LIMIT, E_RADAR_OBJECT, Text3D: E_RADAR_TEXT3D }; new g_radar_info[MAX_RADAR][E_RADAR_INFO]; new NULL_g_radar_info[E_RADAR_INFO] = { INVALID_STREAMER_ID, false, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, INVALID_STREAMER_ID, Text3D:INVALID_STREAMER_ID }; enum E_PLAYER_RADAR_INFO { PLAYER_RADAR_EDIT } new g_player_radar_info[MAX_PLAYERS][E_PLAYER_RADAR_INFO]; new NULL_g_player_radar_info[E_PLAYER_RADAR_INFO] = { INVALID_RADAR_ID }; enum { STREAMER_TYPE_AREA_RADAR = 1 } enum E_STREAMER_RADAR_DATA { STREAMER_RADAR_TYPE, STREAMER_RADAR_ID } new g_player_radar_streamer_data[MAX_PLAYERS][E_STREAMER_RADAR_DATA]; new NULL_g_player_radar_streamer_data[E_STREAMER_RADAR_DATA] = { INVALID_STREAMER_ID, INVALID_RADAR_ID };

К stock`ам
stock bool: Radar_IsValid(radar_id) { return 0 <= radar_id <= MAX_RADAR - 1; } stock bool: Radar_IsValidSpeed(Float: speed) { return (floatcmp(speed, MIN_RADAR_SPEED) >= 0 && floatcmp(speed, MAX_RADAR_SPEED) <= 0); } stock bool: Radar_IsValidRange(Float: range) { return (floatcmp(range, MIN_RADAR_RANGE) >= 0 && floatcmp(range, MAX_RADAR_RANGE) <= 0); } stock Radar_GetFreeIndex() { for (new i = 0; i < MAX_RADAR; ++i) { if(g_radar_info[i][E_RADAR_AREA] == INVALID_STREAMER_ID) { return i; } } return INVALID_RADAR_ID; } stock Radar_IsPlayerNearRadar(playerid, radar_id, Float: distance = MIN_DISTANCE_TO_RADAR) { return (radar_id != INVALID_RADAR_ID && 0.0 < Radar_GetPlayerDistanceTo(playerid) <= distance); } stock Float: Radar_GetPlayerDistanceTo(playerid) { new Float: x, Float: y, Float: z; if (!GetPlayerPos(playerid, x, y, z)) { return 0.0; } new radar_id = g_player_radar_streamer_data[playerid][STREAMER_RADAR_ID]; if (radar_id == INVALID_RADAR_ID) { return 0.0; } return VectorSize(floatsub(x, g_radar_info[radar_id][E_RADAR_POS_X]), floatsub(y, g_radar_info[radar_id][E_RADAR_POS_Y]), floatsub(z, g_radar_info[radar_id][E_RADAR_POS_Z])); } stock Radar_DeleteMovePosInfo(radar_id) { if(g_radar_info[radar_id][E_RADAR_AREA] == NULL_g_radar_info[E_RADAR_AREA]) { return false; } DestroyDynamicArea(g_radar_info[radar_id][E_RADAR_AREA]); if (g_radar_info[radar_id][E_RADAR_OBJECT] != NULL_g_radar_info[E_RADAR_OBJECT]) { DestroyDynamicObject(g_radar_info[radar_id][E_RADAR_OBJECT]); } if (g_radar_info[radar_id][E_RADAR_TEXT3D] != NULL_g_radar_info[E_RADAR_TEXT3D]) { DestroyDynamic3DTextLabel(g_radar_info[radar_id][E_RADAR_TEXT3D]); } return true; } stock Radar_Delete(radar_id) { if(g_radar_info[radar_id][E_RADAR_AREA] == NULL_g_radar_info[E_RADAR_AREA]) { return false; } Radar_DeleteMovePosInfo(radar_id); g_radar_info[radar_id] = NULL_g_radar_info; return true; } stock Radar_UpdateMovePosInfo(radar_id) { if(!Radar_IsValid(radar_id)) { return false; } Radar_DeleteMovePosInfo(radar_id); new string[sizeof(RADAR_TEXT_INFO) + (-2 + 3)]; format(string, sizeof(string), RADAR_TEXT_INFO, g_radar_info[radar_id][E_RADAR_LIMIT]); g_radar_info[radar_id][E_RADAR_TEXT3D] = CreateDynamic3DTextLabel( string, COLOR_RADAR_TEXT, g_radar_info[radar_id][E_RADAR_POS_X], g_radar_info[radar_id][E_RADAR_POS_Y], g_radar_info[radar_id][E_RADAR_POS_Z]+2.5, 15.0, INVALID_PLAYER_ID, INVALID_VEHICLE_ID, 0); g_radar_info[radar_id][E_RADAR_OBJECT] = CreateDynamicObject( RADAR_OBJECT, g_radar_info[radar_id][E_RADAR_POS_X], g_radar_info[radar_id][E_RADAR_POS_Y], g_radar_info[radar_id][E_RADAR_POS_Z], 0.0, 0.0, g_radar_info[radar_id][E_RADAR_POS_A]); g_radar_info[radar_id][E_RADAR_AREA] = CreateDynamicCircle( g_radar_info[radar_id][E_RADAR_POS_X], g_radar_info[radar_id][E_RADAR_POS_Y], g_radar_info[radar_id][E_RADAR_RANGE], 0, 0); new array_data[E_STREAMER_RADAR_DATA]; array_data[STREAMER_RADAR_TYPE] = STREAMER_TYPE_AREA_RADAR; array_data[STREAMER_RADAR_ID] = radar_id; Streamer_SetArrayData(STREAMER_TYPE_AREA, g_radar_info[radar_id][E_RADAR_AREA], E_STREAMER_EXTRA_ID, array_data, sizeof(array_data)); return true; } stock Radar_Create(radar_id, Float: x, Float: y, Float: z, Float: a, Float: limit, Float: range) { if (!Radar_IsValid(radar_id) || g_radar_info[radar_id][E_RADAR_ACTIVE]) { return false; } g_radar_info[radar_id][E_RADAR_ACTIVE] = true; g_radar_info[radar_id][E_RADAR_RANGE] = range; g_radar_info[radar_id][E_RADAR_LIMIT] = limit; g_radar_info[radar_id][E_RADAR_POS_X] = x; g_radar_info[radar_id][E_RADAR_POS_Y] = y; g_radar_info[radar_id][E_RADAR_POS_Z] = z; g_radar_info[radar_id][E_RADAR_POS_A] = a; Radar_UpdateMovePosInfo(radar_id); return true; } stock Radar_PlayerCreate(playerid, id, Float: limit, Float: range) { new Float: x, Float: y, Float: z; if (!GetPlayerPos(playerid, x, y, z)) { return false; } new Float: angle; GetPlayerFacingAngle(playerid, angle); x = floatadd(x, (1.5 * floatsin(-angle, degrees))); y = floatadd(y, (1.5 * floatcos(-angle, degrees))); z = floatsub(z, 1.2); if (!Radar_Create(id, x, y, z, angle, limit, range)) { return false; } g_player_radar_info[playerid][PLAYER_RADAR_EDIT] = id; EditDynamicObject(playerid, g_radar_info[id][E_RADAR_OBJECT]); return true; } forward Radar_Load(); public Radar_Load() { new count = 0; for (new i = 0; i < MAX_RADAR; ++i) { if (g_radar_info[i][E_RADAR_AREA] == NULL_g_radar_info[E_RADAR_AREA]) { continue; } if (g_radar_info[i][E_RADAR_OBJECT] != NULL_g_radar_info[E_RADAR_OBJECT]) { DestroyDynamicObject(g_radar_info[i][E_RADAR_OBJECT]); } if (g_radar_info[i][E_RADAR_TEXT3D] != NULL_g_radar_info[E_RADAR_TEXT3D]) { DestroyDynamic3DTextLabel(g_radar_info[i][E_RADAR_TEXT3D]); } Radar_UpdateMovePosInfo(i); count++; } printf("[RADARS]: Система радаров загружена. Всего: %d", count); for (new i = 0; i < MAX_PLAYERS; ++i) { g_player_radar_info[i] = NULL_g_player_radar_info; g_player_radar_streamer_data[i] = NULL_g_player_radar_streamer_data; } return true; } stock Radar_LeaveAreaProcess(playerid, areaid) { new array_data[E_STREAMER_RADAR_DATA]; if (!Streamer_GetArrayData(STREAMER_TYPE_AREA, areaid, E_STREAMER_EXTRA_ID, array_data, sizeof(array_data)) || array_data[STREAMER_RADAR_TYPE] != STREAMER_TYPE_AREA_RADAR) { return false; } g_player_radar_streamer_data[playerid] = NULL_g_player_radar_streamer_data; return true; } stock Radar_EnterAreaProcess(playerid, areaid) { new array_data[E_STREAMER_RADAR_DATA]; if (!Streamer_GetArrayData(STREAMER_TYPE_AREA, areaid, E_STREAMER_EXTRA_ID, array_data, sizeof(array_data)) || array_data[STREAMER_RADAR_TYPE] != STREAMER_TYPE_AREA_RADAR) { return false; } g_player_radar_streamer_data[playerid] = array_data; if (!(GetPlayerState(playerid) == PLAYER_STATE_DRIVER)) { return false; } new vehicle_id = GetPlayerVehicleID(playerid), vehicle_speed = GetVehicleSpeed(vehicle_id), radar = array_data[STREAMER_RADAR_ID]; if (vehicle_speed > g_radar_info[radar][E_RADAR_LIMIT]) { new radar_str[sizeof(RADAR_TEXT_WARNING) + (-2 + 3) + (-4 + 4)]; format(radar_str, sizeof(radar_str), RADAR_TEXT_WARNING, vehicle_speed, g_radar_info[radar][E_RADAR_LIMIT]); SendClientMessage(playerid, COLOR_RADAR_WARNING, radar_str); } return true; } stock Radar_EditObjectProcess(playerid, response, Float:x, Float:y, Float:z, Float:rz) { /* 0 - EDIT_RESPONSE_CANCEL // player cancelled (ESC) 1 - EDIT_RESPONSE_FINAL // player clicked on save 2 - EDIT_RESPONSE_UPDATE // player moved the object (edition did not stop at all) */ new edit_radar_id = g_player_radar_info[playerid][PLAYER_RADAR_EDIT]; if(edit_radar_id == INVALID_RADAR_ID || !(EDIT_RESPONSE_CANCEL <= response <= EDIT_RESPONSE_FINAL)) { return false; } g_radar_info[edit_radar_id][E_RADAR_POS_X] = x; g_radar_info[edit_radar_id][E_RADAR_POS_Y] = y; g_radar_info[edit_radar_id][E_RADAR_POS_Z] = z; g_radar_info[edit_radar_id][E_RADAR_POS_A] = rz; Radar_UpdateMovePosInfo(edit_radar_id); g_player_radar_info[playerid] = NULL_g_player_radar_info; return true; }

В OnPlayerEditDynamicObject
Radar_EditObjectProcess(playerid, response, Float:x, Float:y, Float:z, Float:rz);

В OnPlayerEnterDynamicArea
Radar_EnterAreaProcess(playerid, areaid);

В OnPlayerLeaveDynamicArea
Radar_LeaveAreaProcess(playerid, areaid);

В OnGameModeInit
Radar_Load();

Ко всем командам
CMD:create_radar(playerid, params[]) { new Float: limit, Float: range; if (sscanf(params, "fF(30.0)", limit, range)) { return SendClientMessage(playerid, COLOR_WHITE, "/create_radar [ограничение] [радиус] {FF9900}(Стандартный радиус: 30)"); } if (!Radar_IsValidSpeed(limit)) { static const fmt_text[] = "Ограничение скорости может быть от %.0f до %.0f км./час."; new string[sizeof(fmt_text) + (-2 + 5) + (-2 + 5)]; format(string, sizeof(string), fmt_text, MIN_RADAR_SPEED, MAX_RADAR_SPEED); return SendClientMessage(playerid, -1, string); } if (!Radar_IsValidRange(range)) { static const fmt_text[] = "Радус действия радара может быть от %.0f до %.0f м."; new string[sizeof(fmt_text) + (-2 + 5) + (-2 + 5)]; format(string, sizeof(string), fmt_text, MIN_RADAR_RANGE, MAX_RADAR_RANGE); return SendClientMessage(playerid, -1, string); } new radar_id = g_player_radar_streamer_data[playerid][STREAMER_RADAR_ID]; if (Radar_IsPlayerNearRadar(playerid, radar_id, .distance = MAX_RADAR_RANGE)) { return SendClientMessage(playerid, -1, "Рядом с вами уже есть радар."); } new id = Radar_GetFreeIndex(); if(id == INVALID_RADAR_ID) { return SendClientMessage(playerid, -1, "Достигнуто максимальное количество радаров."); } Radar_PlayerCreate(playerid, id, limit, range); return true; } CMD:del_radar(playerid, params[]) { new radar_id = g_player_radar_streamer_data[playerid][STREAMER_RADAR_ID]; if(!Radar_IsPlayerNearRadar(playerid, radar_id)) { return SendClientMessage(playerid, -1, "Рядом с Вами нет скоростного радара"); } Radar_Delete(radar_id); SendClientMessage(playerid, -1, "Вы успешно удалили радар рядом с Вами"); return true; } CMD:edit_radar(playerid, params[]) { new radar_id = g_player_radar_streamer_data[playerid][STREAMER_RADAR_ID]; if(!Radar_IsPlayerNearRadar(playerid, radar_id)) { return SendClientMessage(playerid, -1, "Рядом с Вами нет скоростного радара"); } g_player_radar_info[playerid][PLAYER_RADAR_EDIT] = radar_id; EditDynamicObject(playerid, g_radar_info[radar_id][E_RADAR_OBJECT]); return true; }

P.S. табуляцию меняет сам сайт, не знаю как сделать, чтобы было в точности, как у меня.
Сообщение отредактировал ex4mpl3: 18 марта 2023 - 11:50
Причина редактирования: табуляция вместо пробелов