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

FREE CrateGuardCS : 1.0.0 1.0.0

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

namespace Oxide.Plugins
{
    [Info("CrateGuardCS", "Eadris", "1.0.0")]
    [Description("Spawns scientists to guard supply drop crates.")]
    public class CrateGuardCS : RustPlugin
    {
        // Register permission on plugin load
        void Init()
        {
            permission.RegisterPermission("crateguard.spawn", this);
        }

        // Configuration structure
        private class Configuration
        {
            public int MinGuardsPerCrate = 0;
            public int MaxGuardsPerCrate = 3;
            public float RoamRadius = 5f;
            public int SpawnDelaySeconds = 2; // Delay after crate lands before spawning
            public float MinSpawnDistanceFromCrate = 2f; // Minimum distance from crate center
            public bool EnableCrateGuards = true; // Toggle spawning guards for supply drop crates
        }

        private Configuration config;

        protected override void LoadConfig()
        {
            base.LoadConfig();
            config = Config.ReadObject<Configuration>();
            if (config == null)
            {
                // If the config file is empty or invalid, regenerate defaults and save
                LoadDefaultConfig();
                return;
            }
            // Ensure reasonable bounds and persist any missing/defaulted values
            if (config.MinGuardsPerCrate < 0)
            {
                config.MinGuardsPerCrate = 0;
            }
            if (config.MaxGuardsPerCrate < 0)
            {
                config.MaxGuardsPerCrate = 3;
            }
            if (config.MinGuardsPerCrate > config.MaxGuardsPerCrate)
            {
                config.MinGuardsPerCrate = 0;
                config.MaxGuardsPerCrate = Mathf.Max(1, config.MaxGuardsPerCrate);
            }
            if (config.RoamRadius <= 0f)
            {
                config.RoamRadius = 5f;
            }
            if (config.SpawnDelaySeconds < 0)
            {
                config.SpawnDelaySeconds = 0;
            }
            if (config.MinSpawnDistanceFromCrate < 0f)
            {
                config.MinSpawnDistanceFromCrate = 2f;
            }
            // Toggle defaults sanity
            // If missing, defaults above already set; no further action needed
            SaveConfig();
        }

        protected override void LoadDefaultConfig()
        {
            config = new Configuration();
            SaveConfig();
        }

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

        void OnServerInitialized()
        {
            Puts("[CrateGuardCS] Plugin loaded successfully.");
            Puts($"[CrateGuardCS] Min guards per crate: {config.MinGuardsPerCrate}");
            Puts($"[CrateGuardCS] Max guards per crate: {config.MaxGuardsPerCrate}");
            Puts($"[CrateGuardCS] Roam radius: {config.RoamRadius}");
            Puts($"[CrateGuardCS] Crate guards enabled: {config.EnableCrateGuards}");
        }

