C#:
using Newtonsoft.Json;
using System.Collections.Generic;
using Facepunch;
using UnityEngine;
namespace Oxide.Plugins
{
[Info("Explosives Detonation", "Beast_", "2.0.1")]
[Description("Detonate the explosives on shooting them.")]
public class ExplosivesDetonation : RustPlugin
{
#region Fields
private Configuration config;
private const string PERM_USE = "explosivesdetonation.use";
#endregion
#region Configuration
private class Configuration
{
[JsonProperty("Allow arrows to trigger explosions")]
public bool AllowArrows { get; set; } = true;
[JsonProperty("Allow melee weapons to trigger explosions")]
public bool AllowMelee { get; set; } = true;
[JsonProperty("Affect deployable siege explosives")]
public bool AffectDeployables { get; set; } = true;
[JsonProperty("Chain Reaction")]
public ChainReaction chainReaction { get; set; } = new ChainReaction();
public class ChainReaction
{
[JsonProperty("Enabled")]
public bool Enabled { get; set; } = true;
[JsonProperty("Radius")]
public float Radius { get; set; } = 5f;
[JsonProperty("Delay (seconds)")]
public float Delay { get; set; } = 0.3f;
}
public string ToJson() => JsonConvert.SerializeObject(this);
public Dictionary<string, object> ToDictionary() => JsonConvert.DeserializeObject<Dictionary<string, object>>(ToJson());
}
protected override void LoadDefaultConfig() => config = new Configuration();
protected override void LoadConfig()
{
base.LoadConfig();
try
{
config = Config.ReadObject<Configuration>();
if (config == null) throw new JsonException();
SaveConfig();
}
catch
{
PrintWarning($"Configuration file {Name}.json is invalid; using defaults");
LoadDefaultConfig();
}
}
protected override void SaveConfig() => Config.WriteObject(config);
#endregion
#region Hooks
private void Init() => permission.RegisterPermission(PERM_USE, this);
private object OnPlayerAttack(BasePlayer attacker, HitInfo info)
{
if (attacker == null || !permission.UserHasPermission(attacker.UserIDString, PERM_USE)) return null;
if (info?.HitEntity == null) return null;
var hitEntity = info.HitEntity;
if (hitEntity == null || !hitEntity.IsValid()) return null;
var heldEntity = attacker.GetHeldEntity();
if (heldEntity == null || ShouldPreventTrigger(heldEntity))
return null;
var explosives = hitEntity as TimedExplosive;
if (explosives != null && explosives.IsValid())
{
NextFrame(() => TriggerExplosion(explosives));
return null;
}
if (config.AffectDeployables)
{
var siegeEntity = hitEntity as DeployableSiegeExplosive;
if (siegeEntity != null && siegeEntity.IsValid())
{
NextFrame(() => {
siegeEntity.CancelInvoke("ActuallyExplode");
siegeEntity.SendMessage("ActuallyExplode");
if (config.chainReaction.Enabled)
TriggerNearbyExplosives(siegeEntity.transform.position);
});
}
}
return null;
}
#endregion
#region Helper
private void TriggerExplosion(TimedExplosive explosive)
{
if (explosive == null || !explosive.IsValid()) return;
explosive.Explode();
if (config.chainReaction.Enabled)
TriggerNearbyExplosives(explosive.transform.position);
}
private void TriggerNearbyExplosives(Vector3 position)
{
var nearby = Pool.Get<List<BaseEntity>>();
Vis.Entities(position, config.chainReaction.Radius, nearby);
int i = 1;
foreach (var entity in nearby)
{
if (entity == null || !entity.IsValid()) continue;
float delay = i * config.chainReaction.Delay;
if (entity is TimedExplosive otherExplosive)
{
if (config.chainReaction.Delay > 0f)
{
timer.Once(delay, () =>
{
if (otherExplosive != null && otherExplosive.IsValid())
otherExplosive.Explode();
});
}
else
{
if (otherExplosive != null && otherExplosive.IsValid())
otherExplosive.Explode();
}
i++;
}
else if (config.AffectDeployables && entity is DeployableSiegeExplosive siege)
{
if (config.chainReaction.Delay > 0f)
{
timer.Once(delay, () =>
{
if (siege != null && siege.IsValid())
{
siege.CancelInvoke("ActuallyExplode");
siege.SendMessage("ActuallyExplode");
}
});
}
else
{
if (siege != null && siege.IsValid())
{
siege.CancelInvoke("ActuallyExplode");
siege.SendMessage("ActuallyExplode");
}
}
i++;
}
}
Pool.FreeUnmanaged(ref nearby);
}
private bool ShouldPreventTrigger(HeldEntity heldEntity)
{
if (heldEntity is BaseMelee && !config.AllowMelee)
return true;
else if (heldEntity is BowWeapon && !config.AllowArrows)
return true;
else return false;
}
#endregion
}
}