Support for Skin ID (Suggestion)

Would you be against adding skin Id support for this plugin? you could add cooldowns per skin id and perms per id. If you had any questions I am sure WhiteThunder could give some guidance.

There is a quick patch here for skin ID but not the cooldowns or perms.

using UnityEngine;
using System.Collections.Generic;
using System;
using Oxide.Core;

namespace Oxide.Plugins
{
    [Info("Signal Cooldown", "Vliek", "1.0.31", ResourceId = 2805)]
    [Description("Add a cooldown to supply signals to avoid that players are going to leave from rage.")]
    class SignalCooldown : RustPlugin
    {
        private bool Changed;
        private bool refundSignal;
        private int timeCooldown;
        private string cooldownPerm;
        private ulong messageIcon;
        private int authLevel;

        public List<ulong> signalCooldown = new List<ulong>();
        public Dictionary<ulong, float> lastRun = new Dictionary<ulong, float>();

        string GetLang(string msg, string userID) => lang.GetMessage(msg, this, userID);

        protected override void LoadDefaultConfig()
        {
            Puts("Creating a new config file.");
            Config.Clear();
            LoadVariables();
        }
        private void LoadVariables()
        {
            refundSignal = Convert.ToBoolean(GetConfig("Settings", "Refund signal", true));
            timeCooldown = Convert.ToInt32(GetConfig("Settings", "Cooldown in seconds", 300));
            cooldownPerm = Convert.ToString(GetConfig("Settings", "Ignore cooldown permission", "signalcooldown.ignore"));
            messageIcon = Convert.ToUInt64(GetConfig("Settings", "Icon for message", 0));
            authLevel = Convert.ToInt32(GetConfig("Settings", "Auth level admin commands", 1));

            if (!Changed) return;
            SaveConfig();
            Changed = false;
        }

        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))
            {
                value = defaultValue;
                data[datavalue] = value;
                Changed = true;
            }
            return value;
        }

        protected override void LoadDefaultMessages()
        {
            lang.RegisterMessages(new Dictionary<string, string>
            {
                ["cooldownActive"] = "<color=#b7b7b7>Supplysignal cooldown active, wait {0} seconds till you can throw a signal again.</color>",
                ["cooldownOver"] = "<color=#b7b7b7>You are able to throw a supplysignal again.</color>",
                ["noPermission"] = "<color=#b7b7b7>You don't have the required auth level to run this command.</color>",
                ["manualReset"] = "<color=#b7b7b7>All supplysignal cooldowns have been manually reset.</color>"
            }, this);
        }

        private void Init()
        {
            LoadVariables();
            permission.RegisterPermission(cooldownPerm, this);
        }

        public bool HasSignalCooldown(ulong userId)
        {
            if (signalCooldown.Contains(userId))
            {
                return true;
            }
            return false;
        }

        private void OnExplosiveDropped(BasePlayer player, BaseEntity entity) => OnExplosiveThrown(player, entity);

        private void OnExplosiveThrown(BasePlayer player, BaseEntity entity)
        {
            if (entity.ShortPrefabName != "grenade.supplysignal.deployed")
                return;
            if (!permission.UserHasPermission(player.UserIDString, cooldownPerm))
            {
                if (signalCooldown.Contains(player.userID))
                {
                    float difference = (lastRun[player.userID] + timeCooldown) - UnityEngine.Time.time;
                    float finaldifference = Mathf.Round(difference);
                    entity.Kill();
                    Player.Message(player, GetLang("cooldownActive", player.UserIDString), null, messageIcon, finaldifference);
                    if (refundSignal)
                    {
                        Item item = ItemManager.CreateByName("supply.signal", 1, entity.skinID);
                        if (item != null)
                        {
                            player.inventory.GiveItem(item, player.inventory.containerBelt);
                        }
                    }
                    return;
                }

                signalCooldown.Add(player.userID);
                lastRun.Add(player.userID, UnityEngine.Time.time);
                timer.Once(timeCooldown, () =>
                {
                    signalCooldown.Remove(player.userID);
                    lastRun.Remove(player.userID);
                    Player.Message(player, GetLang("cooldownOver", player.UserIDString), null, messageIcon);
                });
                //Puts("Signal cooldown started on " + player.displayName);
                return;
            }
            return;
        }

        [ChatCommand("signalreset")]
        private void ResetTimeCMD(BasePlayer player, string command, string[] args)
        {
            if (player.Connection.authLevel < authLevel)
            {
                Player.Message(player, GetLang("noPermission", player.UserIDString), null, messageIcon);
                return;
            }
            Player.Message(player, GetLang("manualReset", player.UserIDString), null, messageIcon);
            Reset();
        }

        void Reset()
        {
            signalCooldown.Clear();
            lastRun.Clear();
            Puts("All cooldowns have been manually reset.");
        }
    }
}

