C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace Oxide.Plugins
{
[Info("Better Grenades", "redBDGR", "1.0.3")]
[Description("Adds enhanced grenades features")]
class BetterGrenades : RustPlugin
{
private bool Changed;
private static BetterGrenades plugin;
private Dictionary<string, float> throwerList = new Dictionary<string, float>();
private float f1FuseTime = 10f;
private float beancanFuseTime = 5f;
#region Configuration
protected override void LoadDefaultConfig()
{
Config.Clear();
LoadVariables();
}
private void LoadVariables()
{
f1FuseTime = Convert.ToSingle(GetConfig("Settings", "F1 Grenade Fuse Time", 10f));
beancanFuseTime = Convert.ToSingle(GetConfig("Settings", "Beancan Grenade Fuse Time", 5f));
if (!Changed) return;
SaveConfig();
Changed = false;
}
#endregion
#region Oxide Hooks
private void Init()
{
plugin = this;
LoadVariables();
foreach(BasePlayer player in BasePlayer.activePlayerList)
if (player.IsConnected)
if (player.GetActiveItem()?.info.shortname == "grenade.f1" || player.GetActiveItem()?.info.shortname == "grenade.beancan")
{
GrenadeTimer grenadeTimer = player.GetComponent<GrenadeTimer>();
if (grenadeTimer)
grenadeTimer.DestroyThis();
player.gameObject.AddComponent<GrenadeTimer>();
}
}
private void Unload()
{
foreach(BasePlayer player in BasePlayer.activePlayerList)
player.GetComponent<GrenadeTimer>()?.DestroyThis();
}
private void OnExplosiveThrown(BasePlayer player, BaseEntity entity)
{
if (!throwerList.ContainsKey(player.UserIDString))
return;
if (entity.ShortPrefabName != "grenade.f1.deployed" && entity.ShortPrefabName != "grenade.beancan.deployed")
return;
TimedExplosive expl = entity.GetComponent<TimedExplosive>();
if (!expl) return;
expl.CancelInvoke("Explode");
expl.SetFuse(throwerList[player.UserIDString]);
}
private void OnExplosiveDropped(BasePlayer player, BaseEntity entity)
{
if (!throwerList.ContainsKey(player.UserIDString))
return;
if (entity.ShortPrefabName != "grenade.f1.deployed" && entity.ShortPrefabName != "grenade.beancan.deployed")
return;
TimedExplosive expl = entity.GetComponent<TimedExplosive>();
if (!expl) return;
expl.CancelInvoke("Explode");
expl.SetFuse(throwerList[player.UserIDString]);
}
private void OnActiveItemChanged(BasePlayer player, Item oldItem, Item newItem)
{
if (newItem != null)
if (newItem.info.shortname == "grenade.f1" || newItem.info.shortname == "grenade.beancan")
player.gameObject.AddComponent<GrenadeTimer>();
else if (oldItem != null)
if (oldItem.info.shortname == "grenade.f1" || oldItem.info.shortname == "grenade.beancan")
player.GetComponent<GrenadeTimer>()?.DestroyThis();
}
#endregion
#region MonoBehaviour Classes
private class GrenadeTimer : MonoBehaviour
{
private BasePlayer player;
private Item activeItem;
private bool cookingGrenade;
private float startTime;
private float timeUntilGrenadeFire;
private void Awake()
{
player = GetComponent<BasePlayer>();
activeItem = player.GetActiveItem();
}
private void Update()
{
if (!player)
{
DestroyThis();
return;
}
Item latestItem = player.GetActiveItem();
if (latestItem == null)
{
DestroyThis();
return;
}
if (latestItem.info.shortname != "grenade.f1" || latestItem.info.shortname != "grenade.beancan")
{
DestroyThis();
return;
}
if (player.serverInput.IsDown(BUTTON.FIRE_PRIMARY))
{
if (!cookingGrenade)
{
cookingGrenade = true;
startTime = UnityEngine.Time.time;
timeUntilGrenadeFire = startTime + GetExplosionLength(activeItem);
}
if (UnityEngine.Time.time >= timeUntilGrenadeFire)
HandleSuicideExplosion(activeItem);
}
else
{
if (!cookingGrenade)
return;
if (plugin.throwerList.ContainsKey(player.UserIDString))
plugin.throwerList.Remove(player.UserIDString);
plugin.throwerList.Add(player.UserIDString, timeUntilGrenadeFire - UnityEngine.Time.time);
cookingGrenade = false;
}
}
private static float GetExplosionLength(Item item)
{
switch (item.info.shortname)
{
case "grenade.f1":
return plugin.f1FuseTime;
case "grenade.beancan":
return plugin.beancanFuseTime;
}
return 10f;
}
private void HandleSuicideExplosion(Item item) // الله أكبر
{
player.inventory.containerBelt.Take(new List<Item>{ item }, item.info.itemid, 1);
BaseEntity grenade = null;
switch (item.info.shortname)
{
case "grenade.f1":
grenade = GameManager.server.CreateEntity("assets/prefabs/weapons/f1 grenade/grenade.f1.deployed.prefab", player.transform.position + new Vector3(0, 1, 0));
break;
case "grenade.beancan":
grenade = GameManager.server.CreateEntity("assets/prefabs/weapons/beancan grenade/grenade.beancan.deployed.prefab", player.transform.position + new Vector3(0, 1, 0));
break;
}
if (grenade == null)
return;
grenade.Spawn();
TimedExplosive expl = grenade.GetComponent<TimedExplosive>();
expl.Explode();
cookingGrenade = false;
if (!player.IsDead())
RemoveActiveItem(player);
DestroyThis();
}
// Active item removal code courtesy of Fujikura
private static void RemoveActiveItem(BasePlayer player)
{
foreach (var item in player.inventory.containerBelt.itemList.Where(x => x.IsValid() && x.GetHeldEntity()).ToList())
{
var slot = item.position;
item.RemoveFromContainer();
item.MarkDirty();
plugin.timer.Once(0.15f, () =>
{
if (item == null)
return;
item.MoveToContainer(player.inventory.containerBelt, slot);
item.MarkDirty();
});
}
}
public void DestroyThis() => Destroy(this);
}
#endregion
private object GetConfig(string menu, string datavalue, object defaultValue)
{
var data = Config[menu] as Dictionary<string, object>;
if (data == null)
{
data = new Dictionary<string, object>();
Config[menu] = data;
Changed = true;
}
object value;
if (data.TryGetValue(datavalue, out value)) return value;
value = defaultValue;
data[datavalue] = value;
Changed = true;
return value;
}
}
}