-- ======================================== -- ФУНКЦИИ ЛЕДОВОГО ПОБОИЩА -- Вспомогательные функции для управления событием -- ======================================== -- ======================================== -- УПРАВЛЕНИЕ ИГРОКАМИ -- ======================================== -- Регистрация игрока в событии -- Создает объект игрока с проверкой уровня function CreatPoboisheRoleObj(RoleID) if Poboishe_Role[RoleID] == nil then local Target_MapID, Target_InstanceID = role.GetRoleMapID(RoleID) local rolelevel = role.GetRoleLevel(Target_MapID, Target_InstanceID, RoleID) -- Проверяем минимальный уровень для участия if rolelevel >= 60 then Poboishe_Roletotal = Poboishe_Roletotal + 1 -- Создаем объект игрока с базовыми параметрами Poboishe_Role[RoleID] = { RoleID = RoleID, Time = 0, Side = "None", InstanceID = 1, State = "OutSide", Kill = 0 } -- Получаем информацию о гильдии local Guild = guild.GetRoleGuildID(RoleID) local FamilyID = role.GetRoleFamilyID(Target_MapID, Target_InstanceID, RoleID) if Guild and Guild ~= 4294967295 then Poboishe_Role[RoleID].Guild = Guild else Poboishe_Role[RoleID].Guild = 0 end if FamilyID and FamilyID ~= 4294967295 then Poboishe_Role[RoleID].FamilyID = FamilyID else Poboishe_Role[RoleID].FamilyID = 0 end -- Привязываем методы к объекту игрока Poboishe_Role[RoleID].ShowPoboisheTime = ShowPoboisheTime Poboishe_Role[RoleID].GetAttBuff_Poboishe = GetAttBuff_Poboishe Poboishe_Role[RoleID].WuDi_Poboishe = WuDi_Poboishe Poboishe_Role[RoleID].SetColor_Poboishe = SetColor_Poboishe Poboishe_Role[RoleID].SendInfo_Poboishe = SendInfo_Poboishe Poboishe_Role[RoleID].PlayerLeavePoboishe = PlayerLeavePoboishe Poboishe_Role[RoleID].PlayerEnterPoboishe = PlayerEnterPoboishe Poboishe_Role[RoleID].GetKillExp_Poboishe = GetKillExp_Poboishe end end end -- Получение объекта игрока по ID function GetPoboisheRoleObj(RoleID) return Poboishe_Role[RoleID] end -- ======================================== -- УПРАВЛЕНИЕ КОМАНДАМИ -- ======================================== -- Создание объекта команды (стороны) function CreatPoboisheSideObj() local k = #Poboishe_Side + 1 Poboishe_Side[k] = { Player = {}, -- Список игроков команды InSidePlayer = {}, -- Игроки на поле боя Num = 0, -- Количество игроков на поле Point = 0 -- Очки команды } -- Чередуем красную и синюю команды if k % 2 == 1 then Poboishe_Side[k].Side = "Red" else Poboishe_Side[k].Side = "Blue" end -- Привязываем метод присоединения игрока Poboishe_Side[k].PlayerJoinPoboisheSide = PlayerJoinPoboisheSide return Poboishe_Side[k] end -- Присоединение игрока к команде function PlayerJoinPoboisheSide(Obj, PlayerID) table.insert(Obj.Player, PlayerID) if Poboishe_Role[PlayerID] then Poboishe_Role[PlayerID].Side = Obj.Side end end -- ======================================== -- УПРАВЛЕНИЕ ПОЛЕМ БОЯ -- ======================================== -- Создание объекта поля боя function CreatPoboishenBattleObj(RedPlayer, BluePlayer) local k = #Poboishe_Battle + 1 -- Создаем инстанс карты map.CreateInstance(S66_1_MapID, k) -- Создаем объект боя Poboishe_Battle[k] = { RedPlayer = RedPlayer, BluePlayer = BluePlayer, InstanceID = k } -- Устанавливаем ID инстанса для всех игроков for k1, v in pairs(RedPlayer.Player) do if Poboishe_Role[v] then Poboishe_Role[v].InstanceID = k end end for k1, v in pairs(BluePlayer.Player) do if Poboishe_Role[v] then Poboishe_Role[v].InstanceID = k end end -- Привязываем методы к объекту боя Poboishe_Battle[k].SendAllInfo_Poboishe = SendAllInfo_Poboishe Poboishe_Battle[k].SetPlayerPoint_Poboishe = SetPlayerPoint_Poboishe Poboishe_Battle[k].SetPlayerFinalPoint_Poboishe = SetPlayerFinalPoint_Poboishe Poboishe_Battle[k].ResetInSidePlayer_Poboishe = ResetInSidePlayer_Poboishe end -- ======================================== -- РАСПРЕДЕЛЕНИЕ ИГРОКОВ ПО КОМАНДАМ -- ======================================== -- Выбор стороны для игроков -- Распределяет игроков по командам с учетом гильдий и семей function Poboishe_ChooseSide() if Poboishe_Roletotal > 159 then -- Для большого количества игроков создаем несколько полей боя local k = math.floor(Poboishe_Roletotal / 80) local av_player = math.floor(Poboishe_Roletotal / k) local num = {} -- Распределяем игроков по полям боя for i = 1, k do if i ~= k then num[i] = av_player else num[i] = Poboishe_Roletotal - av_player * (k - 1) end end local Player = {} local Playertotal = 0 -- Функция для определения индекса поля боя local function GetIndex(Playertotal) local total = 0 for i = 1, k do total = total + num[i] if total >= Playertotal then return i end end end -- Распределяем игроков по полям боя for k1, v in pairs(Poboishe_Role) do Playertotal = Playertotal + 1 local index = GetIndex(Playertotal) if Player[index] == nil then Player[index] = {} end table.insert(Player[index], k1) end -- Создаем поля боя для каждого индекса for i = 1, k do local RedSideObj = CreatPoboisheSideObj() local BlueSideObj = CreatPoboisheSideObj() local red = 0 local times = 0 -- Распределяем игроков по командам while red < num[i] / 2 and #Player[i] > 0 do RedSideObj:PlayerJoinPoboisheSide(Player[i][1]) local Player1Obj = GetPoboisheRoleObj(Player[i][1]) red = red + 1 -- Добавляем игроков из той же гильдии/семьи for k1 = #Player[i], 1, -1 do local PlayerObj = GetPoboisheRoleObj(Player[i][k1]) if PlayerObj and PlayerObj.RoleID ~= Player[i][k1] and ((PlayerObj.Guild ~= 0 and PlayerObj.Guild == Player1Obj.Guild) or (PlayerObj.FamilyID ~= 0 and PlayerObj.FamilyID == Player1Obj.FamilyID)) then RedSideObj:PlayerJoinPoboisheSide(Player[i][k1]) red = red + 1 table.remove(Player[i], k1) if red >= num[i] / 2 then break end end end table.remove(Player[i], 1) times = times + 1 if times > 160 then break end end -- Оставшихся игроков добавляем в синюю команду for k1, v in pairs(Player[i]) do BlueSideObj:PlayerJoinPoboisheSide(v) end CreatPoboishenBattleObj(RedSideObj, BlueSideObj) end else -- Для небольшого количества игроков создаем одно поле боя local Player = {} for k, v in pairs(Poboishe_Role) do table.insert(Player, k) end local RedSideObj = CreatPoboisheSideObj() local BlueSideObj = CreatPoboisheSideObj() local red = 0 local times = 0 -- Распределяем игроков по командам while red < Poboishe_Roletotal / 2 and #Player > 0 do RedSideObj:PlayerJoinPoboisheSide(Player[1]) local Player1Obj = GetPoboisheRoleObj(Player[1]) red = red + 1 -- Добавляем игроков из той же гильдии/семьи for k1 = #Player, 1, -1 do local PlayerObj = GetPoboisheRoleObj(Player[k1]) if PlayerObj and PlayerObj.RoleID ~= Player[k1] and ((PlayerObj.Guild ~= 0 and PlayerObj.Guild == Player1Obj.Guild) or (PlayerObj.FamilyID ~= 0 and PlayerObj.FamilyID == Player1Obj.FamilyID)) then RedSideObj:PlayerJoinPoboisheSide(Player[k1]) red = red + 1 table.remove(Player, k1) if red >= Poboishe_Roletotal / 2 then break end end end table.remove(Player, 1) times = times + 1 if times > 160 then break end end -- Оставшихся игроков добавляем в синюю команду for k1, v in pairs(Player) do BlueSideObj:PlayerJoinPoboisheSide(v) end CreatPoboishenBattleObj(RedSideObj, BlueSideObj) end end -- ======================================== -- ФУНКЦИИ ИГРОКОВ -- ======================================== -- Показ оставшегося времени события function ShowPoboisheTime(RoleObj) local leftSec = 3600 -- 1 час в секундах local Min = tonumber(os.date("%M")) local Second = tonumber(os.date("%S")) leftSec = leftSec - Min * 60 - Second local MsgID = msg.BeginMsgEvent() msg.AddMsgEvent(MsgID, 16, 28) msg.AddMsgEvent(MsgID, 16, leftSec) msg.DispatchRoleMsgEvent(RoleObj.RoleID, MsgID) end -- Применение баффов атрибутов по уровню function GetAttBuff_Poboishe(RoleObj) local rolelevel = role.GetRoleLevel(S66_1_MapID, RoleObj.InstanceID, RoleObj.RoleID) if rolelevel > 100 then rolelevel = 100 end -- Применяем баффы только с 50 уровня if rolelevel >= 50 then local index = math.floor((rolelevel - 50) / 5) + 1 unit.AddBuff(S66_1_MapID, RoleObj.InstanceID, RoleObj.RoleID, index * 100 + 6107001, RoleObj.RoleID) end end -- Получение опыта за убийство function GetKillExp_Poboishe(RoleObj) local rolelevel = role.GetRoleLevel(S66_1_MapID, RoleObj.InstanceID, RoleObj.RoleID) -- Ограничиваем уровень для расчета опыта if rolelevel < 60 then rolelevel = 60 elseif rolelevel > 100 then rolelevel = 100 end RoleObj.Kill = RoleObj.Kill + 1 local exp1 = math.floor(Poboishe_Exp[rolelevel] / 10) -- Ограничиваем опыт 30 убийствами if RoleObj.Kill > 30 then exp1 = 0 else role.AddRoleExp(S66_1_MapID, RoleObj.InstanceID, RoleObj.RoleID, exp1) end -- Отправляем сообщение о полученном опыте local MsgID = msg.BeginMsgEvent() msg.AddMsgEvent(MsgID, 13, 0) msg.AddMsgEvent(MsgID, 1, 206731) -- Убито: X, получено Y очков опыта msg.AddMsgEvent(MsgID, 9, RoleObj.Kill) msg.AddMsgEvent(MsgID, 9, exp1) msg.DispatchRoleMsgEvent(RoleObj.RoleID, MsgID) end -- Применение неуязвимости на 15 секунд function WuDi_Poboishe(RoleObj) unit.AddBuff(S66_1_MapID, RoleObj.InstanceID, RoleObj.RoleID, 6109401, RoleObj.RoleID) end -- Установка цвета команды function SetColor_Poboishe(RoleObj) if RoleObj.Side == "Red" then unit.SetState(S66_1_MapID, RoleObj.InstanceID, RoleObj.RoleID, 10) -- Красная команда else unit.SetState(S66_1_MapID, RoleObj.InstanceID, RoleObj.RoleID, 11) -- Синяя команда end end -- Отправка информации о состоянии боя function SendInfo_Poboishe(RoleObj) local redpoint = Poboishe_Battle[RoleObj.InstanceID].RedPlayer.Point local rednum = Poboishe_Battle[RoleObj.InstanceID].RedPlayer.Num local bluepoint = Poboishe_Battle[RoleObj.InstanceID].BluePlayer.Point local bluenum = Poboishe_Battle[RoleObj.InstanceID].BluePlayer.Num local char = redpoint .. "," .. rednum .. "," .. bluepoint .. "," .. bluenum -- role.DotaSendMsg(S66_1_MapID, RoleObj.InstanceID, RoleObj.RoleID, 1, char) end -- Вход игрока на поле боя function PlayerEnterPoboishe(RoleObj) RoleObj.State = "InSide" local tbl = {} if RoleObj.Side == "Red" then Poboishe_Battle[RoleObj.InstanceID].RedPlayer.Num = Poboishe_Battle[RoleObj.InstanceID].RedPlayer.Num + 1 tbl = Poboishe_Battle[RoleObj.InstanceID].RedPlayer.InSidePlayer elseif RoleObj.Side == "Blue" then Poboishe_Battle[RoleObj.InstanceID].BluePlayer.Num = Poboishe_Battle[RoleObj.InstanceID].BluePlayer.Num + 1 tbl = Poboishe_Battle[RoleObj.InstanceID].BluePlayer.InSidePlayer end table.insert(tbl, RoleObj.RoleID) end -- Выход игрока с поля боя function PlayerLeavePoboishe(RoleObj) RoleObj.State = "OutSide" local tbl = {} if RoleObj.Side == "Red" then Poboishe_Battle[RoleObj.InstanceID].RedPlayer.Num = Poboishe_Battle[RoleObj.InstanceID].RedPlayer.Num - 1 tbl = Poboishe_Battle[RoleObj.InstanceID].RedPlayer.InSidePlayer elseif RoleObj.Side == "Blue" then Poboishe_Battle[RoleObj.InstanceID].BluePlayer.Num = Poboishe_Battle[RoleObj.InstanceID].BluePlayer.Num - 1 tbl = Poboishe_Battle[RoleObj.InstanceID].BluePlayer.InSidePlayer end -- Удаляем игрока из списка находящихся на поле for k = #tbl, 1, -1 do if tbl[k] == RoleObj.RoleID then table.remove(tbl, k) break end end end -- ======================================== -- ФУНКЦИИ ПОЛЯ БОЯ -- ======================================== -- Отправка информации всем игрокам поля боя function SendAllInfo_Poboishe(BattleObj) -- Отправляем информацию игрокам красной команды for k, v in pairs(BattleObj.RedPlayer.Player) do local RoleObj = GetPoboisheRoleObj(v) if RoleObj then local Target_MapID, Target_InstanceID = role.GetRoleMapID(RoleObj.RoleID) if Target_MapID and Target_InstanceID and Target_MapID == S66_1_MapID and RoleObj.InstanceID == Target_InstanceID then RoleObj:SendInfo_Poboishe() end end end -- Отправляем информацию игрокам синей команды for k, v in pairs(BattleObj.BluePlayer.Player) do local RoleObj = GetPoboisheRoleObj(v) if RoleObj then local Target_MapID, Target_InstanceID = role.GetRoleMapID(RoleObj.RoleID) if Target_MapID and Target_InstanceID and Target_MapID == S66_1_MapID and RoleObj.InstanceID == Target_InstanceID then RoleObj:SendInfo_Poboishe() end end end end -- Начисление очков персонажам за время на поле боя function SetPlayerPoint_Poboishe(BattleObj) local RedSideObj = BattleObj.RedPlayer local BlueSideObj = BattleObj.BluePlayer -- Начисляем очки игрокам красной команды for k, v in pairs(RedSideObj.Player) do local RoleObj = Poboishe_Role[v] if RoleObj and RoleObj.State == "InSide" then local Target_MapID, Target_InstanceID = role.GetRoleMapID(RoleObj.RoleID) if Target_MapID and not unit.IsDead(Target_MapID, Target_InstanceID, RoleObj.RoleID) then role.SetRoleScriptData(RoleObj.RoleID, 1, RoleDataType["Poboishe_Point"], role.GetRoleScriptData(RoleObj.RoleID, 1, RoleDataType["Poboishe_Point"]) + 1) end end end -- Начисляем очки игрокам синей команды for k, v in pairs(BlueSideObj.Player) do local RoleObj = Poboishe_Role[v] if RoleObj and RoleObj.State == "InSide" then local Target_MapID, Target_InstanceID = role.GetRoleMapID(RoleObj.RoleID) if Target_MapID and not unit.IsDead(Target_MapID, Target_InstanceID, RoleObj.RoleID) then role.SetRoleScriptData(RoleObj.RoleID, 1, RoleDataType["Poboishe_Point"], role.GetRoleScriptData(RoleObj.RoleID, 1, RoleDataType["Poboishe_Point"]) + 1) end end end end -- Начисление очков за победу команды function SetPlayerFinalPoint_Poboishe(BattleObj) local RedSideObj = BattleObj.RedPlayer local BlueSideObj = BattleObj.BluePlayer -- Победители красной команды if RedSideObj.Point >= BlueSideObj.Point then for k, v in pairs(RedSideObj.Player) do local RoleObj = Poboishe_Role[v] if RoleObj and RoleObj.State == "InSide" then local Target_MapID, Target_InstanceID = role.GetRoleMapID(RoleObj.RoleID) if Target_MapID and not unit.IsDead(Target_MapID, Target_InstanceID, RoleObj.RoleID) then role.SetRoleScriptData(RoleObj.RoleID, 1, RoleDataType["Poboishe_win"], 1) local MsgID = msg.BeginMsgEvent() msg.AddMsgEvent(MsgID, 102, 900243) -- Победа красной команды msg.AddMsgEvent(MsgID, 5, TargetID) msg.DispatchWorldMsgEvent(MsgID) end end end end -- Победители синей команды if RedSideObj.Point <= BlueSideObj.Point then for k, v in pairs(BlueSideObj.Player) do local RoleObj = Poboishe_Role[v] if RoleObj and RoleObj.State == "InSide" then local Target_MapID, Target_InstanceID = role.GetRoleMapID(RoleObj.RoleID) if Target_MapID and not unit.IsDead(Target_MapID, Target_InstanceID, RoleObj.RoleID) then role.SetRoleScriptData(RoleObj.RoleID, 1, RoleDataType["Poboishe_win"], 1) local MsgID = msg.BeginMsgEvent() msg.AddMsgEvent(MsgID, 102, 900244) -- Победа синей команды msg.AddMsgEvent(MsgID, 5, TargetID) msg.DispatchWorldMsgEvent(MsgID) end end end end end -- Обновление списка игроков на поле боя function ResetInSidePlayer_Poboishe(BattleObj) -- Функция для перемешивания массива local function reset(tbl) local tbl_new = {} if #tbl > 0 then for i = 1, #tbl do local index = math.random(1, #tbl) table.insert(tbl_new, tbl[index]) table.remove(tbl, index) end end return tbl_new end -- Перемешиваем списки игроков на поле BattleObj.BluePlayer.InSidePlayer = reset(BattleObj.BluePlayer.InSidePlayer) BattleObj.RedPlayer.InSidePlayer = reset(BattleObj.RedPlayer.InSidePlayer) end