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

FREE MonsterHunt : 1.0.0 1.0.0

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

namespace Oxide.Plugins
{
    [Info("Monster Hunt", "0killrest", "1.0.0")]
    [Description("Periodic monster spawns with rewards for killing them")]
    internal class MonsterHunt : RustPlugin
    {
        #region Configuration
        private static ConfigData config;
        
        private class ConfigData
        {
            public bool Enabled { get; set; } = true;
            public float SpawnIntervalMinutes { get; set; } = 30f;
            public int MaxMonstersAtOnce { get; set; } = 1;
            public bool AnnounceToAllPlayers { get; set; } = true;
            public List<MonsterConfig> Monsters { get; set; }
            public List<RewardItem> KillRewards { get; set; }

            public ConfigData()
            {
                Monsters = new List<MonsterConfig>
                {
                    new MonsterConfig
                    {
                        Name = "Radioactive Bear",
                        Prefab = "assets/rust.ai/agents/bear/bear.prefab",
                        Health = 1000f,
                        Damage = 50f,
                        Scale = 1.5f,
                        Color = "red",
                        SpawnChance = 0.5f
                    },
                    new MonsterConfig
                    {
                        Name = "Frozen Wolf",
                        Prefab = "assets/rust.ai/agents/wolf/wolf.prefab",
                        Health = 600f,
                        Damage = 35f,
                        Scale = 1.3f,
                        Color = "cyan",
                        SpawnChance = 0.3f
                    },
                    new MonsterConfig
                    {
                        Name = "Lava Boar",
                        Prefab = "assets/rust.ai/agents/boar/boar.prefab",
                        Health = 800f,
                        Damage = 40f,
                        Scale = 1.4f,
                        Color = "orange",
                        SpawnChance = 0.2f
                    }
                };
                
                KillRewards = new List<RewardItem>
                {
                    new RewardItem { ShortName = "scrap", Amount = 100, MinAmount = 50, MaxAmount = 200, DisplayName = "Scrap" },
                    new RewardItem { ShortName = "metal.refined", Amount = 50, MinAmount = 25, MaxAmount = 100, DisplayName = "Metal Fragments" },
                    new RewardItem { ShortName = "ammo.rifle", Amount = 30, MinAmount = 15, MaxAmount = 60, DisplayName = "Rifle Ammo" },
                    new RewardItem { ShortName = "cloth", Amount = 100, MinAmount = 50, MaxAmount = 200, DisplayName = "Cloth" }
                };
            }
        }
        
        public class MonsterConfig
        {
            public string Name { get; set; }
            public string Prefab { get; set; }
            public float Health { get; set; }
            public float Damage { get; set; }
            public float Scale { get; set; } = 1f;
            public string Color { get; set; } = "white";
            public float SpawnChance { get; set; } = 0.5f;
        }
        
        public class RewardItem
        {
            public string ShortName { get; set; }
            public int Amount { get; set; }
            public int MinAmount { get; set; }
            public int MaxAmount { get; set; }
            public string DisplayName { get; set; }
        }
        
        protected override void LoadConfig()
        {
            base.LoadConfig();
            config = Config.ReadObject<ConfigData>();
            if (config == null)
            {
                LoadDefaultConfig();
            }
        }
        
        protected override void LoadDefaultConfig()
        {
            config = new ConfigData();
            PrintWarning("Default configuration created.Edit it in oxide/config/MonsterHunt.json");
            SaveConfig();
        }
        
        protected override void SaveConfig() => Config.WriteObject(config);
        #endregion

        #region Data Storage
        private List<HuntMonster> activeMonsters = new List<HuntMonster>();
        private Timer spawnTimer;
        private Random random = new Random();
        
        private class HuntMonster
        {
            public BaseEntity Entity { get; set; }
            public BaseCombatEntity Combat { get; set; }
            public MonsterConfig Config { get; set; }
            public Vector3 SpawnPosition { get; set; }
            public float SpawnTime { get; set; }
            public bool IsAlive { get; set; } = true;
        }
        #endregion

        #region Hooks
        private void Init()
        {
            LoadConfig();
            permission.RegisterPermission("monsterhunt.admin", this);
        }
        
        private void OnServerInitialized()
        {
            if (config.Enabled)
            {
                StartSpawnTimer();
            }
        }
        
        private void Unload()
        {
            spawnTimer?.Destroy();
            DespawnAllMonsters();
        }
        
        private void StartSpawnTimer()
        {
            if (spawnTimer != null)
            {
                spawnTimer.Destroy();
            }
            
            spawnTimer = timer.Repeat(config.SpawnIntervalMinutes * 60f, 0, () =>
            {
                SpawnMonsters();
            });
            
            Puts($"MonsterHunt enabled: spawning every {config.SpawnIntervalMinutes} minutes");
        }
        