        [ChatCommand("crateguards")]
        void CmdCrateGuards(BasePlayer player, string command, string[] args)
        {
            if (!permission.UserHasPermission(player.UserIDString, "crateguard.spawn"))
            {
                player.ChatMessage("You do not have permission to use this command.");
                return;
            }

            if (args.Length == 0)
            {
                player.ChatMessage("=== CrateGuardCS Commands ===");
                player.ChatMessage("/crateguards min <number> - Set minimum guards per crate (0+)");
                player.ChatMessage("/crateguards max <number> - Set maximum guards per crate (1+)");
                player.ChatMessage("/crateguards radius <distance> - Set roam radius");
                player.ChatMessage("/crateguards delay <seconds> - Set spawn delay in seconds");
                player.ChatMessage("/crateguards mindist <distance> - Set minimum spawn distance from crate");
                player.ChatMessage("/crateguards crates <on|off> - Toggle crate guards");
                player.ChatMessage("/crateguards status - Show current settings");
                player.ChatMessage("/crateguards spawn - Spawn a scientist at your position (requires permission)");
                return;
            }

            string subcommand = args[0].ToLower();

            if (subcommand == "spawn")
            {
                Vector3 pos = player.transform.position + new Vector3(0, 2f, 0);
                SpawnScientist(pos);
                player.ChatMessage($"Spawned scientist at {pos.x}, {pos.y}, {pos.z}");
                Puts($"[CrateGuardCS] {player.displayName} spawned scientist at {pos.x}, {pos.y}, {pos.z}");
                return;
            }
            if (subcommand == "min" && args.Length > 1)
            {
                if (int.TryParse(args[1], out int minVal) && minVal >= 0)
                {
                    config.MinGuardsPerCrate = minVal;
                    if (config.MinGuardsPerCrate > config.MaxGuardsPerCrate)
                    {
                        config.MaxGuardsPerCrate = config.MinGuardsPerCrate;
                    }
                    SaveConfig();
                    player.ChatMessage($"Min guards per crate set to: {config.MinGuardsPerCrate}");
                    Puts($"[CrateGuardCS] {player.displayName} set min guards per crate to: {config.MinGuardsPerCrate}");
                }
                else
                {
                    player.ChatMessage("Invalid value. Please use a number >= 0.");
                }
            }
            else if (subcommand == "max" && args.Length > 1)
            {
                if (int.TryParse(args[1], out int maxVal) && maxVal >= 1)
                {
                    config.MaxGuardsPerCrate = maxVal;
                    if (config.MinGuardsPerCrate > config.MaxGuardsPerCrate)
                    {
                        config.MinGuardsPerCrate = config.MaxGuardsPerCrate;
                    }
                    SaveConfig();
                    player.ChatMessage($"Max guards per crate set to: {config.MaxGuardsPerCrate}");
                    Puts($"[CrateGuardCS] {player.displayName} set max guards per crate to: {config.MaxGuardsPerCrate}");
                }
                else
                {
                    player.ChatMessage("Invalid value. Please use a number >= 1.");
                }
            }
            else if (subcommand == "radius" && args.Length > 1)
            {
                if (float.TryParse(args[1], out float radius) && radius > 0f)
                {
                    config.RoamRadius = radius;
                    SaveConfig();
                    player.ChatMessage($"Roam radius set to: {radius}");
                    Puts($"[CrateGuardCS] {player.displayName} set roam radius to: {radius}");
                }
                else
                {
                    player.ChatMessage("Invalid value. Please use a positive number.");
                }
            }
            else if (subcommand == "delay" && args.Length > 1)
            {
                if (int.TryParse(args[1], out int delay) && delay >= 0)
                {
                    config.SpawnDelaySeconds = delay;
                    SaveConfig();
                    player.ChatMessage($"Spawn delay set to: {delay} seconds");
                    Puts($"[CrateGuardCS] {player.displayName} set spawn delay to: {delay} seconds");
                }
                else
                {
                    player.ChatMessage("Invalid value. Please use a non-negative number.");
                }
            }
            else if (subcommand == "mindist" && args.Length > 1)
            {
                if (float.TryParse(args[1], out float minDist) && minDist >= 0f)
                {
                    config.MinSpawnDistanceFromCrate = minDist;
                    SaveConfig();
                    player.ChatMessage($"Minimum spawn distance from crate set to: {minDist}");
                    Puts($"[CrateGuardCS] {player.displayName} set min spawn distance to: {minDist}");
                }
                else
                {
                    player.ChatMessage("Invalid value. Please use a non-negative number.");
                }
            }
            else if (subcommand == "crates" && args.Length > 1)
            {
                string val = args[1].ToLowerInvariant();
                if (val == "on" || val == "off")
                {
                    config.EnableCrateGuards = val == "on";
                    SaveConfig();
                    player.ChatMessage($"Crate guards {(config.EnableCrateGuards ? "enabled" : "disabled")}");
                    Puts($"[CrateGuardCS] {player.displayName} {(config.EnableCrateGuards ? "enabled" : "disabled")} crate guards");
                }
                else
                {
                    player.ChatMessage("Invalid value. Use on|off.");
                }
            }
            else if (subcommand == "status")
            {
                player.ChatMessage("=== CrateGuardCS Status ===");
                player.ChatMessage($"Min guards per crate: {config.MinGuardsPerCrate}");
                player.ChatMessage($"Max guards per crate: {config.MaxGuardsPerCrate}");
                player.ChatMessage($"Roam radius: {config.RoamRadius}");
                player.ChatMessage($"Spawn delay: {config.SpawnDelaySeconds} seconds");
                player.ChatMessage($"Min spawn distance from crate: {config.MinSpawnDistanceFromCrate}");
                player.ChatMessage($"Crate guards: {(config.EnableCrateGuards ? "enabled" : "disabled")}");
            }
            else
            {
                player.ChatMessage("Unknown subcommand. Use /crateguards for help.");
            }
        }

