Иконка ресурса

FREE Notif : 1.0.0 1.0.0

Нет прав для скачивания
C#:
using Oxide.Core;
using Oxide.Core.Plugins;
using Oxide.Game.Rust.Cui;
using System;
using System.Collections.Generic;
using System.IO;
using UnityEngine;

namespace Oxide.Plugins
{
    [Info("Notif", "fufeldev", "1.0.0")]
    public class Notif : RustPlugin
    {
        [PluginReference] private Plugin SClan;

        private const string UiRoot = "Notif_UI";
        private const string UiLayer = "Notif_UI.Layer";
        private const float HoldTime = 2.5f;
        private const float KillNoticeCooldown = 60f;
        private const int KillstreakPoints = 3;
        private int _nextId;
        private string _heliPng;
        private string _killPng;
        private string _bradleyPng;
        private readonly List<Notice> _notices = new List<Notice>();
        private readonly Dictionary<ulong, int> _killStreaks = new Dictionary<ulong, int>();
        private readonly Dictionary<ulong, float> _nextKillNoticeTime = new Dictionary<ulong, float>();
        private readonly Dictionary<string, string> _imageStorageIds = new Dictionary<string, string>();
        private static readonly float[] SlotY = { 90f, 43.3333f, -4f };
        private static readonly Dictionary<string, string> ImageFiles = new Dictionary<string, string>
        {
            { "Hudaima_Event_Helicopter_CardIcon_1", "Hudaima_Event_Helicopter_CardIcon_1.png" },
            { "Hudaima_Event_Killstreak_CardIcon_1", "Hudaima_Event_Killstreak_CardIcon_1.png" },
            { "Hudaima_Event_Bradley_CardIcon_1", "Hudaima_Event_Bradley_CardIcon_1.png" }
        };

        private class Notice
        {
            public int Id;
            public string Kind;
            public string Text;
            public float Y;
            public bool Created;
        }

        private void OnServerInitialized()
        {
            LoadImageAssets();
        }

        private void LoadImageAssets()
        {
            var imageDir = Path.Combine(Interface.Oxide.DataDirectory, "Notif", "Images");
            Directory.CreateDirectory(imageDir);
            _imageStorageIds.Clear();
            foreach (var kv in ImageFiles)
            {
                var path = Path.Combine(imageDir, kv.Value);
                if (!File.Exists(path))
                {
                    PrintWarning($"[UIAssets] Missing PNG file: {path}");
                    continue;
                }
                try
                {
                    var bytes = File.ReadAllBytes(path);
                    _imageStorageIds[kv.Key] = FileStorage.server.Store(bytes, FileStorage.Type.png, CommunityEntity.ServerInstance.net.ID).ToString();
                }
                catch (Exception ex)
                {
                    PrintWarning($"[UIAssets] Failed to load {kv.Key}: {ex.Message}");
                }
            }

            _heliPng = Img("Hudaima_Event_Helicopter_CardIcon_1");
            _killPng = Img("Hudaima_Event_Killstreak_CardIcon_1");
            _bradleyPng = Img("Hudaima_Event_Bradley_CardIcon_1");
        }

        private string Img(string key)
        {
            return _imageStorageIds.TryGetValue(key, out var stored) ? stored : string.Empty;
        }

        private void OnPlayerDeath(BasePlayer player, HitInfo info)
        {
            if (player == null || player.IsNpc)
            {
                return;
            }

            _killStreaks[player.userID] = 0;
            _nextKillNoticeTime.Remove(player.userID);

            var killer = info?.InitiatorPlayer;
            if (killer == null || killer == player || killer.IsNpc || !killer.IsConnected)
            {
                return;
            }

            int streak = _killStreaks.ContainsKey(killer.userID) ? _killStreaks[killer.userID] + 1 : 1;
            _killStreaks[killer.userID] = streak;

            if (streak < 3)
            {
                return;
            }

            float nextTime;
            if (_nextKillNoticeTime.TryGetValue(killer.userID, out nextTime) && Time.realtimeSinceStartup < nextTime)
            {
                return;
            }

            _nextKillNoticeTime[killer.userID] = Time.realtimeSinceStartup + KillNoticeCooldown;
            AddNotice("kill", killer.displayName);
            SClan?.Call("AddPointsToPlayer", killer.userID, KillstreakPoints);
        }

        private void OnEntitySpawned(BaseNetworkable entity)
        {
            if (entity is PatrolHelicopter)
            {
                AddNotice("heli", null);
                return;
            }

            if (entity is BradleyAPC)
            {
                AddNotice("bradley", null);
            }
        }

        [ConsoleCommand("notif.testall")]
        private void TestAllCommand(ConsoleSystem.Arg arg)
        {
            AddNotice("heli", null);
            AddNotice("kill", arg.Player()?.displayName ?? "PLAYER");
            AddNotice("bradley", null);
        }

