Archives
Trending
Support
Login
clear text
XML
Django
JavaScript
MATLAB
C
C++
C#
Python
SQL
Shell
Bash
Markdown
YAML
JSON
HTML
CSS
PHP
Java
Ruby
Go
Rust
Swift
Kotlin
Arduino
TypeScript
Perl
Autohotkey
Lua
SQF
R
Scala
Haskell
Groovy
Dart
Clojure
VB.NET
Objective-C
PowerShell
Bash
CoffeeScript
Verilog
// ==================== РЕАЛИЗАЦИЯ СИСТЕМЫ СЦЕН ==================== // Создание сцены stock EventEngine:CreateScene(event_id, const name[], task_min, task_max, flags) { if (g_EventEngine_SceneCount >= MAX_SCENES) { printf("[EventEngine] Ошибка: Достигнут лимит сцен (%d)", MAX_SCENES); return EVENT_INVALID_VALUE; } new scene_id = g_EventEngine_SceneCount; g_EventEngine_Scenes[scene_id][E_SCENE_ID] = scene_id; g_EventEngine_Scenes[scene_id][E_SCENE_EVENT_ID] = event_id; format(g_EventEngine_Scenes[scene_id][E_SCENE_NAME], 32, name); g_EventEngine_Scenes[scene_id][E_SCENE_TASK_MIN] = task_min; g_EventEngine_Scenes[scene_id][E_SCENE_TASK_MAX] = task_max; g_EventEngine_Scenes[scene_id][E_SCENE_FLAGS] = flags; g_EventEngine_Scenes[scene_id][E_SCENE_ENTITY_COUNT] = 0; g_EventEngine_Scenes[scene_id][E_SCENE_ZONE_ID] = EVENT_INVALID_VALUE; g_EventEngine_Scenes[scene_id][E_SCENE_ACTIVE] = false; g_EventEngine_SceneCount++; printf("[EventEngine] Создана сцена '%s' (ID: %d, Задания: %d-%d)", name, scene_id, task_min, task_max); return scene_id; } // Добавление сущности в сцену stock EventEngine:AddSceneEntity(scene_id, E_SCENE_ENTITY_TYPE:type, Float:x, Float:y, Float:z, ...) { if (scene_id < 0 || scene_id >= g_EventEngine_SceneCount) return false; if (g_EventEngine_Scenes[scene_id][E_SCENE_ENTITY_COUNT] >= MAX_SCENE_ENTITIES) { printf("[EventEngine] Ошибка: Достигнут лимит сущностей в сцене %d", scene_id); return false; } new entity_index = g_EventEngine_Scenes[scene_id][E_SCENE_ENTITY_COUNT]; new entity[E_SCENE_ENTITY]; entity[E_ENTITY_TYPE] = _:type; entity[E_ENTITY_ID] = EVENT_INVALID_VALUE; // Будет установлен при активации entity[E_ENTITY_X] = x; entity[E_ENTITY_Y] = y; entity[E_ENTITY_Z] = z; // Обработка дополнительных параметров в зависимости от типа switch (type) { case SCENE_ENTITY_OBJECT: { entity[E_ENTITY_REFERENCE] = getarg(3); // modelid entity[E_ENTITY_RX] = Float:getarg(4); entity[E_ENTITY_RY] = Float:getarg(5); entity[E_ENTITY_RZ] = Float:getarg(6); } case SCENE_ENTITY_VEHICLE: { entity[E_ENTITY_REFERENCE] = getarg(3); // modelid entity[E_ENTITY_RZ] = Float:getarg(4); // rotation } case SCENE_ENTITY_NPC, SCENE_ENTITY_ACTOR: { entity[E_ENTITY_REFERENCE] = getarg(3); // skin/model entity[E_ENTITY_RZ] = Float:getarg(4); // rotation } case SCENE_ENTITY_SOUND: { entity[E_ENTITY_REFERENCE] = getarg(3); // sound name (через хэш) entity[E_ENTITY_RADIUS] = Float:getarg(4); // радиус звука } case SCENE_ENTITY_WEATHER: { entity[E_ENTITY_REFERENCE] = getarg(3); // weather id } case SCENE_ENTITY_TIME: { entity[E_ENTITY_REFERENCE] = getarg(3); // hour entity[E_ENTITY_EXTRA_1] = getarg(4); // minute } case SCENE_ENTITY_ZONE: { entity[E_ENTITY_RADIUS] = Float:getarg(3); // радиус зоны } } // Копируем сущность в сцену g_EventEngine_Scenes[scene_id][E_SCENE_ENTITIES][entity_index] = entity; g_EventEngine_Scenes[scene_id][E_SCENE_ENTITY_COUNT]++; printf("[EventEngine] Добавлена сущность типа %d в сцену %d", _:type, scene_id); return true; } // Активация сцены для игрока stock EventEngine:ActivatePlayerScene(playerid, scene_id) { if (scene_id < 0 || scene_id >= g_EventEngine_SceneCount) return false; if (g_EventEngine_PlayerScenes[playerid][E_PLAYER_SCENE_COUNT] >= MAX_PLAYER_SCENES) { printf("[EventEngine] Ошибка: У игрока %d достигнут лимит активных сцен", playerid); return false; } // Проверяем, не активирована ли уже сцена if (EventEngine:IsSceneActiveForPlayer(playerid, scene_id)) return true; new scene[E_SCENE_DATA]; scene = g_EventEngine_Scenes[scene_id]; // Сохраняем исходные настройки игрока при первой активации сцены if (g_EventEngine_PlayerScenes[playerid][E_PLAYER_SCENE_COUNT] == 0) { g_EventEngine_PlayerScenes[playerid][E_PLAYER_CURRENT_WEATHER] = GetPlayerWeather(playerid); g_EventEngine_PlayerScenes[playerid][E_PLAYER_CURRENT_TIME] = GetPlayerTime(playerid); g_EventEngine_PlayerScenes[playerid][E_PLAYER_CURRENT_INTERIOR] = GetPlayerInterior(playerid); g_EventEngine_PlayerScenes[playerid][E_PLAYER_CURRENT_WORLD] = GetPlayerVirtualWorld(playerid); } // Создаем сущности сцены for (new i = 0; i < scene[E_SCENE_ENTITY_COUNT]; i++) { new entity[E_SCENE_ENTITY] = scene[E_SCENE_ENTITIES][i]; switch (E_SCENE_ENTITY_TYPE:entity[E_ENTITY_TYPE]) { case SCENE_ENTITY_OBJECT: { new object_id = CreateDynamicObject( entity[E_ENTITY_REFERENCE], entity[E_ENTITY_X], entity[E_ENTITY_Y], entity[E_ENTITY_Z], entity[E_ENTITY_RX], entity[E_ENTITY_RY], entity[E_ENTITY_RZ], .worldid = playerid, // Индивидуальный мир для игрока .interiorid = GetPlayerInterior(playerid) ); entity[E_ENTITY_ID] = object_id; } case SCENE_ENTITY_VEHICLE: { new vehicle_id = CreateVehicle( entity[E_ENTITY_REFERENCE], entity[E_ENTITY_X], entity[E_ENTITY_Y], entity[E_ENTITY_Z], entity[E_ENTITY_RZ], -1, -1, -1, 0 // Прозрачные цвета ); SetVehicleVirtualWorld(vehicle_id, playerid + 1000); // Индивидуальный виртуальный мир entity[E_ENTITY_ID] = vehicle_id; } case SCENE_ENTITY_NPC: { // Создание NPC в индивидуальном мире new npc_id = NPC_Create( entity[E_ENTITY_REFERENCE], entity[E_ENTITY_X], entity[E_ENTITY_Y], entity[E_ENTITY_Z], entity[E_ENTITY_RZ], .worldid = playerid + 1000 ); entity[E_ENTITY_ID] = npc_id; } case SCENE_ENTITY_SOUND: { // Воспроизведение 3D звука Sound:Play3D( entity[E_ENTITY_REFERENCE], // Имя звукового файла entity[E_ENTITY_X], entity[E_ENTITY_Y], entity[E_ENTITY_Z], .min_distance = 5.0, .max_distance = entity[E_ENTITY_RADIUS], .initiator_system = SOUND_SYSTEM_EVENT_SCENE ); } case SCENE_ENTITY_WEATHER: { SetPlayerWeather(playerid, entity[E_ENTITY_REFERENCE]); } case SCENE_ENTITY_TIME: { SetPlayerTime(playerid, entity[E_ENTITY_REFERENCE], entity[E_ENTITY_EXTRA_1]); } case SCENE_ENTITY_INTERIOR: { SetPlayerInterior(playerid, entity[E_ENTITY_REFERENCE]); } } // Сохраняем обновленную сущность g_EventEngine_Scenes[scene_id][E_SCENE_ENTITIES][i] = entity; } // Добавляем сцену в список активных сцен игрока g_EventEngine_PlayerScenes[playerid][E_PLAYER_ACTIVE_SCENES][g_EventEngine_PlayerScenes[playerid][E_PLAYER_SCENE_COUNT]] = scene_id; g_EventEngine_PlayerScenes[playerid][E_PLAYER_SCENE_COUNT]++; g_EventEngine_Scenes[scene_id][E_SCENE_ACTIVE] = true; // Вызываем callback активации if (funcidx("OnPlayerSceneActivate") != -1) { CallLocalFunction("OnPlayerSceneActivate", "ii", playerid, scene_id); } printf("[EventEngine] Активирована сцена %d для игрока %d", scene_id, playerid); return true; } // Деактивация сцены для игрока stock EventEngine:DeactivatePlayerScene(playerid, scene_id) { if (!EventEngine:IsSceneActiveForPlayer(playerid, scene_id)) return true; new scene[E_SCENE_DATA]; scene = g_EventEngine_Scenes[scene_id]; // Удаляем сущности сцены for (new i = 0; i < scene[E_SCENE_ENTITY_COUNT]; i++) { new entity[E_SCENE_ENTITY] = scene[E_SCENE_ENTITIES][i]; switch (E_SCENE_ENTITY_TYPE:entity[E_ENTITY_TYPE]) { case SCENE_ENTITY_OBJECT: { if (entity[E_ENTITY_ID] != EVENT_INVALID_VALUE) { DestroyDynamicObject(entity[E_ENTITY_ID]); } } case SCENE_ENTITY_VEHICLE: { if (entity[E_ENTITY_ID] != EVENT_INVALID_VALUE) { DestroyVehicle(entity[E_ENTITY_ID]); } } case SCENE_ENTITY_NPC: { if (entity[E_ENTITY_ID] != EVENT_INVALID_VALUE) { NPC_Destroy(entity[E_ENTITY_ID]); } } case SCENE_ENTITY_SOUND: { Sound:Stop3D(entity[E_ENTITY_REFERENCE], entity[E_ENTITY_X], entity[E_ENTITY_Y], entity[E_ENTITY_Z]); } case SCENE_ENTITY_WEATHER: { // Восстанавливаем исходную погоду при удалении последней сцены if (g_EventEngine_PlayerScenes[playerid][E_PLAYER_SCENE_COUNT] == 1) { SetPlayerWeather(playerid, g_EventEngine_PlayerScenes[playerid][E_PLAYER_CURRENT_WEATHER]); } } case SCENE_ENTITY_TIME: { if (g_EventEngine_PlayerScenes[playerid][E_PLAYER_SCENE_COUNT] == 1) { ResetPlayerTime(playerid); } } } // Сбрасываем ID сущности entity[E_ENTITY_ID] = EVENT_INVALID_VALUE; g_EventEngine_Scenes[scene_id][E_SCENE_ENTITIES][i] = entity; } // Удаляем сцену из списка активных for (new i = 0; i < g_EventEngine_PlayerScenes[playerid][E_PLAYER_SCENE_COUNT]; i++) { if (g_EventEngine_PlayerScenes[playerid][E_PLAYER_ACTIVE_SCENES][i] == scene_id) { // Сдвигаем остальные сцены for (new j = i; j < g_EventEngine_PlayerScenes[playerid][E_PLAYER_SCENE_COUNT] - 1; j++) { g_EventEngine_PlayerScenes[playerid][E_PLAYER_ACTIVE_SCENES][j] = g_EventEngine_PlayerScenes[playerid][E_PLAYER_ACTIVE_SCENES][j + 1]; } g_EventEngine_PlayerScenes[playerid][E_PLAYER_SCENE_COUNT]--; break; } } g_EventEngine_Scenes[scene_id][E_SCENE_ACTIVE] = false; // Вызываем callback деактивации if (funcidx("OnPlayerSceneDeactivate") != -1) { CallLocalFunction("OnPlayerSceneDeactivate", "ii", playerid, scene_id); } printf("[EventEngine] Деактивирована сцена %d для игрока %d", scene_id, playerid); return true; } // Автоматическое обновление сцен при смене задания stock EventEngine:UpdatePlayerScenes(playerid, current_task) { printf("[EventEngine] Обновление сцен для игрока %d (задание: %d)", playerid, current_task); // Деактивируем сцены, которые больше не подходят for (new i = 0; i < g_EventEngine_PlayerScenes[playerid][E_PLAYER_SCENE_COUNT]; i++) { new scene_id = g_EventEngine_PlayerScenes[playerid][E_PLAYER_ACTIVE_SCENES][i]; new scene[E_SCENE_DATA] = g_EventEngine_Scenes[scene_id]; if (current_task < scene[E_SCENE_TASK_MIN] || current_task > scene[E_SCENE_TASK_MAX]) { if (scene[E_SCENE_FLAGS] & SCENE_FLAG_AUTO_DESTROY) { EventEngine:DeactivatePlayerScene(playerid, scene_id); i--; // Уменьшаем счетчик т.к. массив сдвинулся } } } // Активируем подходящие сцены for (new scene_id = 0; scene_id < g_EventEngine_SceneCount; scene_id++) { new scene[E_SCENE_DATA] = g_EventEngine_Scenes[scene_id]; // Проверяем, подходит ли сцена по заданию и мероприятию if (scene[E_SCENE_EVENT_ID] == g_EventEngine_ActiveEvent && current_task >= scene[E_SCENE_TASK_MIN] && current_task <= scene[E_SCENE_TASK_MAX] && !EventEngine:IsSceneActiveForPlayer(playerid, scene_id)) { EventEngine:ActivatePlayerScene(playerid, scene_id); } } } // Проверка активности сцены для игрока stock EventEngine:IsSceneActiveForPlayer(playerid, scene_id) { for (new i = 0; i < g_EventEngine_PlayerScenes[playerid][E_PLAYER_SCENE_COUNT]; i++) { if (g_EventEngine_PlayerScenes[playerid][E_PLAYER_ACTIVE_SCENES][i] == scene_id) return true; } return false; } // Уничтожение всех сцен игрока stock EventEngine:DestroyPlayerScenes(playerid, bool:keep_persistent = false) { printf("[EventEngine] Уничтожение сцен для игрока %d (persistent: %d)", playerid, _:keep_persistent); for (new i = 0; i < g_EventEngine_PlayerScenes[playerid][E_PLAYER_SCENE_COUNT]; i++) { new scene_id = g_EventEngine_PlayerScenes[playerid][E_PLAYER_ACTIVE_SCENES][i]; new scene[E_SCENE_DATA] = g_EventEngine_Scenes[scene_id]; if (keep_persistent && (scene[E_SCENE_FLAGS] & SCENE_FLAG_PERSISTENT)) continue; EventEngine:DeactivatePlayerScene(playerid, scene_id); i--; // Уменьшаем счетчик т.к. массив сдвинулся } // Восстанавливаем исходные настройки if (g_EventEngine_PlayerScenes[playerid][E_PLAYER_SCENE_COUNT] == 0) { SetPlayerWeather(playerid, g_EventEngine_PlayerScenes[playerid][E_PLAYER_CURRENT_WEATHER]); ResetPlayerTime(playerid); SetPlayerInterior(playerid, g_EventEngine_PlayerScenes[playerid][E_PLAYER_CURRENT_INTERIOR]); SetPlayerVirtualWorld(playerid, g_EventEngine_PlayerScenes[playerid][E_PLAYER_CURRENT_WORLD]); } } // Интеграция с системой заданий - обновляем при смене задания stock EventEngine:SetPlayerTask(playerid, task_id, bool:is_on_login = false) { // ... существующий код смены задания ... // Обновляем сцены после смены задания EventEngine:UpdatePlayerScenes(playerid, task_id); // ... остальной код ... } // Обработка отключения игрока public OnPlayerDisconnect(playerid, reason) { EventEngine:DestroyPlayerScenes(playerid, false); // ... остальной код ... return 1; } // Обработка выхода из зоны public OnPlayerLeaveDynamicArea(playerid, areaid) { for (new i = 0; i < g_EventEngine_PlayerScenes[playerid][E_PLAYER_SCENE_COUNT]; i++) { new scene_id = g_EventEngine_PlayerScenes[playerid][E_PLAYER_ACTIVE_SCENES][i]; new scene[E_SCENE_DATA] = g_EventEngine_Scenes[scene_id]; if ((scene[E_SCENE_FLAGS] & SCENE_FLAG_ZONE_BASED) && scene[E_SCENE_ZONE_ID] == areaid) { EventEngine:DeactivatePlayerScene(playerid, scene_id); i--; } } return 1; } // Пример создания сцены для задания "Поиск реквизита" public Circus_OnTaskInit(task_id) { if (task_id == TASK_FIND_PROPS) { // Создаем сцену с реквизитом в цирке new scene_id = EventEngine:CreateScene( EVENT_CIRCUS, "Реквизит цирка", TASK_FIND_PROPS, TASK_FIND_PROPS_FINISH, SCENE_FLAG_AUTO_DESTROY ); // Добавляем объекты реквизита EventEngine:AddSceneEntity(scene_id, SCENE_ENTITY_OBJECT, 35.8412, 1945.6732, 9.8203, 19315, 0.0, 0.0, 0.0); // Ящик с реквизитом EventEngine:AddSceneEntity(scene_id, SCENE_ENTITY_OBJECT, 33.1289, 1943.4512, 9.8203, 19632, 0.0, 0.0, 90.0); // Костюмы // Добавляем NPC охраны EventEngine:AddSceneEntity(scene_id, SCENE_ENTITY_NPC, 37.2198, 1942.1289, 9.8203, 71, 180.0); // Охранник // Добавляем атмосферный звук EventEngine:AddSceneEntity(scene_id, SCENE_ENTITY_SOUND, 35.0, 1945.0, 10.0, "circus/ambient/storage.mp3", 15.0); } } // Пример сцены с транспортом для задания доставки public Circus_OnPlayerStartTask(playerid, sub_task) { new task_id = EventEngine:GetPlayerTask(playerid); if (task_id == TASK_DELIVER_PROPS) { // Создаем индивидуальный транспорт для доставки new scene_id = EventEngine:CreateScene( EVENT_CIRCUS, "Транспорт доставки", TASK_DELIVER_PROPS, TASK_DELIVER_PROPS_FINISH, SCENE_FLAG_AUTO_DESTROY ); // Добавляем фургон для доставки EventEngine:AddSceneEntity(scene_id, SCENE_ENTITY_VEHICLE, 45.2198, 1950.1289, 10.1203, 498, 270.0); // Фургон Boxville // Устанавливаем погоду для атмосферы EventEngine:AddSceneEntity(scene_id, SCENE_ENTITY_WEATHER, 0.0, 0.0, 0.0, 8); // Туманная погода // Устанавливаем вечернее время EventEngine:AddSceneEntity(scene_id, SCENE_ENTITY_TIME, 0.0, 0.0, 0.0, 20, 0); // 20:00 } }
Mark as private (unlisted)
for 30 minutes
for 6 hours
for 1 day
for 1 week
for 1 month
for 1 year
everlasting (like CCCP)