DoomsdayNight = DoomsdayNight or {} DoomsdayNight.active = false DoomsdayNight.start_time = 0 DoomsdayNight.participants = {} DoomsdayNight.spectators = {} DoomsdayNight.spawn_positions = {} DoomsdayNight.weapons = { "tfa_ins2_ak74", "tfa_ins2_m4a1", "tfa_ins2_ak12", "tfa_ins2_m16a4", "tfa_ins2_scar_h_ssr", "tfa_ins2_m40a1", "tfa_ins2_mosin", "tfa_ins2_svd", "tfa_ins2_m590", "tfa_ins2_toz", "tfa_ins2_glock_17", "tfa_ins2_m9", "tfa_ins2_makarov", "tfa_ins2_mp5", "tfa_ins2_ump45", "tfa_ins2_mp40" } util.AddNetworkString("doomsday_night_notification") util.AddNetworkString("doomsday_night_hud_update") function DoomsdayNight:Init() SetGlobalBool("doomsday_night_active", false) SetGlobalInt("doomsday_night_start_time", 0) SetGlobalInt("doomsday_night_alive_count", 0) self:GenerateSpawnPositions() end function DoomsdayNight:GenerateSpawnPositions() local map = game.GetMap() local map_positions = { ["gm_construct"] = { Vector(980, -1500, -79), Vector(-700, 1000, 200), Vector(1500, 800, 100), Vector(-1200, -800, 50) }, ["rp_valkyrie_forest_v1"] = { Vector(5000, 3000, 200), Vector(-5000, -3000, 150), Vector(8000, -2000, 100), Vector(-8000, 2000, 180) } } self.spawn_positions = map_positions[map] or { Vector(1000, 1000, 100), Vector(-1000, -1000, 100) } end function DoomsdayNight:StartEvent(ply) local players = player.GetAll() if (#players < 2) then ply:Notify("Недостаточно игроков для начала Судной Ночи!") return end self.active = true self.start_time = CurTime() self.participants = {} self.spectators = {} SetGlobalBool("doomsday_night_active", true) SetGlobalInt("doomsday_night_start_time", CurTime()) for _, player in ipairs(players) do if (IsValid(player)) then self:PreparePlayer(player) end end self:BroadcastMessage("🌙 СУДНАЯ НОЧЬ НАЧАЛАСЬ! 🌙\nСражайтесь до последнего выжившего!\nВыдано случайное оружие.") timer.Simple(3, function() if (self.active) then self:TeleportPlayers() end end) self:UpdateHUD() end function DoomsdayNight:PreparePlayer(ply) local steamid = ply:SteamID() self.participants[steamid] = { start_pos = ply:GetPos(), join_time = CurTime(), kills = 0, nick = ply:Nick(), alive = true } ply:StripWeapons() self:GiveRandomWeapons(ply) end function DoomsdayNight:GiveRandomWeapons(ply) if (!IsValid(ply) or !ply:Alive()) then return end ply:Give("ix_hands") local weapons_to_give = {} local used = {} for i = 1, math.random(2, 3) do local w = self.weapons[math.random(1, #self.weapons)] if (!used[w]) then used[w] = true table.insert(weapons_to_give, w) end end for _, w_class in ipairs(weapons_to_give) do local weapon = ply:Give(w_class) if (IsValid(weapon)) then ply:GiveAmmo(500, weapon:GetPrimaryAmmoType(), true) end end ply:Give("weapon_frag") ply:GiveAmmo(2, "Grenade", true) ply:SetHealth(100) ply:SetArmor(100) end function DoomsdayNight:TeleportPlayers() local players = {} for steamid, data in pairs(self.participants) do local ply = player.GetBySteamID(steamid) if (IsValid(ply)) then table.insert(players, ply) end end local positions = table.Copy(self.spawn_positions) for i, ply in ipairs(players) do local spawn_pos = positions[((i - 1) % #positions) + 1] ply:SetPos(spawn_pos) ply:SetEyeAngles(Angle(0, math.random(0, 360), 0)) end SetGlobalInt("doomsday_night_alive_count", #players) self:BroadcastMessage("⚡ Игроки телепортированы! К БОЮ!") end function DoomsdayNight:EndEvent(ply, cancelled) if (!self.active) then return end self.active = false SetGlobalBool("doomsday_night_active", false) for steamid, _ in pairs(self.spectators) do local spec_ply = player.GetBySteamID(steamid) if (IsValid(spec_ply)) then spec_ply:UnSpectate() spec_ply:Spawn() end end self:BroadcastMessage(cancelled and "🛑 СУДНАЯ НОЧЬ ОТМЕНЕНА" or "🏆 СУДНАЯ НОЧЬ ЗАВЕРШЕНА") self.participants = {} self.spectators = {} self:UpdateHUD() end function DoomsdayNight:OnPlayerKilled(victim, attacker) if (!self.active) then return end local data = self.participants[victim:SteamID()] if (!data) then return end data.alive = false if (IsValid(attacker) and attacker:IsPlayer()) then local attacker_data = self.participants[attacker:SteamID()] if (attacker_data) then attacker_data.kills = attacker_data.kills + 1 end end timer.Simple(2, function() if (IsValid(victim)) then self.spectators[victim:SteamID()] = true victim:Spectate(OBS_MODE_ROAMING) victim:Notify("👁️ Вы перешли в режим наблюдения до конца ивента.") end end) local alive_count = 0 for _, d in pairs(self.participants) do if (d.alive) then alive_count = alive_count + 1 end end SetGlobalInt("doomsday_night_alive_count", alive_count) if (alive_count <= 1) then timer.Simple(3, function() if (self.active) then self:EndEvent() end end) end end function DoomsdayNight:BroadcastMessage(msg) for _, ply in ipairs(player.GetAll()) do ply:ChatPrint(msg) end end function DoomsdayNight:UpdateHUD() net.Start("doomsday_night_hud_update") net.WriteBool(self.active) net.WriteInt(self.start_time, 32) net.Broadcast() end -- Hook aliases for PLUGIN function PLUGIN:DoomsdayNight_Init() DoomsdayNight:Init() end function PLUGIN:DoomsdayNight_PlayerDeath(victim, inflictor, attacker) DoomsdayNight:OnPlayerKilled(victim, attacker) end hook.Add("InitPostEntity", "DoomsdayNight_Init", function() DoomsdayNight:Init() end)