        private void SpawnMonsters()
        {
            if (!config.Enabled) return;
            
            // Clean up dead monsters
            activeMonsters.RemoveAll(m => m.Entity == null || m.Entity.IsDestroyed || (m.Combat != null && m.Combat.IsDead()));
            
            int currentCount = activeMonsters.Count;
            int toSpawn = Math.Max(0, config.MaxMonstersAtOnce - currentCount);
            
            if (toSpawn <= 0) return;
            
            for (int i = 0; i < toSpawn; i++)
            {
                SpawnRandomMonster();
            }
            
            if (config.AnnounceToAllPlayers && toSpawn > 0)
            {
                string message = $"<color=red>⚠️ A deadly monster has appeared on the island!</color> Find and kill it for rewards!";
                Server.Broadcast(message);
                PrintToChat(message);
            }
        }
        
        private void SpawnRandomMonster()
        {
            // Select random monster based on spawn chance
            float totalChance = config.Monsters.Sum(m => m.SpawnChance);
            float randomValue = (float)random.NextDouble() * totalChance;
            float cumulative = 0f;
            MonsterConfig selectedConfig = null;
            
            foreach (var monster in config.Monsters)
            {
                cumulative += monster.SpawnChance;
                if (randomValue <= cumulative)
                {
                    selectedConfig = monster;
                    break;
                }
            }
            
            if (selectedConfig == null) selectedConfig = config.Monsters.First();
            
            // Find spawn position (random on map, away from monuments)
            Vector3 spawnPos = GetRandomSpawnPosition();
            
            // Spawn the entity
            BaseEntity entity = GameManager.server.CreateEntity(selectedConfig.Prefab, spawnPos);
            if (entity == null)
            {
                PrintError($"Failed to spawn monster: {selectedConfig.Prefab}");
                return;
            }
            
            BaseCombatEntity combat = entity as BaseCombatEntity;
            if (combat == null)
            {
                entity.Kill();
                PrintError($"Spawned entity is not a combat entity: {selectedConfig.Prefab}");
                return;
            }
            
            // Apply monster properties
            combat.health = selectedConfig.Health;
            combat.maxHealth = selectedConfig.Health;
            combat.StartHealthRegeneration(0f, 0f, 0f);
            
            // Scale the entity
            entity.transform.localScale = Vector3.one * selectedConfig.Scale;
            
            // Set custom name
            combat.displayName = $"<color={selectedConfig.Color}>★ {selectedConfig.Name} ★</color>";
            
            entity.Spawn();
            
            // Add to active monsters
            activeMonsters.Add(new HuntMonster
            {
                Entity = entity,
                Combat = combat,
                Config = selectedConfig,
                SpawnPosition = spawnPos,
                SpawnTime = Time.realtimeSinceStartup,
                IsAlive = true
            });
            
            Puts($"Spawned monster: {selectedConfig.Name} at {spawnPos}");
            
            // Create map marker
            CreateMonsterMarker(entity, selectedConfig);
        }
        
        private Vector3 GetRandomSpawnPosition()
        {
            // Try up to 20 times to find a valid spawn position
            for (int i = 0; i < 20; i++)
            {
                float x = (float)random.NextDouble() * TerrainMeta.Size.x;
                float z = (float)random.NextDouble() * TerrainMeta.Size.z;
                float y = TerrainMeta.HeightMap.GetHeight(new Vector3(x, 0, z));
                
                Vector3 pos = new Vector3(x, y, z);
                
                // Check if not too close to monuments or other monsters
                bool valid = true;
                foreach (var monument in UnityEngine.Object.FindObjectsOfType<MonumentInfo>())
                {
                    if (Vector3.Distance(pos, monument.transform.position) < 100f)
                    {
                        valid = false;
                        break;
                    }
                }
                
                if (valid) return pos;
            }
            
            // Fallback to a default position
            return new Vector3(0, TerrainMeta.HeightMap.GetHeight(new Vector3(0, 0, 0)), 0);
        }
        
        private void CreateMonsterMarker(BaseEntity entity, MonsterConfig config)
        {
            var marker = GameManager.server.CreateEntity("assets/prefabs/deployable/chickencoop/chickencoop.deployed.prefab", entity.transform.position);
            if (marker != null)
            {
                // Use marker visibility system
                foreach (var player in BasePlayer.activePlayerList)
                {
                    player.SendConsoleCommand("createmarker", entity.net.ID, $"☠️ {config.Name}", config.Color, entity.transform.position);
                }
            }
        }
        
        private void DespawnAllMonsters()
        {
            foreach (var monster in activeMonsters)
            {
                if (monster.Entity != null && !monster.Entity.IsDestroyed)
                {
                    monster.Entity.Kill();
                }
            }
            activeMonsters.Clear();
        }
        