Β 

This has been implemented in v1.0.32.

How to implement this, there is nothing in the docs ?

What I implemented was a bug fix where if signals were on cooldown, attempting to throw a skinned signal would refund an unskinned one. Now, throwing a skinned signal, if you are are cooldown, will refund a skinned signal. I think LizardMods' request was going beyond, asking for configurable cooldown per skin, which has not been done.

ahh I assumed when you said it was implemented it was the configurable cooldown, all good thanks.

@WhiteThunder
It appears this is not giving back skinned signals anymore, Was testing with a Admin on their servers not sure what changed but it should however its giving back regualr signals again instead of the skinned ones
buMBXA6BPKEP0nw.jpg FastBurst
@WhiteThunder
It appears this is not giving back skinned signals anymore, Was testing with a Admin on their servers not sure what changed but it should however its giving back regualr signals again instead of the skinned ones
I just tested and still seeing the skinned signals get refunded. You might be experiencing an interaction with another plugin.
NKXTQs24ExGTuL8.jpg WhiteThunder
I just tested and still seeing the skinned signals get refunded. You might be experiencing an interaction with another plugin.

We tested it with Vehicle Airdrops and it was giving back regular supply signals

buMBXA6BPKEP0nw.jpg FastBurst

We tested it with Vehicle Airdrops and it was giving back regular supply signals

Same Problem here, please Fix this πŸ™
Or do I have to enter the IDs somewhere?

NKXTQs24ExGTuL8.jpgWeißer Donner
I just tested it and I still see that the skinned signals are being refunded. You may be experiencing an interaction with another plugin.

To be absolutely sure that another plugin is not causing the problem, I tested it on my test server.
There is only
Vehicle Airdrops 1.0.20
and
SignalCooldown 1.0.32.

During the cooldown, only a standard signal is returned, but not the actual signal with the ID.



Merged post

I have found the problem.
It is related to the loading of the plugins. There

no cooldown is active.
Now when I reload VehicleAirdrops, the drops are only returned as default signal if they are thrown during a cooldown.
But when I reload SignalCooldown, it works again.
So it seems to have something to do with the order in which the plugins are loaded. Could you check that?

Merged post

Oddly enough I spoke and discussed this with NIkedemos and I don't know why but on Vehicle Airdrops in the config this apparently makes a huge deal
"Use 3RD party plugin to handle stack sizes, like StacksExtended, Stack Size Controller etc": false

If you have any type of stacking plugin you need to set to TRUE, once that was done in our test, the signal cooldown works as it should flawlessly. Again I do not know why or how or the logic behind it, but he knew exactly what the issue was as soon as I showed him the config and afte reloading the plugin it works perfectly fine.Β 

Now if you DO NOT have any type of stacking plugin that is a different story. Hopefully this helps out

I changed it and set it to true. I thought it would work now. But if you wait for it to cool down and then try again, there is a supply signal and no custom drop.
Like I said in my last post,
It has to do with restarting the plugins. If I reload VA, it stops working and gives me a supply signal. If I reload SignalCooldown, it works.
Try multiple drops and different plugin restarts, it will happen again.
That is a pity.

I just tested with the latest version of Signal Cooldown and Vehicle Airdrops v1.0.20 (by Nikedemos), but I couldn't reproduce this issueΒ and I was able to reproduce the issue when using the vabuy command, but not when I created the signals via another plugin. Seems the way the signals are created by Vehicle Airdrops is incorrect. The item is skinned but the held entity is not. This happens because the item is created without the skin, then the skin is applied afterward, and not applied correctly. The plugin attempts to correct the held entity skin when it's thrown, but depending on hook call order, the skin may be corrected too late (after Signal Cooldown has refunded the signal). This needs to be fixed in Vehicle Airdrops.

