---------------------------------------------------------------------------------------- -------------------------------- Система "Два дракона и сундук" ------------------------ ---------------------------------------------------------------------------------------- -- Активность "Охота за сундуком" - игроки охотятся за сундуком, который появляется на карте -------------------------------------------------------------------------------------- -- Глобальные переменные активности -------------------------------------------------------------------------------------- BaoXiang_ID = 4500028 -- ID предмета сундука DuoBaoQiBing_Active_ID = 27 -- ID активности "Два дракона и сундук" ERS_HoldChest = 16777216 -- Статус "несет сундук" (0x1000000) HoldChest_BuffID = 9003301 -- ID баффа для носителя сундука ERS_SafeArea = 16 -- Статус безопасной зоны (0x0010) -- Константы событий C++ ESRE_OnChaseHolderDie = 44 -- Событие смерти носителя сундука ESRE_ForceLootChase = 45 -- Событие принудительного отнятия сундука ESIE_CanUse = 0 -- Проверка возможности использования предмета ESIE_CanDelGroundItem = 2 -- Проверка возможности удаления предмета с земли ESIE_PutDownItem = 3 -- Событие бросания предмета ESIE_CanPickUpItem = 4 -- Проверка возможности поднятия предмета ESIE_PickUpItem = 5 -- Событие поднятия предмета ESIE_CanPutDown = 6 -- Проверка возможности бросания предмета ESIE_CanDelItemOnRoleInit = 7 -- Проверка необходимости удаления предмета при инициализации персонажа ESAE_OnTimer = 1 -- Событие таймера активности ESAE_OnStart = 2 -- Событие начала активности ESAE_OnEnd = 3 -- Событие окончания активности ESAE_OnTimerMin = 4 -- Событие ежесекундного таймера ESAE_OnActOpenClose = 9 -- Событие открытия/закрытия активности через админ-панель -- Состояния движения персонажа EMS_Swim = 6 -- Плавание EMS_SwimStand = 7 -- Стояние в воде -- Коды ошибок для поднятия сундука E_Loot_Swim_Can_Not_Pickup_BaoXiang = 11 -- Невозможно поднять сундук во время плавания E_Loot_Role_Level_Limit = 12 -- Уровень персонажа не соответствует требованиям E_Loot_Role_SafeArea_Limit = 13 -- Невозможно поднять сундук в безопасной зоне -- Таблица дней недели EWeekDay = {["Sunday"] = 1, ["Monday"] = 2, ["Tuesday"] = 3, ["Wednesday"] = 4, ["Thursday"] = 5, ["Friday"] = 6, ["Saturday"] = 7} -------------------------------------------------------------------------------------- -- Настраиваемые точки спавна сундука (x/z в tile-координатах как в большинстве скриптов) -- MapID для s03 = 3424073256 (см. `server_data/script/Map/s03/s03.lua`) -- Добавляй сюда свои точки: {map = MAP_ID, x = X, z = Z} -------------------------------------------------------------------------------------- BaoXiang_SpawnPoints = { { map = 3424073256, x = 532, z = 1266 }, { map = 3424073256, x = 600, z = 1200 }, { map = 3424073256, x = 650, z = 1350 }, } -------------------------------------------------------------------------------------- -- Переменные состояния активности -------------------------------------------------------------------------------------- BaoXiang_SerialID_High = 0 -- Серийный ID сундука (старшая часть) BaoXiang_SerialID_Low = 0 -- Серийный ID сундука (младшая часть) BaoXiang_GroupID_High = 0 -- ID группы сундука (старшая часть) BaoXiang_GroupID_Low = 0 -- ID группы сундука (младшая часть) BaoXiang_MapID = 0 -- ID карты с сундуком BaoXiang_X = 0 -- Координата X сундука BaoXiang_Z = 0 -- Координата Z сундука BaoXiang_Holder = 0 -- ID игрока, несущего сундук Min_Counter = 0 -- Счетчик минут Active_Started = 0 -- Флаг начала активности Active_End = 0 -- Флаг окончания активности BaoXiang_OpenRemainTime = BaoXiang_CDTime -- Оставшееся время до открытия сундука (в секундах) Tick_Count = 0 -- Счетчик тиков BaoXiang_UpdateRemainTime = BaoXiang_Update_Interval -- Время до обновления позиции сундука (в секундах) WeekDay_OpenState = {0, 0, 0, 0, 0, 0, 0} -- Состояние активности по дням недели -------------------------------------------------------------------------------------- -- Вспомогательные функции активности -------------------------------------------------------------------------------------- -- Сброс всех данных активности -- Вызывается при завершении или инициализации активности function ResetActiveData() -- Очистка информации о сундуке BaoXiang_MapID = 0 BaoXiang_X = 0 BaoXiang_Z = 0 BaoXiang_Holder = 0 -- Сброс счетчиков времени Min_Counter = 0 BaoXiang_OpenRemainTime = BaoXiang_CDTime Tick_Count = 0 -- Очистка ID сундука BaoXiang_SerialID_High = 0 BaoXiang_SerialID_Low = 0 BaoXiang_GroupID_High = 0 BaoXiang_GroupID_Low = 0 -- Сброс времени обновления BaoXiang_UpdateRemainTime = BaoXiang_Update_Interval end -- Отправка сообщения о поднятии сундука игроком -- Уведомляет всех игроков о том, кто поднял сундук и где он находится function SendPickUpBaoXiangMsg() -- Проверяем корректность данных if BaoXiang_MapID == nil or BaoXiang_Holder == nil or BaoXiang_MapID == 0 or BaoXiang_Holder == 0 then return end -- Создаем сообщение local MsgID = msg.BeginMsgEvent() msg.AddMsgEvent(MsgID, 102, 100073) -- "Игрок поднял сундук в локации X, Y!" msg.AddMsgEvent(MsgID, 2, BaoXiang_Holder) -- ID игрока msg.AddMsgEvent(MsgID, 6, BaoXiang_MapID) -- ID карты msg.AddMsgEvent(MsgID, 9, BaoXiang_X) -- Координата X msg.AddMsgEvent(MsgID, 9, BaoXiang_Z) -- Координата Z msg.DispatchWorldMsgEvent(MsgID) end -- Отправка сообщения об обновлении позиции сундука -- Уведомляет игроков о появлении сундука в новой локации function SendChaseUpdateMsg() -- Проверяем корректность данных if BaoXiang_MapID == nil or BaoXiang_MapID == 0 then return end -- Создаем сообщение local MsgID = msg.BeginMsgEvent() msg.AddMsgEvent(MsgID, 102, 100072) -- "Сундук появился на карте X в точке Y, Z!" msg.AddMsgEvent(MsgID, 6, BaoXiang_MapID) -- ID карты msg.AddMsgEvent(MsgID, 9, BaoXiang_X) -- Координата X msg.AddMsgEvent(MsgID, 9, BaoXiang_Z) -- Координата Z msg.DispatchWorldMsgEvent(MsgID) end -- Отправка сообщения о смерти носителя сундука -- Уведомляет о том, что носитель сундука был убит другим игроком function SendChaseHolderBeKilledByRole(KillerID) -- Проверяем входные параметры if KillerID == nil then return end -- Проверяем корректность данных if BaoXiang_MapID == nil or BaoXiang_MapID == 0 then return end -- Создаем сообщение local MsgID = msg.BeginMsgEvent() msg.AddMsgEvent(MsgID, 102, 100074) -- "Игрок убил носителя сундука! Сундук упал в точке X, Y!" msg.AddMsgEvent(MsgID, 2, KillerID) -- ID убийцы msg.AddMsgEvent(MsgID, 2, BaoXiang_Holder) -- ID жертвы msg.AddMsgEvent(MsgID, 6, BaoXiang_MapID) -- ID карты msg.AddMsgEvent(MsgID, 9, BaoXiang_X) -- Координата X msg.AddMsgEvent(MsgID, 9, BaoXiang_Z) -- Координата Z msg.DispatchWorldMsgEvent(MsgID) end -- Синхронизация оставшегося времени открытия сундука с клиентом -- Отправляет игроку информацию о времени до открытия сундука function SyncOpenChaseRemainTime() if BaoXiang_Holder ~= 0 then role.SyncOpenChaseRemainTime(BaoXiang_Holder, BaoXiang_OpenRemainTime) end end -- Обновление позиции сундука по позиции игрока -- Синхронизирует позицию сундука с позицией его носителя function UpdateBaoXiangPos(RoleID) -- Проверяем входные параметры if RoleID == nil then return end -- Проверяем корректность данных карты if BaoXiang_MapID == nil or BaoXiang_MapID == 0 then return end -- Обновляем позицию только если есть носитель if RoleID ~= 0 then local BaoXiang_Y = 0 BaoXiang_X, BaoXiang_Y, BaoXiang_Z = unit.GetPosition(BaoXiang_MapID, 0, RoleID) end end -- Снятие статуса "несет сундук" с игрока -- Убирает бафф и статус носителя сундука function UnSetHoldChestState(RoleID) -- Проверяем входной параметр if RoleID == nil or RoleID == 0 then return end -- Снимаем статус и бафф role.UnSetRoleState(RoleID, ERS_HoldChest, 1) unit.CancelBuff(BaoXiang_MapID, 0, RoleID, HoldChest_BuffID) end -- Установка статуса "несет сундук" для игрока -- Добавляет бафф и статус носителя сундука function SetHoldChestState(RoleID) -- Проверяем входной параметр if RoleID == nil or RoleID == 0 then return end -- Устанавливаем статус и бафф role.SetRoleState(RoleID, ERS_HoldChest, 1) unit.AddBuff(BaoXiang_MapID, 0, RoleID, HoldChest_BuffID, RoleID) end -- Установка ID игрока-носителя сундука -- Управляет статусом игрока при поднятии/бросании сундука function SetBaoXiangHolderRoleID(RoleID) -- Проверяем входной параметр if RoleID == nil then return end if RoleID == 0 then -- Игрок бросил сундук или умер UnSetHoldChestState(BaoXiang_Holder) -- Сбрасываем время открытия, если модификатор времени равен 0 if BaoXiang_Hold_Time_Mod == 0 then BaoXiang_OpenRemainTime = BaoXiang_CDTime end -- Обновляем позицию сундука UpdateBaoXiangPos(BaoXiang_Holder) else -- Игрок поднял сундук SetHoldChestState(RoleID) -- Сбрасываем время обновления позиции BaoXiang_UpdateRemainTime = BaoXiang_Update_Interval -- Обновляем позицию сундука UpdateBaoXiangPos(RoleID) end -- Устанавливаем нового носителя BaoXiang_Holder = RoleID -- Синхронизируем время с клиентом SyncOpenChaseRemainTime() end -- Удаление сундука из игры -- Убирает сундук либо из инвентаря игрока, либо с земли function RemoveBaoXiang() if BaoXiang_Holder ~= 0 then -- Сундук у игрока - удаляем из инвентаря role.RemoveFromRole(BaoXiang_MapID, 0, BaoXiang_Holder, BaoXiang_ID, 1, 310) else -- Сундук на земле - удаляем с карты map.RemoveGroundItem(BaoXiang_MapID, BaoXiang_GroupID_High, BaoXiang_GroupID_Low) end end -- Начало активности ежедневно -- Вызывается в начале каждого дня активности function ActiveStart() -- Если активность не завершена - удаляем существующий сундук if Active_End == 0 then RemoveBaoXiang() end -- Сбрасываем статус носителя UnSetHoldChestState(BaoXiang_Holder) -- Сбрасываем все данные активности ResetActiveData() -- Отправляем сообщение о начале активности local RuleMsgID = msg.BeginMsgEvent() msg.AddMsgEvent(RuleMsgID, 102, 100075) -- "Активность 'Охота за сундуком' началась!" msg.DispatchWorldMsgEvent(RuleMsgID) -- Устанавливаем флаги активности Active_Started = 1 Active_End = 0 -- Запускаем активность и рассылаем уведомления ActiveStartAndStartBroadcast() end -- Завершение активности "Два дракона и сундук" -- Вызывается при окончании активности или принудительном завершении function ActiveEnd() -- Устанавливаем флаг завершения Active_End = 1 -- Отправляем сообщение о завершении local MsgID = msg.BeginMsgEvent() msg.AddMsgEvent(MsgID, 102, 100083) -- "Активность 'Охота за сундуком' завершена!" msg.DispatchWorldMsgEvent(MsgID) -- Сбрасываем статус носителя UnSetHoldChestState(BaoXiang_Holder) end -- Запуск активности с созданием сундука и рассылкой уведомлений -- Создает сундук в случайном месте и уведомляет игроков function ActiveStartAndStartBroadcast() -- Получаем текущее время local Hour = tonumber(os.date("%H")) local Min = tonumber(os.date("%M")) -- Создаем сундук в одной из заданных точек local n = #BaoXiang_SpawnPoints if n <= 0 then return end local p = BaoXiang_SpawnPoints[math.random(n)] if p == nil or p.map == nil or p.x == nil or p.z == nil then return end BaoXiang_MapID, BaoXiang_X, BaoXiang_Z, BaoXiang_SerialID_High, BaoXiang_SerialID_Low, BaoXiang_GroupID_High, BaoXiang_GroupID_Low = map.PutGroundItemAtPos(p.map, -1, BaoXiang_ID, p.x, p.z) -- Проверяем успешность создания сундука if BaoXiang_MapID == nil or BaoXiang_X == nil or BaoXiang_Z == nil or BaoXiang_SerialID_High == nil or BaoXiang_SerialID_Low == nil or BaoXiang_GroupID_High == nil or BaoXiang_GroupID_Low == nil then return end -- Отправляем сообщение о появлении сундука SendChaseUpdateMsg() end -- Проверка завершения активности -- Возвращает true если активность завершена function IsActiveEnd() return Active_End end -- Обновление оставшегося времени до открытия сундука -- Уменьшает таймер открытия сундука носителем function UpdateOpenRemainTime() -- Инициализируем время открытия, если оно не установлено if BaoXiang_OpenRemainTime == nil then BaoXiang_OpenRemainTime = BaoXiang_CDTime end -- Не обновляем время если активность завершена if IsActiveEnd() == 1 then return end -- Уменьшаем время только если есть носитель if BaoXiang_Holder ~= 0 then BaoXiang_OpenRemainTime = BaoXiang_OpenRemainTime - 1 -- Если время вышло - завершаем активность if BaoXiang_OpenRemainTime < 0 then ActiveEnd() end end end -- Обновление времени до перемещения сундука -- Перемещает сундук если он долго лежит без дела function BaoXiangUpdateRemainTime() -- Инициализируем время обновления, если оно не установлено if BaoXiang_UpdateRemainTime == nil then BaoXiang_UpdateRemainTime = BaoXiang_Update_Interval end -- Не обновляем если активность завершена if IsActiveEnd() == 1 then return end -- Обновляем только если нет носителя if BaoXiang_Holder == 0 then BaoXiang_UpdateRemainTime = BaoXiang_UpdateRemainTime - 1 -- Если время вышло - перемещаем сундук if BaoXiang_UpdateRemainTime < 0 then -- Удаляем старый сундук map.RemoveGroundItem(BaoXiang_MapID, BaoXiang_GroupID_High, BaoXiang_GroupID_Low) -- Создаем новый сундук ActiveStartAndStartBroadcast() -- Сбрасываем таймер BaoXiang_UpdateRemainTime = BaoXiang_Update_Interval end end end -- Проверка активности на сегодня -- Возвращает true если сегодня день активности function IsTodayHaveActive() -- Получаем текущий день недели и проверяем его активность local today = os.date("%A") local dayIndex = EWeekDay[today] if dayIndex ~= nil then return WeekDay_OpenState[dayIndex] end -- Возвращаем false если день не определен return false end -------------------------------------------------------------------------------------- -- Обработчики событий C++ (регистрация событий) -------------------------------------------------------------------------------------- -- Начало активности "Два дракона и сундук" -- Вызывается при запуске активности через систему активаций function DuoBaoQiBing_OnActiveStart(ActiveID) -- Проверяем входные параметры if ActiveID == nil then return end -- Проверяем триггер активности if DuoBaoQiBing_trigger == 0 then return end -- Получаем состояние активности по дням недели WeekDay_OpenState[1], WeekDay_OpenState[2], WeekDay_OpenState[3], WeekDay_OpenState[4], WeekDay_OpenState[5], WeekDay_OpenState[6], WeekDay_OpenState[7] = act.GetDuoBaoQiBingOpenState() -- Сбрасываем данные активности ResetActiveData() -- Устанавливаем начальное состояние Active_Started = 0 Active_End = 1 end -- Таймер активности (каждую секунду) -- Управляет временем активности и автоматическим запуском function DuoBaoQiBing_OnActiveTimer(ActiveID, Sec) -- Проверяем входные параметры if ActiveID == nil then return end -- Проверяем триггер активности if DuoBaoQiBing_trigger == 0 then return end -- Получаем текущее время local Hour = tonumber(os.date("%H")) local Min = tonumber(os.date("%M")) local Sec = tonumber(os.date("%S")) -- Обновляем счетчик тиков (каждые 6 секунд обновляем таймеры) Tick_Count = Tick_Count + 1 if Tick_Count == 6 then -- Обновляем время открытия сундука UpdateOpenRemainTime() -- Обновляем время перемещения сундука BaoXiangUpdateRemainTime() -- Сбрасываем счетчик тиков Tick_Count = 0 end -- Автоматическое управление активностью по времени if IsTodayHaveActive() == 1 then -- Останавливаем активность за 1 минуту до конца (18:59) if Hour == 18 and Min == 59 and Active_Started == 1 then Active_Started = 0 end -- Запускаем активность в 19:00 if Hour == 19 and Min == 0 and Active_Started == 0 then ActiveStart() end end end -- Ежеминутный таймер активности -- Обновляет позицию сундука и рассылает уведомления function DuoBaoQiBing_OnActiveTimeMin(ActiveID) -- Проверяем входные параметры if ActiveID == nil then return end -- Проверяем триггер активности if DuoBaoQiBing_trigger == 0 then return end -- Не выполняем если активность завершена if IsActiveEnd() == 1 then return end -- Обновляем позицию сундука если есть носитель if BaoXiang_Holder ~= 0 then UpdateBaoXiangPos(BaoXiang_Holder) SyncOpenChaseRemainTime() end -- Увеличиваем счетчик минут Min_Counter = Min_Counter + 1 -- Проверяем интервал рассылки уведомлений if Min_Counter > BaoXiang_Pos_Broadcast_Interval then if BaoXiang_Holder ~= 0 then -- Отправляем сообщение о позиции носителя SendPickUpBaoXiangMsg() else -- Отправляем сообщение о позиции сундука на земле SendChaseUpdateMsg() end -- Сбрасываем счетчик минут Min_Counter = 0 end end -- Завершение активности -- Вызывается при окончании активности function DuoBaoQiBing_OnActiveEnd(ActiveID) -- Проверяем входные параметры if ActiveID == nil then return end -- Здесь можно добавить дополнительную логику завершения -- Пока функция остается пустой, так как основная логика -- завершения реализована в ActiveEnd() end -- Обработка поднятия сундука игроком -- Вызывается когда игрок поднимает сундук с земли function DuoBaoQiBing_OnPickUpBaoXiang(ItemID, RoleID) -- Проверяем входные параметры if ItemID == nil or RoleID == nil then return end -- Проверяем триггер активности if DuoBaoQiBing_trigger == 0 then return end -- Не обрабатываем если активность завершена if IsActiveEnd() == 1 then return end -- Проверяем что подняли именно сундук if ItemID ~= BaoXiang_ID then return end -- Устанавливаем игрока носителем сундука SetBaoXiangHolderRoleID(RoleID) -- Очищаем ID группы (сундук больше не на земле) BaoXiang_GroupID_High = 0 BaoXiang_GroupID_Low = 0 -- Отправляем уведомление всем игрокам SendPickUpBaoXiangMsg() end -- Проверка возможности поднятия сундука -- Возвращает 0 если поднять можно, иначе код ошибки function DuoBaoQiBing_CanPickUpBaoXiang(ItemID, RoleID) -- Проверяем входные параметры if ItemID == nil or RoleID == nil then return 0 end -- Проверяем триггер активности if DuoBaoQiBing_trigger == 0 then return 0 end -- Получаем уровень игрока local RoleLvl = role.GetRoleLevel(BaoXiang_MapID, 0, RoleID) if RoleLvl == nil then return 0 end -- Проверяем уровень игрока if BaoXiang_ID == ItemID and (RoleLvl < Active_Min_Level or RoleLvl > Active_Max_Level) then return E_Loot_Role_Level_Limit end -- Проверяем состояние движения (плавание) local CurMoveState = role.GetCurMoveState(RoleID) if CurMoveState == EMS_Swim or CurMoveState == EMS_SwimStand then return E_Loot_Swim_Can_Not_Pickup_BaoXiang end -- Проверяем нахождение в безопасной зоне if role.IsRoleInStatus(RoleID, ERS_SafeArea) then return E_Loot_Role_SafeArea_Limit end -- Проверяем дополнительные статусы безопасной зоны if role.IsRoleInStatus(RoleID, 8192) then return E_Loot_Role_SafeArea_Limit end -- Все проверки пройдены - можно поднять return 0 end -- Обработка смерти носителя сундука -- Вызывается когда носитель сундука погибает function DuoBaoQiBing_OnChaseHolderDie(RoleID, KillerID) -- Проверяем входные параметры if RoleID == nil or KillerID == nil then return end -- Проверяем триггер активности if DuoBaoQiBing_trigger == 0 then return end -- Не обрабатываем если активность завершена if IsActiveEnd() == 1 then return end -- Проверяем что умер именно носитель сундука if BaoXiang_Holder ~= RoleID then return end -- Обновляем позицию сундука UpdateBaoXiangPos(BaoXiang_Holder) -- Отправляем соответствующее сообщение if unit.IsPlayer(KillerID) then -- Убийца - игрок SendChaseHolderBeKilledByRole(KillerID) else -- Убийца - монстр или другое SendChaseUpdateMsg() end -- Заставляем игрока бросить сундук role.PutDownItem(RoleID, BaoXiang_ID) -- Очищаем носителя сундука SetBaoXiangHolderRoleID(0) end -- Проверка возможности удаления сундука с земли -- Возвращает 1 если можно удалить, 0 если нельзя function DuoBaoQiBing_CanDelBaoXiangOnGround(TypeID, SerialID_High, SerialID_Low) -- Проверяем входные параметры if TypeID == nil or SerialID_High == nil or SerialID_Low == nil then return 0 end -- Проверяем триггер активности if DuoBaoQiBing_trigger == 0 then return 0 end -- Не удаляем если активность завершена if IsActiveEnd() == 1 then return 0 end -- Проверяем что это именно наш сундук if TypeID == BaoXiang_ID and BaoXiang_SerialID_High == SerialID_High and BaoXiang_SerialID_Low == SerialID_Low then return 1 -- Можно удалить else return 0 -- Нельзя удалить end end -- Принудительное отнятие сундука -- Вызывается для принудительного отнятия сундука у игрока function DuoBaoQiBing_ForceLootChase(RoleID) -- Проверяем входной параметр if RoleID == nil then return end -- Проверяем триггер активности if DuoBaoQiBing_trigger == 0 then return end -- Не выполняем если активность завершена if IsActiveEnd() == 1 then return end -- Проверяем что игрок действительно носитель сундука if BaoXiang_Holder == RoleID then -- Обновляем позицию сундука UpdateBaoXiangPos(BaoXiang_Holder) -- Заставляем игрока бросить сундук role.PutDownItem(RoleID, BaoXiang_ID) -- Выполняем принудительное отнятие role.ForceLootChase(BaoXiang_Holder) -- Очищаем носителя SetBaoXiangHolderRoleID(0) -- Отправляем уведомление об обновлении позиции SendChaseUpdateMsg() end end -- Проверка возможности открытия сундука -- Возвращает время открытия и возможность открыть function DuoBaoQiBing_CanOpenBaoXiang(MapID, InstanceID, TypeID, TargetID) -- Проверяем входные параметры if MapID == nil or TypeID == nil or TargetID == nil then return 0, 0 end -- Проверяем триггер активности if DuoBaoQiBing_trigger == 0 then return 0, 0 end -- Если активность завершена if IsActiveEnd() == 1 then -- Проверяем свободное место в инвентаре local FreeSize = role.GetBagFreeSize(TargetID) if FreeSize < 8 then return 40, false -- Недостаточно места в инвентаре end return 0, 0 -- Можно открыть сразу end -- Активность активна - возвращаем время открытия return 60, 1 -- 60 секунд до открытия end -- Проверка необходимости удаления сундука при инициализации персонажа -- Возвращает 1 если нужно удалить, 0 если не нужно function DuoBaoQiBing_CanDeleteBaoXiang(TypeID, SerialID_High, SerialID_Low) -- Проверяем входные параметры if TypeID == nil or SerialID_High == nil or SerialID_Low == nil then return 1 -- Удаляем по умолчанию если параметры некорректны end -- Проверяем что это сундук активности if TypeID == BaoXiang_ID then -- Удаляем сундук только если активность завершена и это наш сундук if BaoXiang_SerialID_High == SerialID_High and BaoXiang_SerialID_Low == SerialID_Low and IsActiveEnd() == 1 then return 1 -- Нужно удалить else return 0 -- Не удалять end else return 1 -- Удаляем другие предметы end end -- Обработка открытия/закрытия активности через админ-панель -- Вызывается при изменении статуса активности GM function DuoBaoQiBing_OnActOpenClose(ActiveID, IsOpen) -- Проверяем входные параметры if ActiveID == nil or IsOpen == nil then return end -- Проверяем что это наша активность if DuoBaoQiBing_Active_ID ~= ActiveID then return end -- Если активность выключается и не завершена - завершаем принудительно if DuoBaoQiBing_trigger == 0 and IsActiveEnd() ~= 1 then RemoveBaoXiang() ActiveEnd() end -- Устанавливаем новый статус активности DuoBaoQiBing_trigger = IsOpen end -- Регистрация обработчиков событий активности -- Все события регистрируются для корректной работы системы "Два дракона и сундук" -- События активности aux.RegisterActEvent(DuoBaoQiBing_Active_ID, ESAE_OnTimer, "DuoBaoQiBing_OnActiveTimer") -- Таймер активности aux.RegisterActEvent(DuoBaoQiBing_Active_ID, ESAE_OnStart, "DuoBaoQiBing_OnActiveStart") -- Начало активности aux.RegisterActEvent(DuoBaoQiBing_Active_ID, ESAE_OnEnd, "DuoBaoQiBing_OnActiveEnd") -- Завершение активности aux.RegisterActEvent(DuoBaoQiBing_Active_ID, ESAE_OnTimerMin, "DuoBaoQiBing_OnActiveTimeMin") -- Ежеминутный таймер aux.RegisterActEvent(DuoBaoQiBing_Active_ID, ESAE_OnActOpenClose, "DuoBaoQiBing_OnActOpenClose") -- Открытие/закрытие через GM -- События персонажей aux.RegisterRoleEvent(ESRE_OnChaseHolderDie, "DuoBaoQiBing_OnChaseHolderDie") -- Смерть носителя сундука aux.RegisterRoleEvent(ESRE_ForceLootChase, "DuoBaoQiBing_ForceLootChase") -- Принудительное отнятие сундука -- События предметов (сундука) aux.RegisterItemEvent(BaoXiang_ID, ESIE_CanPickUpItem, "DuoBaoQiBing_CanPickUpBaoXiang") -- Проверка поднятия aux.RegisterItemEvent(BaoXiang_ID, ESIE_PickUpItem, "DuoBaoQiBing_OnPickUpBaoXiang") -- Поднятие сундука aux.RegisterItemEvent(BaoXiang_ID, ESIE_CanDelGroundItem, "DuoBaoQiBing_CanDelBaoXiangOnGround") -- Удаление с земли aux.RegisterItemEvent(BaoXiang_ID, ESIE_CanPutDown, "DuoBaoQiBing_CanPutDownBaoXiang") -- Бросание сундука (не используется) aux.RegisterItemEvent(BaoXiang_ID, ESIE_CanUse, "DuoBaoQiBing_CanOpenBaoXiang") -- Проверка открытия aux.RegisterItemEvent(BaoXiang_ID, ESIE_CanDelItemOnRoleInit, "DuoBaoQiBing_CanDeleteBaoXiang") -- Удаление при инициализации