C#:
using Newtonsoft.Json;
using Oxide.Core;
using System.Collections.Generic;
using UnityEngine;
namespace Oxide.Plugins
{
[Info("SpawnJunk", "OxideBro / RustPlugin.ru", "0.0.1")]
class SpawnJunk : RustPlugin
{
private PluginConfig config;
protected override void LoadDefaultConfig()
{
PrintWarning("Благодарим за скачивание плагина на сайте RustPlugin.ru. Если вы передадите этот плагин сторонним лицам знайте - это лишает вас гарантированных обновлений!");
config = PluginConfig.DefaultConfig();
}
protected override void LoadConfig()
{
base.LoadConfig();
config = Config.ReadObject<PluginConfig>();
if (config.PluginVersion < Version)
UpdateConfigValues();
Config.WriteObject(config, true);
}
private void UpdateConfigValues()
{
PluginConfig baseConfig = PluginConfig.DefaultConfig();
if (config.PluginVersion < new VersionNumber(0, 1, 0))
{
PrintWarning("Config update detected! Updating config values...");
PrintWarning("Config update completed!");
}
config.PluginVersion = Version;
}
protected override void SaveConfig()
{
Config.WriteObject(config);
}
class PluginConfig
{
[JsonProperty("Максимальное количество мусорок на карте")]
public int MaxCount = 200;
[JsonProperty("Радиус спавна от дороги Min")]
public int MinSpawn = 15;
[JsonProperty("Радиус спавна от дороги Max")]
public int MaxSpawn = 25;
[JsonProperty("Время респавна мусорки после удаления в секундах")]
public int RespawnTime = 120;
[JsonProperty("Список префабов мосурок")]
public List<string> JunkShortnamesList = new List<string>();
[JsonProperty("Версия конфигурации")]
public VersionNumber PluginVersion = new VersionNumber();
public static PluginConfig DefaultConfig()
{
return new PluginConfig()
{
PluginVersion = new VersionNumber(),
JunkShortnamesList = new List<string>()
{
"assets/prefabs/misc/junkpile/junkpile_a.prefab",
"assets/prefabs/misc/junkpile/junkpile_b.prefab",
"assets/prefabs/misc/junkpile/junkpile_c.prefab",
"assets/prefabs/misc/junkpile/junkpile_d.prefab",
"assets/prefabs/misc/junkpile/junkpile_f.prefab",
"assets/prefabs/misc/junkpile/junkpile_e.prefab",
"assets/prefabs/misc/junkpile/junkpile_g.prefab",
"assets/prefabs/misc/junkpile/junkpile_i.prefab",
"assets/prefabs/misc/junkpile/junkpile_j.prefab"
},
MinSpawn = 15,
MaxSpawn = 25,
MaxCount = 200,
RespawnTime = 120
};
}
}
int terrainMask = LayerMask.GetMask("Terrain");
List<Vector3> Positions = new List<Vector3>();
private static int blockedLayer = LayerMask.GetMask("Default");
public Dictionary<JunkPile, Vector3> JunkList = new Dictionary<JunkPile, Vector3>();
static float GetGroundPosition(Vector3 pos)
{
float y = TerrainMeta.HeightMap.GetHeight(pos);
RaycastHit hit;
if (Physics.Raycast(new Vector3(pos.x, pos.y + 20f, pos.z), Vector3.down, out hit, Mathf.Infinity, LayerMask.GetMask(new[]
{
"Terrain", "World", "Default", "Construction", "Deployed"
}
)) && !hit.collider.name.Contains("rock_cliff")) return Mathf.Max(hit.point.y, y);
return y;
}
static Vector3 RandomCircle(Vector3 center, float radius = 2)
{
float ang = UnityEngine.Random.value * 360;
Vector3 pos = Vector3.zero;
pos.x = center.x + radius * Mathf.Sin(ang * Mathf.Deg2Rad);
pos.z = center.z + radius * Mathf.Cos(ang * Mathf.Deg2Rad);
pos.y = GetGroundPosition(pos);
return pos;
}
void OnServerInitialized()
{
Subscribe("OnEntityKill");
var road = TerrainMeta.Path.Roads;
int count1 = 0;
foreach (var generate in road)
{
foreach (var pos in generate.Path.Points)
{
var pos1 = pos;
for (int i = 0; i < 4; i++)
{
var pos2 = new Vector3();
switch (i)
{
case 0:
pos2 = pos1 + new Vector3(-2, 0, UnityEngine.Random.Range(config.MinSpawn, config.MaxSpawn));
break;
case 1:
pos2 = pos1 + new Vector3(UnityEngine.Random.Range(config.MinSpawn, config.MaxSpawn), 0, 2);
break;
case 2:
pos2 = pos1 + new Vector3(-UnityEngine.Random.Range(config.MinSpawn, config.MaxSpawn), 0, 2);
break;
case 3:
pos2 = pos1 + new Vector3(-2, 0, -UnityEngine.Random.Range(config.MinSpawn, config.MaxSpawn));
break;
}
pos2.y = GetGroundPosition(pos2);
if ((pos2.y - pos.y) > 2 || (pos2.y - pos.y) < -2)
{
continue;
}
var count = Physics.OverlapSphereNonAlloc(pos2, 15, Vis.colBuffer, blockedLayer);
if (count > 0)
break;
RaycastHit hit;
if (Physics.Raycast(pos2 + Vector3.up, Vector3.down, out hit, terrainMask))
{
if (hit.GetCollider().name.Contains("Terrain"))
{
Positions.Add(pos2);
}
else
{
pos2.x = pos2.x + 3f;
if (Physics.Raycast(pos2 + Vector3.up, Vector3.down, out hit, terrainMask))
{
if (hit.GetCollider().name.Contains("Terrain"))
{
Positions.Add(pos2);
}
}
}
}
count1++;
}
}
}
Puts($"Generated {Positions.Count} position on spawn");
SpawnableJunk();
}
void SpawnableJunk()
{
int Spawned = 0;
for (int i = 0; i < config.MaxCount; i++)
{
if (Positions.Count == 0) break;
var en = Positions.GetRandom();
if (en == Vector3.zero)
{
i--;
continue;
}
var count = Physics.OverlapSphereNonAlloc(en, 15, Vis.colBuffer, blockedLayer);
if (count > 0)
{
i--;
continue;
}
var pos = en;
var entity = GameManager.server.CreateEntity(config.JunkShortnamesList.GetRandom(), pos + new Vector3(0, 0.2f, 0)) as JunkPile;
if (entity == null)
{
i--;
entity.Kill();
continue;
}
entity.enableSaving = false;
entity.Spawn();
JunkList.Add(entity, pos);
Positions.Remove(en);
Spawned++;
}
Puts("{0} junks bins created successfully", Spawned);
}
void Unload()
{
Unsubscribe("OnEntityKill");
foreach (var ore in JunkList)
{
if (ore.Key != null && !ore.Key.IsDestroyed)
{
ore.Key.Kill();
var count = Physics.OverlapSphereNonAlloc(ore.Value, 10, Vis.colBuffer, blockedLayer);
for (int i = 0; i < count; i++)
{
var entity = Vis.colBuffer[i].ToBaseEntity();
if (entity == null) continue;
entity.Kill();
}
}
}
}
void OnEntityKill(JunkPile entity)
{
if (JunkList.ContainsKey(entity))
{
var pos = JunkList[entity];
timer.Once(config.RespawnTime, () =>
{
var newEntity = GameManager.server.CreateEntity(config.JunkShortnamesList.GetRandom(), pos) as JunkPile;
if (newEntity == null)
{
newEntity.Kill();
return;
}
newEntity.enableSaving = false;
newEntity.Spawn();
JunkList.Add(entity, pos);
});
JunkList.Remove(entity);
}
}
[ConsoleCommand("spawnjunk_list")]
void cmdListSpawnOres(ConsoleSystem.Arg args)
{
if (args.Connection != null) return;
PrintWarning($"{JunkList.Count} junk to map");
}
}
}