coolDownSystem

I implemented a simple cooldown system in the actionstore script. It seems to work fine. But I wonder if I might have missed something, some critical bug? I gave the dockedItems a cooldown variable. I also added a cooldown variable on the actionitem. I then made a list of DockedItemSlot.

In the use method i check if the item is in cooldown, if so i return false. Then i add the dockedItemSlot to the list and set its cooldown to the cooldown variable in the actionItem script.

In the update method i decrease the value of the cooldown for all the items in the list and remove them from the list if cooldown reaches 0.

I also wonder if someone has any idea of how to make the cooldown visible in the slot the item is in. Ex an area that fades out like a clock arm moving around the slot.

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Linq;
using GameDevTV.Saving;

namespace GameDevTV.Inventories
{
    /// <summary>
    /// Provides the storage for an action bar. The bar has a finite number of
    /// slots that can be filled and actions in the slots can be "used".
    /// 
    /// This component should be placed on the GameObject tagged "Player".
    /// </summary>
    public class ActionStore : MonoBehaviour, ISaveable
    {
        List<DockedItemSlot> coolDownItems = new List<DockedItemSlot>();
        


        private void Update()
        {
            
                for (int i = coolDownItems.Count - 1; i >= 0; i--)
                {
                    coolDownItems[i].cooldown -= Time.deltaTime;
                    if (coolDownItems[i].cooldown < 0)
                    {
                        coolDownItems.Remove(coolDownItems[i]);
                    }
                }
                
           
            
        }


        // STATE
        Dictionary<int, DockedItemSlot> dockedItems = new Dictionary<int, DockedItemSlot>();
        private class DockedItemSlot
        {
            public ActionItem item;
            public int number;
            public float cooldown = 0;
        }

        // PUBLIC

        /// <summary>
        /// Broadcasts when the items in the slots are added/removed.
        /// </summary>
        public event Action storeUpdated;

        /// <summary>
        /// Get the action at the given index.
        /// </summary>
        public ActionItem GetAction(int index)
        {
            if (dockedItems.ContainsKey(index))
            {
                return dockedItems[index].item;
            }
            return null;
        }

        /// <summary>
        /// Get the number of items left at the given index.
        /// </summary>
        /// <returns>
        /// Will return 0 if no item is in the index or the item has
        /// been fully consumed.
        /// </returns>
        public int GetNumber(int index)
        {
            if (dockedItems.ContainsKey(index))
            {
                return dockedItems[index].number;
            }
            return 0;
        }

        /// <summary>
        /// Add an item to the given index.
        /// </summary>
        /// <param name="item">What item should be added.</param>
        /// <param name="index">Where should the item be added.</param>
        /// <param name="number">How many items to add.</param>
        public void AddAction(InventoryItem item, int index, int number)
        {
            if (dockedItems.ContainsKey(index))
            {
                if (object.ReferenceEquals(item, dockedItems[index].item))
                {
                    dockedItems[index].number += number;
                }
            }
            else
            {
                var slot = new DockedItemSlot();
                slot.item = item as ActionItem;
                slot.number = number;
                dockedItems[index] = slot;
            }
            if (storeUpdated != null)
            {
                storeUpdated();
            }
        }

        /// <summary>
        /// Use the item at the given slot. If the item is consumable one
        /// instance will be destroyed until the item is removed completely.
        /// </summary>
        /// <param name="user">The character that wants to use this action.</param>
        /// <returns>False if the action could not be executed.</returns>
        public bool Use(int index, GameObject user)
        {

            if (dockedItems.ContainsKey(index))
            {

                for (int i = coolDownItems.Count - 1; i >= 0; i--)
                {
                    
                    if(coolDownItems[i].cooldown > 0 && object.ReferenceEquals(coolDownItems[i].item, dockedItems[index].item))
                    {
                        return false;
                    }
                }

                dockedItems[index].item.Use(user);
                coolDownItems.Add(dockedItems[index]);
                var coolDownItem = coolDownItems.Last();
                coolDownItem.cooldown = dockedItems[index].item.coolDownTimer();

                if (dockedItems[index].item.isConsumable())
                {
                    RemoveItems(index, 1);
                }
                return true;
            }
            return false;
        }

        /// <summary>
        /// Remove a given number of items from the given slot.
        /// </summary>
        public void RemoveItems(int index, int number)
        {
            if (dockedItems.ContainsKey(index))
            {
                dockedItems[index].number -= number;
                if (dockedItems[index].number <= 0)
                {
                    dockedItems.Remove(index);
                }
                if (storeUpdated != null)
                {
                    storeUpdated();
                }
            }

        }

        /// <summary>
        /// What is the maximum number of items allowed in this slot.
        /// 
        /// This takes into account whether the slot already contains an item
        /// and whether it is the same type. Will only accept multiple if the
        /// item is consumable.
        /// </summary>
        /// <returns>Will return int.MaxValue when there is not effective bound.</returns>
        public int MaxAcceptable(InventoryItem item, int index)
        {
            var actionItem = item as ActionItem;
            if (!actionItem) return 0;

            // if we already have an item in this slot but its not of the same type as the item we want to
            // add we cant add it.
            if (dockedItems.ContainsKey(index) && !object.ReferenceEquals(item, dockedItems[index].item))
            {
                return 0;
            }
            // if its a consumable item you can take as many items as you want in the slot.
            if (actionItem.isConsumable())
            {
                return int.MaxValue;
            }
            // if its not a consumable item and it already contains an item you cant take anything.
            if (dockedItems.ContainsKey(index))
            {
                return 0;
            }
            //otherwise if its not consumable you can take just one item.
            return 1;
        }

        /// PRIVATE

        [System.Serializable]
        private struct DockedItemRecord
        {
            public string itemID;
            public int number;
        }

        object ISaveable.CaptureState()
        {
            var state = new Dictionary<int, DockedItemRecord>();
            foreach (var pair in dockedItems)
            {
                var record = new DockedItemRecord();
                record.itemID = pair.Value.item.GetItemID();
                record.number = pair.Value.number;
                state[pair.Key] = record;
            }
            return state;
        }

        void ISaveable.RestoreState(object state)
        {
            var stateDict = (Dictionary<int, DockedItemRecord>)state;
            foreach (var pair in stateDict)
            {
                AddAction(InventoryItem.GetFromID(pair.Value.itemID), pair.Key, pair.Value.number);
            }
        }
    }
}

We use a slightly different approach for cooldowns in our Shops and Abilities course (the final course in the series) where we make a CooldownManager with a Dictionary<ActionItem, float>, but it can be done this way. The only downside I see is that you could simply drag the item into Inventory and back again to reset the cooldown, which won’t work with our CooldownManager.

For the countdown display, add a semi-transparent image as an overlay to the ActionItemUI. Make sure that the image has RaycastTarget turned off. Then ActionSlotUI.Update() can adjust this overlay as needed.

Great thnx! Didnt know there was a cooldown system, i probably use that instead. I tried dragging item into iventory and back again but it doesnt reset the cooldown.

Privacy & Terms