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

FREE ChickenLover : 1.9.0 1.9.0

Нет прав для скачивания
C#:
// File: oxide/plugins/ChickenLover.cs

using System;
using System.Collections.Generic;
using Facepunch;
using Oxide.Game.Rust.Cui;
using UnityEngine;

namespace Oxide.Plugins
{
    [Info("ChickenLover", "xADROCx", "1.9.0")]
    [Description("Adds a Chicken Lover button to Chicken Coop UI that satisfies only the chickens inside the coop you are currently looting.")]
    public class ChickenLover : RustPlugin
    {
        private const string PermUse = "chickenlover.use";
        private const string UiRootName = "ChickenLover.UI";
        private const string CmdLove = "chickenlover.love";

        // Hardcoded UI placement
        private const string UiParent = "Hud.Menu";
        private const string UiAnchorMin = "0.805 0.915";
        private const string UiAnchorMax = "0.955 0.955";
        private const string UiOffsetMin = "2 2";
        private const string UiOffsetMax = "-2 -2";
        private const int UiFontSize = 12;

        private const string UiButtonColorDisabled = "0.45 0.45 0.45 0.85";

        private ConfigData _config;

        private readonly Dictionary<ulong, LootSession> _sessions = new Dictionary<ulong, LootSession>();
        private HashSet<string> _allowedPrefabs = new HashSet<string>(StringComparer.Ordinal);

        private class LootSession
        {
            public NetworkableId CoopNetId;
            public bool Used;
        }

        private class ConfigData
        {
            public UiSettings UI = new UiSettings();
            public ActionSettings Action = new ActionSettings();
        }

        private class UiSettings
        {
            public string ReadyText = "♥ ♥ ♥CHICKEN LOVE♥ ♥ ♥";
            public string DoneText = "YOU SATISFIED THEIR NEEDS";

            public string TextColor = "1 1 1 1";
            public string ButtonColor = "1 0.3921569 0 1";
            public string ButtonColorDone = "1 0 0.3254902 1";

            public bool UseBackdrop = true;
            public string BackdropColor = "0 0 0 0.35";
        }

        private class ActionSettings
        {
            public float ScanRadius = 6f;

            public string[] ChickenShortPrefabNames =
            {
                "simplechicken.entity"
            };

            public bool HealToFull = true;
            public bool FillNeedsToFull = true;
        }

        private void Init() => permission.RegisterPermission(PermUse, this);

        protected override void LoadDefaultConfig()
        {
            _config = new ConfigData();
            SaveConfig();
            RebuildPrefabCache();
        }

        protected override void LoadConfig()
        {
            base.LoadConfig();

            try
            {
                _config = Config.ReadObject<ConfigData>();
                if (_config == null || _config.UI == null || _config.Action == null)
                    throw new Exception("Invalid config object");

                _config.Action.ScanRadius = Mathf.Clamp(_config.Action.ScanRadius, 1f, 20f);

                if (_config.Action.ChickenShortPrefabNames == null || _config.Action.ChickenShortPrefabNames.Length == 0)
                    _config.Action.ChickenShortPrefabNames = new[] { "simplechicken.entity" };

                RebuildPrefabCache();
            }
            catch
            {
                PrintWarning("Config invalid; loading defaults.");
                LoadDefaultConfig();
            }
        }

        protected override void SaveConfig() => Config.WriteObject(_config, true);

        private void Unload()
        {
            foreach (var p in BasePlayer.activePlayerList)
                DestroyUi(p);

            _sessions.Clear();
        }

        private void OnPlayerDisconnected(BasePlayer player, string reason)
        {
            if (player == null) return;
            EndSession(player);
        }

        private void OnLootEntity(BasePlayer player, BaseEntity entity)
        {
            if (player == null || entity == null) return;

            var coop = entity as ChickenCoop;
            if (coop == null) return;

            if (!HasPerm(player)) return;

            _sessions[player.userID] = new LootSession
            {
                CoopNetId = coop.net != null ? coop.net.ID : default(NetworkableId),
                Used = false
            };

            NextTick(() => RefreshUi(player));
        }

        private void OnLootEntityEnd(BasePlayer player, BaseEntity entity)
        {
            if (player == null) return;
            if (entity is ChickenCoop) EndSession(player);
        }

        private void OnPlayerLootEnd(BasePlayer player)
        {
            if (player == null) return;
            EndSession(player);
        }

        [ConsoleCommand(CmdLove)]
        private void CmdLoveHandler(ConsoleSystem.Arg arg)
        {
            var player = arg?.Player();
            if (player == null) return;

            if (!HasPerm(player))
            {
                player.ChatMessage("You don't have permission to use Chicken Lover.");
                return;
            }

            if (!_sessions.TryGetValue(player.userID, out var session) || session.CoopNetId.Value == 0 || session.Used)
                return;

            var coop = BaseNetworkable.serverEntities.Find(session.CoopNetId) as ChickenCoop;
            if (coop == null) return;

            var matched = ApplyToChickensInCoop(coop);

            if (matched <= 0)
            {
                player.ChatMessage("Chicken Lover: no chickens found in this coop.");
                return;
            }

            session.Used = true;
            RefreshUi(player);
        }

        private int ApplyToChickensInCoop(ChickenCoop coop)
        {
            var matched = 0;
            var animals = Pool.Get<List<FarmableAnimal>>();
            Vis.Entities(coop.transform.position, _config.Action.ScanRadius, animals);

            for (var i = 0; i < animals.Count; i++)
            {
                var animal = animals[i];
                if (animal == null || !_allowedPrefabs.Contains(animal.ShortPrefabName)) continue;
                if (!IsInThisCoop(animal, coop)) continue;

                matched++;
                var changed = false;

                if (_config.Action.FillNeedsToFull)
                    changed |= TryFillNeedsToFull(animal);

                if (_config.Action.HealToFull)
                    changed |= TryHealToFull(animal);

                if (changed)
                    animal.SendNetworkUpdate();
            }

            if (matched > 0)
                coop.SendNetworkUpdate();

            Pool.FreeUnmanaged(ref animals);
            return matched;
        }

