C#:
using Oxide.Core.Plugins;
using Oxide.Core;
using Oxide.Core.Libraries.Covalence;
using UnityEngine;
using System.Collections.Generic;
namespace Oxide.Plugins
{
[Info("Random Scarecrow Spawner", "Chernarust", "1.1.5")]
[Description("Spawns scarecrows around players with a configurable random chance and allows one-hit headshot kills.")]
public class RandomScarecrowSpawner : CovalencePlugin
{
private const string scarecrowPrefab = "assets/prefabs/npc/scarecrow/scarecrow.prefab";
private const string permissionName = "randomscarecrowspawner.use";
private PluginConfig config;
private Dictionary<string, int> playerScarecrowCount = new Dictionary<string, int>();
private Dictionary<NetworkableId, string> scarecrowToPlayerMap = new Dictionary<NetworkableId, string>();
private class PluginConfig
{
public float SpawnChance { get; set; }
public float CheckInterval { get; set; }
public float SpawnDistance { get; set; }
public int MaxScarecrowsPerPlayer { get; set; }
public bool OneHitHeadshotKill { get; set; }
public static PluginConfig DefaultConfig()
{
return new PluginConfig
{
SpawnChance = 0.1f,
CheckInterval = 60.0f,
SpawnDistance = 20.0f,
MaxScarecrowsPerPlayer = 3,
OneHitHeadshotKill = true
};
}
}
protected override void LoadDefaultConfig() => config = PluginConfig.DefaultConfig();
private void Init()
{
permission.RegisterPermission(permissionName, this);
}
private void OnServerInitialized()
{
LoadConfig();
timer.Every(config.CheckInterval, () => SpawnScarecrowsForPlayers());
}
private void SpawnScarecrowsForPlayers()
{
foreach (var player in players.Connected)
{
if (!player.HasPermission(permissionName)) continue;
BasePlayer basePlayer = player.Object as BasePlayer;
if (!basePlayer.IsAlive() || basePlayer.IsSleeping() || basePlayer.InSafeZone() || IsInToolCupboardRange(basePlayer))
continue;
string playerId = player.Id;
if (!playerScarecrowCount.ContainsKey(playerId))
playerScarecrowCount[playerId] = 0;
if (playerScarecrowCount[playerId] >= config.MaxScarecrowsPerPlayer)
continue;
if (UnityEngine.Random.value < config.SpawnChance)
{
Vector3 randomDirection = UnityEngine.Random.insideUnitSphere * config.SpawnDistance;
randomDirection.y = 0;
Vector3 spawnPosition = basePlayer.transform.position + randomDirection;
spawnPosition.y = TerrainMeta.HeightMap.GetHeight(spawnPosition);
SpawnScarecrow(spawnPosition, playerId);
}
}
}
private void SpawnScarecrow(Vector3 position, string playerId)
{
var scarecrow = GameManager.server.CreateEntity(scarecrowPrefab, position, Quaternion.identity);
if (scarecrow != null)
{
scarecrow.Spawn();
playerScarecrowCount[playerId]++;
scarecrowToPlayerMap[scarecrow.net.ID] = playerId;
Puts($"Spawned a scarecrow at {position} for player {playerId}");
}
}
private bool IsInToolCupboardRange(BasePlayer player)
{
var buildingPrivileges = player.GetBuildingPrivilege();
return buildingPrivileges != null && buildingPrivileges.IsAuthed(player);
}
[HookMethod("OnEntityTakeDamage")]
private void OnEntityTakeDamage(BaseCombatEntity entity, HitInfo hitInfo)
{
if (entity?.ShortPrefabName != "scarecrow" || hitInfo == null || !config.OneHitHeadshotKill)
return;
if (hitInfo.isHeadshot)
{
entity.Die(); // Kill the entity instantly on a headshot
}
}
private void LoadConfig()
{
config = Config.ReadObject<PluginConfig>();
if (config?.SpawnChance == null)
{
LoadDefaultConfig();
}
SaveConfig();
}
protected override void SaveConfig() => Config.WriteObject(config);
[HookMethod("OnEntityDeath")]
private void OnEntityDeath(BaseEntity entity)
{
if (entity?.ShortPrefabName != "scarecrow") return;
if (scarecrowToPlayerMap.TryGetValue(entity.net.ID, out string playerId))
{
playerScarecrowCount[playerId]--;
scarecrowToPlayerMap.Remove(entity.net.ID);
}
}
}
}