For what it's worth, there are alternative designs for Signal Cooldown which would circumvent this issue. I have submitted a patch to Signal Cooldown which will resolve this. In case it takes time to review/merge the patch, here is the updated code for OnExplosiveDropped and OnExplosiveThrown. The difference is that the skin ID is now determined from the item rather than from the entity.

private void OnExplosiveDropped(BasePlayer player, SupplySignal signal, ThrownWeapon thrownWeapon) => OnExplosiveThrown(player, signal, thrownWeapon);

private void OnExplosiveThrown(BasePlayer player, SupplySignal signal, ThrownWeapon thrownWeapon)
{
    if (signal.ShortPrefabName != "grenade.supplysignal.deployed")
        return;
    if (!permission.UserHasPermission(player.UserIDString, cooldownPerm))
    {
        if (signalCooldown.Contains(player.userID))
        {
            float difference = (lastRun[player.userID] + timeCooldown) - UnityEngine.Time.time;
            float finaldifference = Mathf.Round(difference);
            signal.Kill();
            Player.Message(player, GetLang("cooldownActive", player.UserIDString), null, messageIcon, finaldifference);
            if (refundSignal)
            {
                Item item = ItemManager.CreateByName("supply.signal", 1, thrownWeapon.GetItem().skin);
                if (item != null)
                {
                    player.inventory.GiveItem(item, player.inventory.containerBelt);
                }
            }
            return;
        }

        signalCooldown.Add(player.userID);
        lastRun.Add(player.userID, UnityEngine.Time.time);
        timer.Once(timeCooldown, () =>
        {
            signalCooldown.Remove(player.userID);
            lastRun.Remove(player.userID);
            Player.Message(player, GetLang("cooldownOver", player.UserIDString), null, messageIcon);
        });
        //Puts("Signal cooldown started on " + player.displayName);
        return;
    }
    return;
}
NKXTQs24ExGTuL8.jpg WhiteThunder

I just tested with the latest version of Signal Cooldown and Vehicle Airdrops v1.0.20 (by Nikedemos), but I couldn't reproduce this issueΒ and I was able to reproduce the issue when using the vabuy command, but not when I created the signals via another plugin. Seems the way the signals are created by Vehicle Airdrops is incorrect. The item is skinned but the held entity is not. This happens because the item is created without the skin, then the skin is applied afterward, and not applied correctly. The plugin attempts to correct the held entity skin when it's thrown, but depending on hook call order, the skin may be corrected too late (after Signal Cooldown has refunded the signal). This needs to be fixed in Vehicle Airdrops.

For what it's worth, there are alternative designs for Signal Cooldown which would circumvent this issue. I have submitted a patch to Signal Cooldown which will resolve this. In case it takes time to review/merge the patch, here is the updated code for OnExplosiveDropped and OnExplosiveThrown. The difference is that the skin ID is now determined from the item rather than from the entity.

private void OnExplosiveDropped(BasePlayer player, SupplySignal signal, ThrownWeapon thrownWeapon) => OnExplosiveThrown(player, signal, thrownWeapon);

private void OnExplosiveThrown(BasePlayer player, SupplySignal signal, ThrownWeapon thrownWeapon)
{
    if (signal.ShortPrefabName != "grenade.supplysignal.deployed")
        return;
    if (!permission.UserHasPermission(player.UserIDString, cooldownPerm))
    {
        if (signalCooldown.Contains(player.userID))
        {
            float difference = (lastRun[player.userID] + timeCooldown) - UnityEngine.Time.time;
            float finaldifference = Mathf.Round(difference);
            signal.Kill();
            Player.Message(player, GetLang("cooldownActive", player.UserIDString), null, messageIcon, finaldifference);
            if (refundSignal)
            {
                Item item = ItemManager.CreateByName("supply.signal", 1, thrownWeapon.GetItem().skin);
                if (item != null)
                {
                    player.inventory.GiveItem(item, player.inventory.containerBelt);
                }
            }
            return;
        }

        signalCooldown.Add(player.userID);
        lastRun.Add(player.userID, UnityEngine.Time.time);
        timer.Once(timeCooldown, () =>
        {
            signalCooldown.Remove(player.userID);
            lastRun.Remove(player.userID);
            Player.Message(player, GetLang("cooldownOver", player.UserIDString), null, messageIcon);
        });
        //Puts("Signal cooldown started on " + player.displayName);
        return;
    }
    return;
}

Hey, great, that has solved the problem.
Thanks for your efforts.