        private void OnEntityDeath(BaseCombatEntity entity, HitInfo info)
        {
            // Check if this is one of our monsters
            var huntMonster = activeMonsters.FirstOrDefault(m => m.Combat == entity);
            if (huntMonster == null) return;
            
            huntMonster.IsAlive = false;
            
            // Determine who killed it
            BasePlayer killer = info?.InitiatorPlayer;
            
            // Give rewards to killer and nearby players
            List<BasePlayer> rewardedPlayers = new List<BasePlayer>();
            
            if (killer != null && killer.IsConnected)
            {
                rewardedPlayers.Add(killer);
                GiveReward(killer, huntMonster.Config);
            }
            
            // Also reward players within 50m
            foreach (var player in BasePlayer.activePlayerList)
            {
                if (player != killer && Vector3.Distance(player.transform.position, huntMonster.Entity.transform.position) <= 50f)
                {
                    rewardedPlayers.Add(player);
                    GiveReward(player, huntMonster.Config);
                }
            }
            
            // Announce death
            string killMessage = $"<color=red>💀 {huntMonster.Config.Name} has been defeated!</color>";
            if (killer != null)
            {
                killMessage = $"<color=green>🏆 {killer.displayName} killed {huntMonster.Config.Name}!</color>";
            }
            Server.Broadcast(killMessage);
            
            // Drop loot chest
            DropLootCrate(huntMonster.Entity.transform.position, huntMonster.Config);
            
            // Remove from active list
            activeMonsters.Remove(huntMonster);
        }
        
        private void GiveReward(BasePlayer player, MonsterConfig monsterConfig)
        {
            Random rnd = new Random();
            
            foreach (var reward in config.KillRewards)
            {
                int amount = reward.Amount;
                if (reward.MinAmount > 0 && reward.MaxAmount > 0)
                {
                    amount = rnd.Next(reward.MinAmount, reward.MaxAmount + 1);
                }
                
                ItemDefinition itemDef = ItemManager.FindItemDefinition(reward.ShortName);
                if (itemDef != null)
                {
                    Item item = ItemManager.Create(itemDef, amount);
                    if (item != null && player.inventory.GiveItem(item))
                    {
                        SendReply(player, $"<color=green>+{amount} {reward.DisplayName}</color> for killing {monsterConfig.Name}!");
                    }
                }
            }
            
            // Also give some XP if XPLevels is installed
            PlayerData(player.userID);
        }
        
        private void DropLootCrate(Vector3 position, MonsterConfig config)
        {
            // Spawn a loot crate at death position
            var crate = GameManager.server.CreateEntity("assets/prefabs/misc/supply drop/supply_drop.prefab", position);
            if (crate != null)
            {
                crate.Spawn();
                
                var lootContainer = crate.GetComponent<LootContainer>();
                if (lootContainer != null)
                {
                    lootContainer.PopulateLoot();
                    
                    // Add extra monster-specific loot
                    foreach (var reward in config.KillRewards)
                    {
                        // Additional logic for crate loot
                    }
                }
            }
        }
        
        private void PlayerData(ulong userId)
        {
            // Placeholder for XP integration
            // This would connect to XPLevels plugin if installed
        }
        
        private void RemoveMarkersForMonster(HuntMonster monster)
        {
            foreach (var player in BasePlayer.activePlayerList)
            {
                player.SendConsoleCommand("removemarker", monster.Entity.net.ID);
            }
        }
        #endregion

        #region Commands
        [ChatCommand("monsters")]
        private void cmdMonsters(BasePlayer player, string command, string[] args)
        {
            if (activeMonsters.Count == 0)
            {
                SendReply(player, "<color=yellow>No active monsters on the map.</color>");
                return;
            }
            
            SendReply(player, "<color=yellow>=== Active Monsters ===</color>");
            foreach (var monster in activeMonsters)
            {
                float distance = Vector3.Distance(player.transform.position, monster.SpawnPosition);
                SendReply(player, $"☠️ {monster.Config.Name} - {distance:F0}m away");
            }
        }
        
        [ConsoleCommand("monsterhunt.spawn")]
        private void cmdSpawnMonster(ConsoleSystem.Arg args)
        {
            if (args.Connection != null && !permission.UserHasPermission(args.Connection.UserId.ToString(), "monsterhunt.admin"))
            {
                args.ReplyWith("No permission");
                return;
            }
            
            SpawnRandomMonster();
            args.ReplyWith("Monster spawned manually");
        }
        
        [ConsoleCommand("monsterhunt.clear")]
        private void cmdClearMonsters(ConsoleSystem.Arg args)
        {
            if (args.Connection != null && !permission.UserHasPermission(args.Connection.UserId.ToString(), "monsterhunt.admin"))
            {
                args.ReplyWith("No permission");
                return;
            }
            
            DespawnAllMonsters();
            args.ReplyWith($"Cleared {activeMonsters.Count} monsters");
        }
        
        [ConsoleCommand("monsterhunt.status")]
        private void cmdStatus(ConsoleSystem.Arg args)
        {
            if (args.Connection != null && !permission.UserHasPermission(args.Connection.UserId.ToString(), "monsterhunt.admin"))
            {
                args.ReplyWith("No permission");
                return;
            }
            
            args.ReplyWith($"MonsterHunt: {activeMonsters.Count} active monsters, next spawn in ~{config.SpawnIntervalMinutes} minutes");
        }
        
        [ConsoleCommand("monsterhunt.reload")]
        private void cmdReload(ConsoleSystem.Arg args)
        {
            if (args.Connection != null && !permission.UserHasPermission(args.Connection.UserId.ToString(), "monsterhunt.admin"))
            {
                args.ReplyWith("No permission");
                return;
            }
            
            LoadConfig();
            args.ReplyWith("MonsterHunt config reloaded");
        }
        #endregion
    }
}

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