C#:
/*
* <----- End-User License Agreement ----->
* Copyright © 2025 Iftebinjan
* Devoloper: Iftebinjan (Discord: https://discord.gg/HFaGs8YwsH)
*
* You may not copy, modify, merge, publish, distribute, sublicense, or sell copies of This Software without the Developer’s consent
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
using Facepunch;
using Newtonsoft.Json;
using Oxide.Core;
using Oxide.Core.Plugins;
using Oxide.Game.Rust.Cui;
using Oxide.Plugins;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
namespace Oxide.Plugins
{
[Info("TrapsLimit", "ifte", "1.0.0")]
[Description("Limit traps based on radius")]
public class TrapsLimit : RustPlugin
{
/*------------------------------------
*
* TrapsLimit by ifte
* Support: https://discord.gg/cCWadjcapr
* Fiverr: https://www.fiverr.com/s/e2pkYY
* Eror404 not found
*
-------------------------------------*/
#region Fields
private readonly Dictionary<string, string> ShortPrefabNameToItemShortName = new Dictionary<string, string>();
private readonly string LockDenidedPrefab = "assets/prefabs/locks/keypad/effects/lock.code.denied.prefab";
#endregion
#region Config
private Configuration config;
private class Configuration
{
[JsonProperty("Traps List")]
public Dictionary<string, TrapsOptions> TrapsList { get; set; }
public VersionNumber Version { get; set; }
}
private class TrapsOptions
{
[JsonProperty("Trap limit")]
public int trapLimit { get; set; }
[JsonProperty("Trap limit radius")]
public float trapLimitRadius { get; set; }
}
// ItemManager.itemList.Where(x => x.category == ItemCategory.Traps).ToDictionary((x) => x.shortname, (x) => trapsOptions), - AutoTurret missing lmao fp
private Configuration GetBaseConfig()
{
TrapsOptions trapsOptions = new TrapsOptions()
{
trapLimit = 5,
trapLimitRadius = 40f
};
return new Configuration()
{
TrapsList = new Dictionary<string, TrapsOptions>()
{
{ "trap.bear", new TrapsOptions() { trapLimit = 10, trapLimitRadius = 40f } },
{ "spikes.floor", new TrapsOptions() { trapLimit = 10, trapLimitRadius = 40f } },
{ "trap.landmine", new TrapsOptions() { trapLimit = 10, trapLimitRadius = 40f } },
{ "tincan.alarm", new TrapsOptions() { trapLimit = 10, trapLimitRadius = 40f } },
{ "guntrap", new TrapsOptions() { trapLimit = 10, trapLimitRadius = 40f } },
{ "flameturret", new TrapsOptions() { trapLimit = 10, trapLimitRadius = 40f } },
{ "samsite", new TrapsOptions() { trapLimit = 4, trapLimitRadius = 40f } },
{ "autoturret", new TrapsOptions() { trapLimit = 12, trapLimitRadius = 40f } },
},
Version = Version,
};
}
protected override void LoadDefaultConfig()
=> config = GetBaseConfig();
protected override void LoadConfig()
{
base.LoadConfig();
config = Config.ReadObject<Configuration>();
if (config.Version < Version)
UpdateConfigValues();
Config.WriteObject(config, true);
}
protected override void SaveConfig()
=> Config.WriteObject(config, true);
private void UpdateConfigValues()
{
PrintWarning("Your config file is outdated! Updating config values...");
config.Version = Version;
PrintWarning("Config updated!");
}
#endregion
#region Lang
protected override void LoadDefaultMessages()
{
lang.RegisterMessages(new Dictionary<string, string>()
{
{ "LimitReached", "You’ve reached the limit of {0}. A maximum of {1} can be placed within {2} meters." },
}, this);
}
#endregion
#region Init
private void OnServerInitialized()
{
InitShortPrefabNameToItemShortName();
}
private void Unload()
{
ShortPrefabNameToItemShortName.Clear();
}
#endregion
#region Methods
private void InitShortPrefabNameToItemShortName()
{
foreach (var itemDefinition in ItemManager.GetItemDefinitions())
{
var deployablePrefab = itemDefinition.GetComponent<ItemModDeployable>()?.entityPrefab?.resourcePath;
if (string.IsNullOrEmpty(deployablePrefab))
continue;
var shortPrefabName = Utility.GetFileNameWithoutExtension(deployablePrefab);
if (!string.IsNullOrEmpty(shortPrefabName) && !ShortPrefabNameToItemShortName.ContainsKey(shortPrefabName))
{
ShortPrefabNameToItemShortName.Add(shortPrefabName, itemDefinition.shortname);
}
}
}
private void SendTipMsg(BasePlayer player, string messageID, params object[] args)
{
if (player == null || string.IsNullOrEmpty(messageID))
return;
var chatMessage = string.Format(lang.GetMessage(messageID, this, player.UserIDString), args);
player.SendConsoleCommand("gametip.showtoast", "5", chatMessage);
Effect.server.Run(LockDenidedPrefab, player.transform.position);
}
#endregion
#region Hooks
private void OnEntityBuilt(Planner planner, GameObject gameObject)
{
BasePlayer player = planner.GetOwnerPlayer();
if (!player)
return;
Item item = player.GetActiveItem();
if (item == null)
return;
string itemShortname = item.info.shortname;
if (!config.TrapsList.TryGetValue(itemShortname, out var trapConfig))
return;
Vector3 position = gameObject.transform.position;
int trapCount = 0;
var entities = Pool.Get<List<BaseEntity>>();
Vis.Entities(position, trapConfig.trapLimitRadius, entities, LayerMask.GetMask("Deployed"));
foreach (var entity in entities)
{
string prefabName = entity.ShortPrefabName;
if (ShortPrefabNameToItemShortName.TryGetValue(prefabName, out var deployableShortname) && deployableShortname == itemShortname)
{
float distance = Vector3.Distance(position, entity.transform.position);
if (distance <= trapConfig.trapLimitRadius)
{
trapCount++;
if (trapCount > trapConfig.trapLimit)
break;
}
}
}
Pool.FreeUnmanaged(ref entities);
if (trapCount > trapConfig.trapLimit)
{
SendTipMsg(player, "LimitReached", item.info.displayName.english, trapConfig.trapLimit, trapConfig.trapLimitRadius);
player.GiveItem(ItemManager.CreateByItemID(item.info.itemid, 1));
var builtEntity = gameObject.ToBaseEntity();
if (builtEntity != null && !builtEntity.IsDestroyed)
{
builtEntity.Kill();
}
return;
}
}
#endregion
}
}