        // Spawn scientist NPC at a given position
        // Common scientist prefab variations in Rust:
        // - assets/prefabs/npc/scientist/htn/scientist_full_any.prefab (common)
        // - assets/rust.ai/agents/npcplayer/humannpc/scientist/scientistnpc_roam.prefab
        // - assets/rust.ai/agents/npcplayer/humannpc/scientist/scientistnpc_roam_tethered.prefab
        private const string ScientistPrefab = "assets/rust.ai/agents/npcplayer/humannpc/scientist/scientistnpc_roam.prefab";

        // Raycast constants for ground detection when spawning scientists
        private const float RaycastStartHeight = 50f;
        private const float DefaultGroundOffset = 1.5f;
        private const float RaycastMaxDistance = 100f;
        // NOTE: Rust 2025 does not support customizing patrol, aggression, or roam radius via plugin code.
        // The RoamRadius config only affects spawn position randomization, not AI behavior.
        // Scientists will use default prefab AI (patrol, attack, roam) as defined by the server.
        void SpawnScientist(Vector3 position)
        {
            BaseEntity entity = GameManager.server.CreateEntity(ScientistPrefab, position, Quaternion.identity);
            if (entity != null)
            {
                entity.Spawn();
                Puts($"[CrateGuardCS] Entity spawned: Type={entity.GetType().Name}, ShortPrefabName={entity.ShortPrefabName}");
                timer.Once(1f, () => {
                    if (entity != null && !entity.IsDestroyed)
                    {
                        Puts($"[CrateGuardCS] Entity confirmed alive at {position}");
                    }
                    else
                    {
                        Puts($"[CrateGuardCS] Entity failed to spawn at {position}");
                    }
                });
            }
            else
            {
                Puts($"[CrateGuardCS] Failed to create entity with prefab: {ScientistPrefab}");
            }
        }

        // --- Oxide Hook (The main logic) ---
        void OnSupplyDropLanded(SupplyDrop supplyDrop)
        {
            if (supplyDrop == null || !supplyDrop.IsValid()) 
            {
                return;
            }

            if (!config.EnableCrateGuards)
            {
                return;
            }

            Vector3 cratePos = supplyDrop.transform.position;
            int minG = Mathf.Max(0, config.MinGuardsPerCrate);
            int maxG = Mathf.Max(minG, config.MaxGuardsPerCrate);
            int guards = Random.Range(minG, maxG + 1);
            Puts($"[CrateGuardCS] Supply Crate landed at {cratePos}. Will spawn {guards} guards in {config.SpawnDelaySeconds} seconds...");

            timer.Once(config.SpawnDelaySeconds, () => {
                for (int i = 0; i < guards; i++)
                {
                    // Ensure spawn offset is at least MinSpawnDistanceFromCrate units away from crate center
                    float xOffset = Random.Range(-config.RoamRadius, config.RoamRadius);
                    float zOffset = Random.Range(-config.RoamRadius, config.RoamRadius);
                    float distance = Mathf.Sqrt(xOffset * xOffset + zOffset * zOffset);
                    if (distance > 0f && distance < config.MinSpawnDistanceFromCrate)
                    {
                        float scale = config.MinSpawnDistanceFromCrate / distance;
                        xOffset *= scale;
                        zOffset *= scale;
                    }
                    else if (distance == 0f)
                    {
                        // If both offsets are zero, use a default offset
                        xOffset = config.MinSpawnDistanceFromCrate;
                        zOffset = 0f;
                    }
                    
                    Vector3 abovePos = cratePos + new Vector3(xOffset, RaycastStartHeight, zOffset);
                    RaycastHit hit;
                    Vector3 groundPos = cratePos + new Vector3(xOffset, DefaultGroundOffset, zOffset);
                    if (Physics.Raycast(abovePos, Vector3.down, out hit, RaycastMaxDistance, LayerMask.GetMask("Terrain", "World", "Default")))
                    {
                        groundPos = hit.point;
                    }
                    Puts($"[CrateGuardCS] Spawning scientist at {groundPos.x}, {groundPos.y}, {groundPos.z}");
                    SpawnScientist(groundPos);
                }
            });
        }
    }
}

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