C#:
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;
using UnityEngine;
namespace Oxide.Plugins
{
[Info("Enhanced Sprinkler Fire Extinguisher", "YourMom", "1.0.1")] // Bumped version for changes
[Description("Makes sprinklers extinguish all types of fires in their area")]
public class EnhancedSprinklerFireExtinguisher : RustPlugin
{
private List<BaseEntity> allSprinklers = new List<BaseEntity>();
private List<BaseEntity> fireCheckList = new List<BaseEntity>();
#region Configuration
private ConfigData configData = new ConfigData();
private class ConfigData
{
[JsonProperty(PropertyName = "Base Sprinkler Range")]
public float BaseSprinklerRange { get; set; } = 0.6f;
[JsonProperty(PropertyName = "Use Dynamic Range Based On Water Pressure")]
public bool UseDynamicRange { get; set; } = true;
[JsonProperty(PropertyName = "Max Range With Full Water")]
public float MaxRangeWithFullWater { get; set; } = 0.8f;
[JsonProperty(PropertyName = "Min Range With Low Water")]
public float MinRangeWithLowWater { get; set; } = 0.3f;
[JsonProperty(PropertyName = "Check Interval (seconds)")]
public float CheckInterval { get; set; } = 1f;
[JsonProperty(PropertyName = "Extinguish Campfires")]
public bool ExtinguishCampfires { get; set; } = true;
[JsonProperty(PropertyName = "Extinguish Furnaces")]
public bool ExtinguishFurnaces { get; set; } = true;
[JsonProperty(PropertyName = "Extinguish Lanterns")]
public bool ExtinguishLanterns { get; set; } = true;
[JsonProperty(PropertyName = "Extinguish Fire Barrels")]
public bool ExtinguishFireBarrels { get; set; } = true;
[JsonProperty(PropertyName = "Extinguish Molotov Fires")]
public bool ExtinguishMolotovFires { get; set; } = true;
[JsonProperty(PropertyName = "Extinguish Incendiary Rocket Fires")]
public bool ExtinguishIncendiaryFires { get; set; } = true;
[JsonProperty(PropertyName = "Show Debug Messages")]
public bool ShowDebugMessages { get; set; } = true;
[JsonProperty(PropertyName = "Show Visual Effects")]
public bool ShowVisualEffects { get; set; } = true;
[JsonProperty(PropertyName = "Require Water In Sprinkler")]
public bool RequireWater { get; set; } = false;
}
protected override void LoadConfig()
{
base.LoadConfig();
try
{
configData = Config.ReadObject<ConfigData>();
if (configData == null) LoadDefaultConfig();
}
catch
{
PrintError("Configuration file is corrupt, check your config file at https://jsonlint.com/!");
LoadDefaultConfig();
return;
}
SaveConfig();
}
protected override void LoadDefaultConfig() => configData = new ConfigData();
protected override void SaveConfig() => Config.WriteObject(configData);
#endregion
#region Hooks
void OnServerInitialized()
{
Puts("Enhanced Sprinkler Fire Extinguisher loaded!");
PopulateSprinklerList();
timer.Every(configData.CheckInterval, () => CheckAllSprinklers());
}
void OnEntitySpawned(BaseEntity entity)
{
if (entity != null && IsSprinkler(entity) && !allSprinklers.Contains(entity))
{
allSprinklers.Add(entity);
if (configData.ShowDebugMessages) Puts($"Added new sprinkler: {entity.ShortPrefabName}");
}
}
void OnEntityDeath(BaseEntity entity)
{
if (entity != null && IsSprinkler(entity))
{
allSprinklers.Remove(entity);
if (configData.ShowDebugMessages) Puts($"Removed destroyed sprinkler: {entity.ShortPrefabName}");
}
}
#endregion
#region Core Methods
void PopulateSprinklerList()
{
foreach (var entity in UnityEngine.Object.FindObjectsOfType<BaseEntity>())
{
if (IsSprinkler(entity))
{
allSprinklers.Add(entity);
}
}
Puts($"Initial population complete. Found {allSprinklers.Count} sprinklers.");
}
void CheckAllSprinklers()
{
var sprinklerCount = allSprinklers.Count;
var extinguishedCount = 0;
for (int i = allSprinklers.Count - 1; i >= 0; i--)
{
var entity = allSprinklers[i];
if (entity == null || entity.IsDestroyed)
{
allSprinklers.RemoveAt(i);
continue;
}
if (IsSprinklerActive(entity))
{
int fires = ExtinguishNearbyFires(entity);
extinguishedCount += fires;
}
}
if (configData.ShowDebugMessages && extinguishedCount > 0)
{
Puts($"Found {sprinklerCount} sprinklers, extinguished {extinguishedCount} fires");
}
}
bool IsSprinkler(BaseEntity entity)
{
if (entity == null) return false;
string prefab = entity.ShortPrefabName?.ToLower() ?? "";
return prefab.Contains("sprinkler") || prefab.Contains("water.catcher");
}
float GetSprinklerRange(BaseEntity sprinkler)
{
if (!configData.UseDynamicRange)
{
return configData.BaseSprinklerRange;
}
var storage = sprinkler.GetComponent<StorageContainer>();
if (storage?.inventory != null)
{
var waterItem = storage.inventory.FindItemByItemID(-1779180711); D
if (waterItem != null)
{
/
float waterPercentage = Mathf.Clamp01(waterItem.amount / 500f);
float dynamicRange = Mathf.Lerp(configData.MinRangeWithLowWater, configData.MaxRangeWithFullWater, waterPercentage);
if (configData.ShowDebugMessages && waterPercentage < 0.3f)
{
Puts($"Sprinkler at {sprinkler.transform.position} has low water ({waterItem.amount}), reduced range to {dynamicRange:F1}m");
}
return dynamicRange;
}
}
return configData.MinRangeWithLowWater;
}
bool IsSprinklerActive(BaseEntity sprinkler)
{
if (sprinkler == null || sprinkler.IsDestroyed) return false;
if (!sprinkler.HasFlag(BaseEntity.Flags.On)) return false;
if (configData.RequireWater && !HasWater(sprinkler)) return false;
return true;
}
bool HasWater(BaseEntity sprinkler)
{
if (!configData.RequireWater) return true;
var storage = sprinkler.GetComponent<StorageContainer>();
if (storage?.inventory != null)
{
return storage.inventory.itemList.Count > 0;
}
return true;
}
int ExtinguishNearbyFires(BaseEntity sprinkler)
{
float sprinklerRange = GetSprinklerRange(sprinkler);
fireCheckList.Clear();
Vis.Entities(sprinkler.transform.position, sprinklerRange, fireCheckList);
int extinguished = 0;
foreach (var entity in fireCheckList)
{
if (entity == null || entity.IsDestroyed || entity == sprinkler) continue;
if (ExtinguishFire(entity, sprinkler))
{
extinguished++;
}
}
return extinguished;
}
bool ExtinguishFire(BaseEntity entity, BaseEntity sprinkler)
{
string prefab = entity.ShortPrefabName?.ToLower() ?? "";
bool wasExtinguished = false;
string fireType = "";
if (configData.ExtinguishCampfires && prefab.Contains("campfire"))
{
var oven = entity.GetComponent<BaseOven>();
if (oven != null && oven.IsOn())
{
oven.StopCooking();
wasExtinguished = true;
fireType = "campfire";
}
}
else if (configData.ExtinguishFurnaces && (prefab.Contains("furnace") || prefab.Contains("refinery") || prefab.Contains("smelter")))
{
var oven = entity.GetComponent<BaseOven>();
if (oven != null && oven.IsOn())
{
oven.StopCooking();
wasExtinguished = true;
fireType = "furnace";
}
}
else if (configData.ExtinguishFireBarrels && (prefab.Contains("firebarrel") || prefab.Contains("fire_barrel")))
{
var oven = entity.GetComponent<BaseOven>();
if (oven != null && oven.IsOn())
{
oven.StopCooking();
wasExtinguished = true;
fireType = "fire barrel";
}
}
else if (configData.ExtinguishLanterns && (prefab.Contains("lantern") || prefab.Contains("torch") || prefab.Contains("candle")))
{
if (entity.HasFlag(BaseEntity.Flags.On))
{
entity.SetFlag(BaseEntity.Flags.On, false);
wasExtinguished = true;
fireType = "lantern/torch";
}
}
else if (configData.ExtinguishMolotovFires && (prefab.Contains("napalm") || prefab.Contains("fireball") || prefab.Contains("fire_") || entity.name.ToLower().Contains("fire")))
{
if (entity.HasFlag(BaseEntity.Flags.On))
{
entity.SetFlag(BaseEntity.Flags.On, false);
wasExtinguished = true;
fireType = "molotov fire";
}
else
{
entity.Kill();
wasExtinguished = true;
fireType = "fire effect";
}
}
else if (configData.ExtinguishIncendiaryFires && (prefab.Contains("incendiary") || prefab.Contains("rocket_fire") || prefab.Contains("explosion_fire")))
{
if (entity.HasFlag(BaseEntity.Flags.On))
{
entity.SetFlag(BaseEntity.Flags.On, false);
wasExtinguished = true;
fireType = "incendiary fire";
}
else
{
entity.Kill();
wasExtinguished = true;
fireType = "incendiary effect";
}
}
else if (prefab.Contains("flame") || prefab.Contains("fire"))
{
if (entity.HasFlag(BaseEntity.Flags.On))
{
entity.SetFlag(BaseEntity.Flags.On, false);
wasExtinguished = true;
fireType = "flame entity";
}
}
if (wasExtinguished)
{
if (configData.ShowDebugMessages)
{
Puts($"Sprinkler extinguished {fireType} ({prefab}) at distance {Vector3.Distance(sprinkler.transform.position, entity.transform.position):F1}m");
}
Effect.server.Run("assets/bundled/prefabs/fx/extinguish_small.prefab", entity.transform.position);
return true;
}
return false;
}
#endregion
#region Chat Commands
[ChatCommand("sprinkler")]
void SprinklerCommand(BasePlayer player, string command, string[] args)
{
if (!player.IsAdmin)
{
player.ChatMessage("You don't have permission to use this command.");
return;
}
if (args.Length == 0)
{
player.ChatMessage("Sprinkler Commands:");
player.ChatMessage("/sprinkler info - Show sprinkler information");
player.ChatMessage("/sprinkler test - Test fire extinguishing around you");
player.ChatMessage("/sprinkler reload - Reload configuration");
return;
}
switch (args[0].ToLower())
{
case "info":
ShowSprinklerInfo(player);
break;
case "test":
TestExtinguishing(player);
break;
case "reload":
LoadConfig();
PopulateSprinklerList();
player.ChatMessage("Configuration reloaded and sprinkler list re-populated!");
break;
default:
player.ChatMessage("Unknown command. Use /sprinkler for help.");
break;
}
}
void ShowSprinklerInfo(BasePlayer player)
{
int sprinklerCount = allSprinklers.Count;
int activeSprinklerCount = 0;
var allEntities = UnityEngine.Object.FindObjectsOfType<BaseEntity>();
int fireCount = 0;
foreach (var entity in allEntities)
{
if (entity == null || entity.IsDestroyed) continue;
if (IsSprinkler(entity) && allSprinklers.Contains(entity)) // Ensure it's a tracked sprinkler
{
if (IsSprinklerActive(entity))
{
activeSprinklerCount++;
}
}
else if (IsFireEntity(entity))
{
fireCount++;
}
}
player.ChatMessage($"=== Sprinkler Info ===");
player.ChatMessage($"Total sprinklers: {sprinklerCount}");
player.ChatMessage($"Active sprinklers: {activeSprinklerCount}");
player.ChatMessage($"Active fires (Server Scan): {fireCount}");
player.ChatMessage($"Base range: {configData.BaseSprinklerRange}m");
player.ChatMessage($"Dynamic range: {configData.UseDynamicRange}");
if (configData.UseDynamicRange)
{
player.ChatMessage($"Range: {configData.MinRangeWithLowWater}m - {configData.MaxRangeWithFullWater}m");
}
player.ChatMessage($"Check interval: {configData.CheckInterval}s");
player.ChatMessage($"Debug messages: {configData.ShowDebugMessages}");
}
void TestExtinguishing(BasePlayer player)
{
var nearbyEntities = new List<BaseEntity>();
Vis.Entities(player.transform.position, 20f, nearbyEntities);
int sprinklers = 0;
int activeSprinklers = 0;
int fires = 0;
foreach (var entity in nearbyEntities)
{
if (entity == null || entity.IsDestroyed) continue;
if (IsSprinkler(entity))
{
sprinklers++;
bool isActive = IsSprinklerActive(entity);
if (isActive) activeSprinklers++;
float range = GetSprinklerRange(entity);
var storage = entity.GetComponent<StorageContainer>();
int waterAmount = 0;
if (storage?.inventory != null)
{
var waterItem = storage.inventory.FindItemByItemID(-1779180711);
waterAmount = waterItem?.amount ?? 0;
}
player.ChatMessage($"Sprinkler: {entity.ShortPrefabName} (Active: {isActive}, Range: {range:F1}m, Water: {waterAmount}) at {entity.transform.position}");
}
else if (IsFireEntity(entity))
{
fires++;
var oven = entity.GetComponent<BaseOven>();
bool isOn = oven?.IsOn() ?? entity.HasFlag(BaseEntity.Flags.On);
player.ChatMessage($"Found fire: {entity.ShortPrefabName} (On: {isOn}) at {entity.transform.position}");
}
}
player.ChatMessage($"Found {sprinklers} sprinklers ({activeSprinklers} active) and {fires} fire entities within 20m");
if (sprinklers > 0 && activeSprinklers == 0)
{
player.ChatMessage("Sprinklers found but none are active! Make sure they are turned on idiot.");
}
}
bool IsFireEntity(BaseEntity entity)
{
string prefab = entity.ShortPrefabName?.ToLower() ?? "";
string name = entity.name?.ToLower() ?? "";
return prefab.Contains("campfire") || prefab.Contains("furnace") || prefab.Contains("firebarrel") ||
prefab.Contains("lantern") || prefab.Contains("torch") || prefab.Contains("flame") ||
prefab.Contains("fire") || prefab.Contains("napalm") || prefab.Contains("fireball") ||
prefab.Contains("incendiary") || prefab.Contains("rocket_fire") || prefab.Contains("explosion_fire") ||
name.Contains("fire");
}
#endregion
}
}