        private void AddNotice(string kind, string text)
        {
            for (int i = _notices.Count - 1; i >= 0; i--)
            {
                if (_notices[i].Kind != kind)
                {
                    continue;
                }

                DestroyNotice(_notices[i]);
                _notices.RemoveAt(i);
            }

            var notice = new Notice
            {
                Id = ++_nextId,
                Kind = kind,
                Text = text
            };

            _notices.Add(notice);
            SortNotices();
            var container = ApplyLayout() ?? new CuiElementContainer();
            AddNoticeUi(container, notice);
            Broadcast(container);
            notice.Created = true;
            timer.Once(HoldTime, () => RemoveNotice(notice));
        }

        private void SortNotices()
        {
            _notices.Sort((a, b) => Priority(a.Kind).CompareTo(Priority(b.Kind)));
        }

        private int Priority(string kind)
        {
            if (kind == "heli")
            {
                return 0;
            }

            if (kind == "kill")
            {
                return 1;
            }

            return 2;
        }

        private CuiElementContainer ApplyLayout()
        {
            CuiElementContainer updates = null;

            for (int i = 0; i < _notices.Count; i++)
            {
                var notice = _notices[i];
                float target = SlotY[Mathf.Min(i, SlotY.Length - 1)];
                float y = target - OriginalY(notice.Kind);
                if (notice.Created && Math.Abs(notice.Y - y) > 0.001f)
                {
                    notice.Y = y;
                    if (updates == null)
                    {
                        updates = new CuiElementContainer();
                    }

                    AddNoticePositionUpdate(updates, notice);
                    continue;
                }

                notice.Y = y;
            }

            return updates;
        }

        private float OriginalY(string kind)
        {
            if (kind == "heli")
            {
                return 90f;
            }

            if (kind == "kill")
            {
                return 43.3333f;
            }

            return -4f;
        }

        private void Broadcast(CuiElementContainer container)
        {
            Broadcast(CuiHelper.ToJson(container));
        }

        private void Broadcast(string json)
        {
            foreach (var player in BasePlayer.activePlayerList)
            {
                if (player == null || !player.IsConnected || player.IsNpc)
                {
                    continue;
                }

                CuiHelper.AddUi(player, json);
            }
        }

        private void AddNoticeUi(CuiElementContainer container, Notice notice)
        {
            string root = RootName(notice);
            string layer = LayerName(notice);

            container.Add(new CuiElement
            {
                Name = root,
                Parent = "Hud",
                Components =
                {
                    new CuiRectTransformComponent { AnchorMin = "0 0", AnchorMax = "1 1", OffsetMin = "0 0", OffsetMax = "0 0" }
                }
            });

            container.Add(new CuiElement
            {
                Name = layer,
                Parent = root,
                Components =
                {
                    CreateLayerRect(notice.Y)
                }
            });

            if (notice.Kind == "heli")
            {
                AddHeli(container, layer);
            }
            else if (notice.Kind == "kill")
            {
                AddKill(container, layer, notice.Text);
            }
            else
            {
                AddBradley(container, layer);
            }
        }

        private CuiRectTransformComponent CreateLayerRect(float y)
        {
            return new CuiRectTransformComponent
            {
                AnchorMin = "0 0",
                AnchorMax = "1 1",
                OffsetMin = $"0 {Format(y)}",
                OffsetMax = $"0 {Format(y)}"
            };
        }

        private void AddHeli(CuiElementContainer container, string parent)
        {
            container.Add(new CuiElement
            {
                Name = "Hudaima_Event_Helicopter_CardIcon_1." + parent,
                Parent = parent,
                Components =
                {
                    new CuiRawImageComponent { Color = "1 1 1 1", Png = _heliPng },
                    new CuiRectTransformComponent { AnchorMin = "1.0000 0.5000", AnchorMax = "1.0000 0.5000", OffsetMin = "-170.0000 90.0000", OffsetMax = "-22.0000 138.6667" }
                }
            });

            container.Add(new CuiElement
            {
                Parent = parent,
                Components =
                {
                    new CuiTextComponent { Text = "HELICOPTER", FontSize = 12, Align = TextAnchor.MiddleCenter, Color = "0.925 0.925 0.925 1", Font = "robotocondensed-bold.ttf" },
                    new CuiRectTransformComponent { AnchorMin = "1.0000 0.5000", AnchorMax = "1.0000 0.5000", OffsetMin = "-127.6667 113.3333", OffsetMax = "-32.3333 129.3333" }
                }
            });

            container.Add(new CuiElement
            {
                Parent = parent,
                Components =
                {
                    new CuiTextComponent { Text = "INCOMING", FontSize = 9, Align = TextAnchor.MiddleCenter, Color = "1.000 0.278 0.278 1", Font = "robotocondensed-bold.ttf" },
                    new CuiRectTransformComponent { AnchorMin = "1.0000 0.5000", AnchorMax = "1.0000 0.5000", OffsetMin = "-113.0000 101.3333", OffsetMax = "-52.3333 114.6667" }
                }
            });
        }