        private static bool IsInThisCoop(BaseEntity entity, BaseEntity coop)
        {
            if (entity == null || coop == null) return false;

            try
            {
                var parent = entity.GetParentEntity();
                if (parent == coop) return true;
            }
            catch { }

            try
            {
                if (entity.transform?.IsChildOf(coop.transform) == true)
                    return true;
            }
            catch { }

            return false;
        }

        private static bool TryFillNeedsToFull(FarmableAnimal animal)
        {
            var full = GuessNeedsFullValue(animal);
            var changed = false;

            if (!Mathf.Approximately(animal.AnimalHunger, full))
            {
                animal.AnimalHunger = full;
                changed = true;
            }
            if (!Mathf.Approximately(animal.AnimalThirst, full))
            {
                animal.AnimalThirst = full;
                changed = true;
            }
            if (!Mathf.Approximately(animal.AnimalLove, full))
            {
                animal.AnimalLove = full;
                changed = true;
            }
            if (!Mathf.Approximately(animal.AnimalSunlight, full))
            {
                animal.AnimalSunlight = full;
                changed = true;
            }

            return changed;
        }

        private static float GuessNeedsFullValue(FarmableAnimal animal)
        {
            var max = Mathf.Max(animal.AnimalHunger, animal.AnimalThirst, animal.AnimalLove, animal.AnimalSunlight);
            return max > 1.01f ? 100f : 1f;
        }

        private static bool TryHealToFull(BaseCombatEntity ent)
        {
            if (ent == null) return false;

            var max = ent.MaxHealth();
            if (max <= 0f) max = ent.startHealth;
            if (max <= 0f || ent.health >= max - 0.01f) return false;

            try
            {
                ent.Heal(max);
            }
            catch
            {
                ent.health = max;
            }

            ent.SendNetworkUpdate();
            return ent.health >= max - 0.01f;
        }

        private void RefreshUi(BasePlayer player)
        {
            if (player == null || !player.IsConnected) return;
            if (!_sessions.TryGetValue(player.userID, out var session)) return;

            var coop = BaseNetworkable.serverEntities.Find(session.CoopNetId) as ChickenCoop;
            if (coop == null)
            {
                DestroyUi(player);
                return;
            }

            var hasChickens = CheckForChickens(coop);
            ShowUi(player, session.Used, hasChickens);
        }

        private bool CheckForChickens(ChickenCoop coop)
        {
            var animals = Pool.Get<List<FarmableAnimal>>();
            Vis.Entities(coop.transform.position, _config.Action.ScanRadius, animals);

            for (var i = 0; i < animals.Count; i++)
            {
                var animal = animals[i];
                if (animal != null && _allowedPrefabs.Contains(animal.ShortPrefabName) && IsInThisCoop(animal, coop))
                {
                    Pool.FreeUnmanaged(ref animals);
                    return true;
                }
            }

            Pool.FreeUnmanaged(ref animals);
            return false;
        }

        private void ShowUi(BasePlayer player, bool done, bool hasChickens)
        {
            DestroyUi(player);

            var container = new CuiElementContainer();

            var root = container.Add(new CuiPanel
            {
                Image = { Color = "0 0 0 0" },
                RectTransform = { AnchorMin = UiAnchorMin, AnchorMax = UiAnchorMax },
                CursorEnabled = true
            }, UiParent, UiRootName);

            var innerParent = root;

            if (_config.UI.UseBackdrop)
            {
                innerParent = container.Add(new CuiPanel
                {
                    Image = { Color = _config.UI.BackdropColor },
                    RectTransform = { AnchorMin = "0 0", AnchorMax = "1 1" },
                    CursorEnabled = false
                }, root);
            }

            var disabled = !done && !hasChickens;
            var cmd = (done || disabled) ? string.Empty : CmdLove;
            var btnColor = done ? _config.UI.ButtonColorDone : (disabled ? UiButtonColorDisabled : _config.UI.ButtonColor);
            var text = done ? _config.UI.DoneText : _config.UI.ReadyText;

            container.Add(new CuiButton
            {
                Button = { Command = cmd, Color = btnColor },
                RectTransform = { AnchorMin = "0 0", AnchorMax = "1 1", OffsetMin = UiOffsetMin, OffsetMax = UiOffsetMax },
                Text = { Text = text, FontSize = UiFontSize, Align = TextAnchor.MiddleCenter, Color = _config.UI.TextColor }
            }, innerParent);

            CuiHelper.AddUi(player, container);
        }

        private void EndSession(BasePlayer player)
        {
            DestroyUi(player);
            _sessions.Remove(player.userID);
        }

        private void DestroyUi(BasePlayer player)
        {
            if (player == null) return;
            CuiHelper.DestroyUi(player, UiRootName);
        }

        private void RebuildPrefabCache()
        {
            _allowedPrefabs.Clear();

            var list = _config?.Action?.ChickenShortPrefabNames;
            if (list == null) return;

            for (var i = 0; i < list.Length; i++)
            {
                var s = list[i];
                if (!string.IsNullOrWhiteSpace(s))
                    _allowedPrefabs.Add(s.Trim());
            }
        }

        private bool HasPerm(BasePlayer player) =>
            player != null && permission.UserHasPermission(player.UserIDString, PermUse);
    }
}

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