C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using Oxide.Core.Libraries.Covalence;
using System;
using UnityEngine;
using System.Collections.Generic;
using Newtonsoft.Json;
using static ConsoleSystem;
namespace Oxide.Plugins
{
[Info("Deforestation", "Lincoln & redBDGR", "1.0.5")]
[Description("Make trees fall over like a boss.")]
class Deforestation : RustPlugin
{
private const string permUse = "deforestation.use";
private const string permRadiusBypass = "deforestation.radiusbypass";
private float radius;
#region PluginConfig
//Creating a config file
private static PluginConfig config;
private class PluginConfig
{
[JsonProperty(PropertyName = "Max Radius: ")] public int maxRadius { get; set; }
[JsonProperty(PropertyName = "Number Of Tree Spawns: ")] public int numberOfTreesToSpawn { get; set; }
public static PluginConfig DefaultConfig() => new PluginConfig()
{
maxRadius = 25,
numberOfTreesToSpawn = 15
};
}
protected override void LoadDefaultConfig()
{
PrintWarning("New configuration file created.");
config = PluginConfig.DefaultConfig();
}
protected override void LoadConfig()
{
base.LoadConfig();
config = Config.ReadObject<PluginConfig>();
SaveConfig();
}
protected override void SaveConfig()
{
Config.WriteObject(config);
}
#endregion
#region Helpers
bool ValidationChecks(BasePlayer player, string[] args)
{
if (!permission.UserHasPermission(player.UserIDString, permUse))
{
ChatMessage(player, "NoPerm");
return true;
}
if (args.Length != 1)
{
ChatMessage(player, "Syntax");
return true;
}
try
{
radius = Convert.ToSingle(args[0]);
}
catch
{
ChatMessage(player, "InvalidArg");
return true;
}
if (!permission.UserHasPermission(player.UserIDString, permRadiusBypass))
{
if (radius > config.maxRadius || radius <= 0)
{
ChatMessage(player, "Radius", config.maxRadius);
return true;
}
}
return false;
}
#endregion
#region Permissions
private void Init()
{
permission.RegisterPermission(permUse, this);
permission.RegisterPermission(permRadiusBypass, this);
}
#endregion
#region Commands
[ChatCommand("counttrees")]
private void CountTreesCMD(BasePlayer player, string command, string[] args)
{
if (ValidationChecks(player, args)) return;
int treeCount = 0;
RaycastHit[] hits = UnityEngine.Physics.SphereCastAll(player.transform.position, radius, Vector3.up);
foreach (RaycastHit hit in hits)
{
TreeEntity tree = hit.GetEntity()?.GetComponent<TreeEntity>();
if (tree) treeCount++;
}
ChatMessage(player, "TreeCount", treeCount, radius);
}
[ChatCommand("killtree")]
private void TreeDeforestationCMD(BasePlayer player, string command, string[] args)
{
if (ValidationChecks(player, args)) return;
RaycastHit[] hits = UnityEngine.Physics.SphereCastAll(player.transform.position, radius, Vector3.up);
foreach (RaycastHit hit in hits)
{
TreeEntity tree = hit.GetEntity()?.GetComponent<TreeEntity>();
if (!tree) continue;
tree.OnDied(new HitInfo() { PointStart = player.transform.position, PointEnd = tree.transform.position });
}
}
[ChatCommand("killbush")]
private void BushDeforestationCMD(BasePlayer player, string command, string[] args)
{
if (ValidationChecks(player, args)) return;
RaycastHit[] hits = UnityEngine.Physics.SphereCastAll(player.transform.position, radius, Vector3.up);
foreach (RaycastHit hit in hits)
{
BushEntity bush = hit.GetEntity()?.GetComponent<BushEntity>();
if (bush) bush.Kill();
}
}
[ChatCommand("growtree")]
private void TreeGrowCMD(BasePlayer player, string command, string[] args)
{
if (ValidationChecks(player, args)) return;
float radius;
if (!float.TryParse(args[0], out radius))
{
player.ChatMessage("Invalid radius value.");
return;
}
int numberOfTrees = config.numberOfTreesToSpawn;
List<Vector3> treePositions = new List<Vector3>();
for (int i = 0; i < numberOfTrees; i++)
{
Vector3 randomPosition = GetRandomPositionWithinRadius(player.transform.position, radius);
float terrainHeight = TerrainMeta.HeightMap.GetHeight(randomPosition);
randomPosition.y = terrainHeight + 100f; // Cast the ray from a higher position
RaycastHit[] hits = UnityEngine.Physics.RaycastAll(randomPosition, Vector3.down, 200f);
bool suitablePosition = false;
foreach (RaycastHit hit in hits)
{
if (hit.collider.gameObject.layer == LayerMask.NameToLayer("Terrain"))
{
//get terrain type at position
TerrainBiome.Enum biome = (TerrainBiome.Enum)TerrainMeta.BiomeMap.GetBiome(randomPosition, 3);
player.ChatMessage(biome.ToString());
randomPosition.y = hit.point.y;
suitablePosition = true;
break;
}
}
if (suitablePosition)
{
treePositions.Add(randomPosition);
}
else
{
i--;
}
}
foreach (Vector3 position in treePositions)
{
SpawnTree(position);
}
}
private Vector3 GetRandomPositionWithinRadius(Vector3 center, float radius)
{
float randomAngle = UnityEngine.Random.Range(0f, 360f);
float randomDistance = UnityEngine.Random.Range(0f, radius);
Vector3 direction = new Vector3(Mathf.Sin(randomAngle), 0f, Mathf.Cos(randomAngle));
Vector3 position = center + direction * randomDistance;
return position;
}
private void SpawnTree(Vector3 position)
{
string treePrefab = "assets/bundled/prefabs/autospawn/resource/v3_tundra_forestside/pine_b.prefab";
TreeEntity tree = GameManager.server.CreateEntity(treePrefab, position, new Quaternion(), true) as TreeEntity;
tree.Spawn();
}
#endregion
#region Localization
private void ReplyToPlayer(IPlayer player, string messageName, params object[] args) =>
player.Reply(string.Format(GetMessage(player, messageName), args));
private void ChatMessage(BasePlayer player, string messageName, params object[] args) =>
player.ChatMessage(string.Format(GetMessage(player.IPlayer, messageName), args));
private string GetMessage(IPlayer player, string messageName, params object[] args) =>
GetMessage(player.Id, messageName, args);
private string GetMessage(string playerId, string messageName, params object[] args)
{
var message = lang.GetMessage(messageName, this, playerId);
return args.Length > 0 ? string.Format(message, args) : message;
}
protected override void LoadDefaultMessages()
{
lang.RegisterMessages(new Dictionary<string, string>
{
["TreeCount"] = "<color=#ffc34d>Deforestation</color>: There are {0} trees within a {1} meter radius of you.",
["Radius"] = "<color=#ffc34d>Deforestation</color>: Invalid radius.Please choose a radius between 1 and {0}",
["NoPerm"] = "<color=#ffc34d>Deforestation</color>: You don't have permission to use that.",
["Syntax"] = "<color=#ffc34d>Deforestation</color>: Invalid syntax! Type /killtree or /killbush <radius>",
["InvalidArg"] = "<color=#ffc34d>Deforestation</color>: Invalid argument! Make sure the radius is a whole number!",
}, this, "en");
}
#endregion
private void Unload()
{
config = null;
}
}
}