        private void AddKill(CuiElementContainer container, string parent, string name)
        {
            container.Add(new CuiElement
            {
                Name = "Hudaima_Event_Killstreak_CardIcon_1." + parent,
                Parent = parent,
                Components =
                {
                    new CuiRawImageComponent { Color = "1 1 1 1", Png = _killPng },
                    new CuiRectTransformComponent { AnchorMin = "1.0000 0.5000", AnchorMax = "1.0000 0.5000", OffsetMin = "-170.0000 43.3333", OffsetMax = "-22.0000 92.0000" }
                }
            });

            container.Add(new CuiElement
            {
                Parent = parent,
                Components =
                {
                    new CuiTextComponent { Text = "KILLSTREAK", FontSize = 12, Align = TextAnchor.MiddleCenter, Color = "0.925 0.925 0.925 1", Font = "robotocondensed-bold.ttf" },
                    new CuiRectTransformComponent { AnchorMin = "1.0000 0.5000", AnchorMax = "1.0000 0.5000", OffsetMin = "-127.0000 66.0000", OffsetMax = "-31.6667 82.0000" }
                }
            });

            container.Add(new CuiElement
            {
                Parent = parent,
                Components =
                {
                    new CuiTextComponent { Text = string.IsNullOrEmpty(name) ? "PLAYER" : name.ToUpperInvariant(), FontSize = 9, Align = TextAnchor.MiddleCenter, Color = "0.239 1.000 0.361 1", Font = "robotocondensed-bold.ttf" },
                    new CuiRectTransformComponent { AnchorMin = "1.0000 0.5000", AnchorMax = "1.0000 0.5000", OffsetMin = "-109.0000 54.0000", OffsetMax = "-48.3333 67.3333" }
                }
            });
        }

        private void AddBradley(CuiElementContainer container, string parent)
        {
            container.Add(new CuiElement
            {
                Name = "Hudaima_Event_Bradley_CardIcon_1." + parent,
                Parent = parent,
                Components =
                {
                    new CuiRawImageComponent { Color = "1 1 1 1", Png = _bradleyPng },
                    new CuiRectTransformComponent { AnchorMin = "1.0000 0.5000", AnchorMax = "1.0000 0.5000", OffsetMin = "-170.0000 -4.0000", OffsetMax = "-22.0000 44.6667" }
                }
            });

            container.Add(new CuiElement
            {
                Parent = parent,
                Components =
                {
                    new CuiTextComponent { Text = "BRADLEY", FontSize = 12, Align = TextAnchor.MiddleCenter, Color = "0.925 0.925 0.925 1", Font = "robotocondensed-bold.ttf" },
                    new CuiRectTransformComponent { AnchorMin = "1.0000 0.5000", AnchorMax = "1.0000 0.5000", OffsetMin = "-115.3333 18.6667", OffsetMax = "-46.0000 34.6667" }
                }
            });

            container.Add(new CuiElement
            {
                Parent = parent,
                Components =
                {
                    new CuiTextComponent { Text = "SPAWNED", FontSize = 9, Align = TextAnchor.MiddleCenter, Color = "1.000 0.278 0.278 1", Font = "robotocondensed-bold.ttf" },
                    new CuiRectTransformComponent { AnchorMin = "1.0000 0.5000", AnchorMax = "1.0000 0.5000", OffsetMin = "-107.6667 6.6667", OffsetMax = "-53.6667 20.0000" }
                }
            });
        }

        private void AddNoticePositionUpdate(CuiElementContainer container, Notice notice)
        {
            container.Add(new CuiElement
            {
                Name = LayerName(notice),
                Update = true,
                Components =
                {
                    CreateLayerRect(notice.Y)
                }
            });
        }

        private void RemoveNotice(Notice notice)
        {
            if (!_notices.Remove(notice))
            {
                return;
            }

            DestroyNotice(notice);
            var updates = ApplyLayout();
            if (updates != null)
            {
                Broadcast(updates);
            }
        }

        private void DestroyNotice(Notice notice)
        {
            foreach (var player in BasePlayer.activePlayerList)
            {
                if (player == null || !player.IsConnected || player.IsNpc)
                {
                    continue;
                }

                CuiHelper.DestroyUi(player, RootName(notice));
            }
        }

        private string RootName(Notice notice)
        {
            return UiRoot + "." + notice.Id;
        }

        private string LayerName(Notice notice)
        {
            return UiLayer + "." + notice.Id;
        }

        private static string Format(float value)
        {
            return value.ToString("0.####", System.Globalization.CultureInfo.InvariantCulture);
        }

        private void Unload()
        {
            foreach (var player in BasePlayer.activePlayerList)
            {
                if (player == null || !player.IsConnected || player.IsNpc)
                {
                    continue;
                }

                for (int i = 0; i <= _nextId; i++)
                {
                    CuiHelper.DestroyUi(player, UiRoot + "." + i);
                }
            }

            _notices.Clear();
            _killStreaks.Clear();
            _nextKillNoticeTime.Clear();
        }
    }
}

Автор
15FPS
Скачиваний
0
Просмотры
1
Первый выпуск
Обновление
Оценка
0.00 звёзд 0 оценок
Сверху