using System; using System.Linq; using System.Collections.Generic; using UnityEngine; using Oxide.Core.Plugins; using Newtonsoft.Json; using Oxide.Core; using Rust.Ai.Gen2; namespace Oxide.Plugins { [Info("Back To The Wild" , "Krungh Crow" , "2.2.3" , ResourceId = 157)] [Description("Animal Randomised health, damage and info")] public class BackToTheWild : RustPlugin { [PluginReference] private Plugin ChickenBow; private Dictionary animalSettingsMap; private bool Debug; private const string Admin_Perm = "backtothewild.admin"; private const string Prefix = "[BackToTheWild] : "; private const ulong Chaticon = 0; private void Init() { LoadConfig(); permission.RegisterPermission(Admin_Perm , this); } protected override void LoadDefaultConfig() { Puts("Creating default configuration file..."); var defaultSettings = GetDefaultAnimalSettings(); Config.WriteObject(new ConfigData { AnimalSettings = defaultSettings , Debug = true } , true); } private void LoadConfig() { try { var config = Config.ReadObject(); animalSettingsMap = config.AnimalSettings ?? GetDefaultAnimalSettings(); Debug = config.Debug; Puts("Loaded configuration successfully."); } catch (Exception ex) { Puts("Config file issue detected. Please delete file, or check syntax and fix."); Puts(ex.ToString()); return; } } protected override void LoadDefaultMessages() { lang.RegisterMessages(new Dictionary { ["InvalidInput"] = "Please enter a valid command!" , ["Info"] = "Animal related info :\n\n" , ["NoPermission"] = "You do not have permission to use that command!" , ["AnimalsInfo"] = "Animals with stats changing on spawn: {animals}" , ["NoAnimals"] = "No animals with stats changes on spawn." } , this); } private Dictionary GetDefaultAnimalSettings() { var settingsMap = new Dictionary(); foreach (var animalPrefab in GetDynamicAnimalTypes()) { settingsMap[animalPrefab] = new AnimalSettings { ChangeStatsOnSpawn = true , MinimumHealth = 100 , MaximumHealth = 500 , MinimumStrength = 10 , MaximumStrength = 30 , RunningSpeed = 1.0f , Alpha = new AlphaSettings { CanSpawnAsAlpha = true , Spawnrate = 10 , HealthMultiplier = 2.0f , StrengthMultiplier = 1.5f , SpeedMultiplier = 1.0f } , ChangePopulation = false , Population = 0 }; } return settingsMap; } private IEnumerable GetDynamicAnimalTypes() { var animalTypes = new HashSet(); animalTypes.Add("wolf2"); foreach (var animalPrefab in UnityEngine.Object.FindObjectsOfType()) { var prefabName = animalPrefab.ShortPrefabName.ToLower(); if (prefabName.Contains("shark") || prefabName.Contains("horse")) continue; animalTypes.Add(prefabName); } return animalTypes; } private void CheckAndAddNewAnimals() { var currentAnimalTypes = GetDynamicAnimalTypes(); bool newAnimalsAdded = false; foreach (var animalType in currentAnimalTypes) { if (!animalSettingsMap.ContainsKey(animalType)) { animalSettingsMap[animalType] = new AnimalSettings { ChangeStatsOnSpawn = true , MinimumHealth = 100 , MaximumHealth = 500 , MinimumStrength = 10 , MaximumStrength = 30 , RunningSpeed = 1.0f , Alpha = new AlphaSettings { CanSpawnAsAlpha = true , Spawnrate = 10 , HealthMultiplier = 2.0f , StrengthMultiplier = 1.5f , SpeedMultiplier = 1.0f } , ChangePopulation = false , Population = 0 }; newAnimalsAdded = true; Debugmsg($"Added new animal '{animalType}' with default settings."); } } if (newAnimalsAdded) { Config.WriteObject(new ConfigData { AnimalSettings = animalSettingsMap , Debug = Debug } , true); Puts("Configuration updated with new animals."); } else { Puts("No new animals found, configuration remains unchanged."); } } private class ConfigData { [JsonProperty("Debug")] public bool Debug { get; set; } public Dictionary AnimalSettings { get; set; } } private class AnimalSettings { [JsonProperty("Change stats on spawns")] public bool ChangeStatsOnSpawn { get; set; } [JsonProperty("Minimum Health")] public float MinimumHealth { get; set; } [JsonProperty("Maximum Health")] public float MaximumHealth { get; set; } [JsonProperty("Minimum Strength (Att dmg)")] public float MinimumStrength { get; set; } [JsonProperty("Maximum Strength (Att dmg)")] public float MaximumStrength { get; set; } [JsonProperty("Running Speed")] public float RunningSpeed { get; set; } public AlphaSettings Alpha { get; set; } [JsonProperty("Change Population")] public bool ChangePopulation { get; set; } [JsonProperty("Population")] public int Population { get; set; } } private class AlphaSettings { [JsonProperty("Can spawn as alpha")] public bool CanSpawnAsAlpha { get; set; } [JsonProperty("Spawnrate (0-100)")] public int Spawnrate { get; set; } [JsonProperty("Health Multiplier")] public float HealthMultiplier { get; set; } [JsonProperty("Strength Multiplier (Att dmg)")] public float StrengthMultiplier { get; set; } [JsonProperty("Speed Multiplier")] public float SpeedMultiplier { get; set; } } private void Debugmsg(string key) { if (Debug) { Puts($"[Debug] {key}"); } } private void OnEntitySpawned(BaseEntity entity) { // Check if entity is either a BaseAnimalNPC or BaseNPC2 (like Wolf2) if (entity is BaseAnimalNPC || entity is BaseNPC2) { var animalEntity = entity as BaseEntity; if (animalEntity == null) { Debugmsg("Spawned animal entity is null."); return; } string animalName = animalEntity.ShortPrefabName.ToLower(); // Check if the animal is a chicken using ChickenBow API if (animalName.Contains("chicken") && ChickenBow != null) { bool isChickenSpawned = ChickenBow.Call("IsSpawnedChicken" , animalEntity.net.ID); if (isChickenSpawned) { Debugmsg($"ChickenBow chicken detected: {animalName}"); return; } } else { Debugmsg($"Normal spawned animal detected: {animalName}"); } // Update stats based on configuration UpdateAnimalStats(animalEntity); } } private void UpdateAnimalStats(BaseEntity animalEntity) { if (animalEntity == null) return; string animalName = animalEntity.ShortPrefabName.ToLower(); if (animalSettingsMap.TryGetValue(animalName , out var settings)) { if (!settings.ChangeStatsOnSpawn) return; float minHealth = settings.MinimumHealth; float maxHealth = settings.MaximumHealth; float minDamage = settings.MinimumStrength; float maxDamage = settings.MaximumStrength; float speed = settings.RunningSpeed; if (settings.Alpha.CanSpawnAsAlpha && SpawnRate(settings.Alpha.Spawnrate)) { // Alpha stats multipliers var alphaHealthMultiplier = settings.Alpha.HealthMultiplier; var alphaDamageMultiplier = settings.Alpha.StrengthMultiplier; var alphaSpeedMultiplier = settings.Alpha.SpeedMultiplier; animalEntity.name = $"Alpha {animalName}"; // Apply the alpha multipliers minHealth *= alphaHealthMultiplier; maxHealth *= alphaHealthMultiplier; minDamage *= alphaDamageMultiplier; maxDamage *= alphaDamageMultiplier; speed *= alphaSpeedMultiplier; // Calculate random health and damage with alpha values float randomAlphaHealth = UnityEngine.Random.Range(minHealth , maxHealth); float randomAlphaDamage = UnityEngine.Random.Range(minDamage , maxDamage); // Initialize health and other stats if (animalEntity is BaseAnimalNPC baseAnimal) { baseAnimal.InitializeHealth(randomAlphaHealth , randomAlphaHealth); baseAnimal.AttackDamage = randomAlphaDamage; baseAnimal.Stats.Speed = speed; baseAnimal.Stats.TurnSpeed = speed; baseAnimal.NewAI = true; } else if (animalEntity is BaseNPC2 baseNpc) { baseNpc.InitializeHealth(randomAlphaHealth , randomAlphaHealth); //baseNpc.AttackDamage = randomAlphaDamage; //baseNpc.Stats.Speed = speed; //baseNpc.Stats.TurnSpeed = speed; } // Output message Puts($"{animalEntity.name} spawned as an Alpha with health {randomAlphaHealth}, damage ({randomAlphaDamage}), and speed {speed}"); return; } // Normal (non-alpha) animal spawn animalEntity.name = animalName; float randomHealth = UnityEngine.Random.Range(minHealth , maxHealth); float randomDamage = UnityEngine.Random.Range(minDamage , maxDamage); if (animalEntity is BaseAnimalNPC normalAnimal) { normalAnimal.InitializeHealth(randomHealth , randomHealth); normalAnimal.lifestate = BaseCombatEntity.LifeState.Alive; normalAnimal.AttackDamage = randomDamage; normalAnimal.Stats.Speed = speed; normalAnimal.Stats.TurnSpeed = speed; normalAnimal.NewAI = true; } else if (animalEntity is BaseNPC2 normalNpc) { normalNpc.InitializeHealth(randomHealth , randomHealth); //normalNpc.AttackDamage = randomDamage; //normalNpc.Stats.Speed = speed; //normalNpc.Stats.TurnSpeed = speed; } Debugmsg($"Updated {animalName} stats: Health ({randomHealth}), Damage ({randomDamage}), Speed ({speed})"); } else { Debugmsg($"No configuration found for animal: {animalName}"); } } private bool SpawnRate(int spawnRate) { return UnityEngine.Random.Range(0 , 100) < spawnRate; } private void OnServerInitialized() { CheckAndAddNewAnimals(); if (animalSettingsMap != null) { Debugmsg("Changing server population settings based on configuration..."); var animalCounts = new Dictionary(); foreach (var kvp in animalSettingsMap) { var animalType = kvp.Key.ToLower(); var settings = kvp.Value; if (settings.ChangePopulation) { int populationValue = settings.Population; string command = $"{animalType}.population"; Server.Command(command , populationValue); Debugmsg($"Set population for {animalType} to {populationValue}"); } else { Debugmsg($"Population change not enabled for {animalType}"); } animalCounts[animalType] = 0; } foreach (var entity in UnityEngine.Object.FindObjectsOfType()) { if (entity is BaseAnimalNPC animal) { var animalName = animal.ShortPrefabName.ToLower(); if (animalSettingsMap.TryGetValue(animalName , out var settings)) { if (settings.ChangeStatsOnSpawn) { UpdateAnimalStats(animal); if (animalCounts.ContainsKey(animalName)) { animalCounts[animalName]++; } else { animalCounts[animalName] = 1; } } } } else if (entity is BaseNPC2 npc) { var npcName = npc.ShortPrefabName.ToLower(); if (animalSettingsMap.TryGetValue(npcName , out var settings)) { if (settings.ChangeStatsOnSpawn) { UpdateAnimalStats(npc); if (animalCounts.ContainsKey(npcName)) { animalCounts[npcName]++; } else { animalCounts[npcName] = 1; } } } } } foreach (var kvp in animalCounts) { if (kvp.Value > 0) { string animalType = kvp.Key; string formattedMessage; if (animalType == "wolf") { formattedMessage = $"Total of {kvp.Value} wolves updated"; } else { formattedMessage = $"Total of {kvp.Value} {animalType}s updated"; } Puts(formattedMessage); } } } } #region Commands [ChatCommand("bttw")] private void cmdbttw(BasePlayer player , string command , string[] args) { if (!HasPerm(player , Admin_Perm)) { Player.Message(player , Prefix + msg("NoPermission" , player.UserIDString) , Chaticon); return; } if (args.Length == 0) { Player.Message(player , Prefix + msg("InvalidInput" , player.UserIDString) , Chaticon); return; } if (args[0].ToLower() == "animals") { string animalsInfo = GetAnimalsInfoMessage(); string message = msg("Info" , player.UserIDString) + "\n" + msg("AnimalsInfo").Replace("{animals}" , animalsInfo); Player.Message(player , Prefix + message , Chaticon); return; } Player.Message(player , Prefix + msg("InvalidInput" , player.UserIDString) , Chaticon); } private string GetAnimalsInfoMessage() { var message = string.Empty; foreach (var kvp in animalSettingsMap) { var animalName = kvp.Key; var settings = kvp.Value; if (settings.ChangeStatsOnSpawn) { message += $"{animalName}, "; } } // Remove the trailing comma and space if message is not empty if (message.EndsWith(", ")) { message = message.Substring(0 , message.Length - 2); } if (string.IsNullOrEmpty(message)) { message = msg("NoAnimals"); } return message; } private bool HasPerm(BasePlayer player , string perm) => permission.UserHasPermission(player.UserIDString , perm); private string msg(string key , string id = null) => lang.GetMessage(key , this , id); #endregion } }