• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!

Cooldown items

Status
Not open for further replies.
Level 10
Joined
Mar 17, 2012
Messages
579
Hi everyone! Tell me please how to forbid hero to sell or take off item when it is on cooldown???

Because I faced a little bug... If I use item with active ability Avatar and take it off while under the effect, when effect ends and I don't have this Item - I stay big and can do this stuf forever to a critical error :ogre_frown:

So... IceFrog solved this problem by forbiding hero to take off item if it's on cooldown...

Does anyone know how to do it?
 
Level 19
Joined
Aug 8, 2007
Messages
2,765
Make two items. The first one is your item u already have. Copy it to create the second one. Enable the "Cannot be dropped, sold, etc." fields

On item use, make a trigger. When this item is used, remove item 1 and add item two. Wait for however long the item's cooldown is than remove item two and add item one.

(theres probably another way to do it, but im too lazy to open WE. You could also use hashtables and timers so you dont have to use the "Wait" function, but you shouldnt worry too bad about it as long as it works)
 
Level 12
Joined
Sep 11, 2011
Messages
1,176
Here is the triggers

Using Item

Undroppable

Unit Indexer

  • Using Item
    • Events
      • Unit - A unit Uses an item
    • Conditions
      • (Item-type of (Item being manipulated)) Equal to Crystal Ball
    • Actions
      • Set cv = (Custom value of (Triggering unit))
      • Set Item[cv] = (Item being manipulated)
      • Set Cooldown[cv] = 5.00
      • Item - Make (Item being manipulated) Undroppable
      • Unit Group - Add (Triggering unit) to User
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Undroppable <gen> is on) Equal to False
        • Then - Actions
          • Trigger - Turn on Undroppable <gen>
        • Else - Actions
  • Undroppable
    • Events
      • Time - Every 0.03 seconds of game time
    • Conditions
    • Actions
      • Unit Group - Pick every unit in User and do (Actions)
        • Loop - Actions
          • Set cv = (Custom value of (Picked unit))
          • Set Cooldown[cv] = (Cooldown[cv] - 0.03)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • Cooldown[cv] Less than or equal to 0.00
            • Then - Actions
              • Item - Make Item[cv] Droppable
              • Trigger - Turn off (This trigger)
            • Else - Actions
  • Unit Indexer
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Custom script: call ExecuteFunc("InitializeUnitIndexer")
      • Custom script: endfunction
      • -------- --------
      • -------- This is the most important function - it provides an index for units as they enter the map --------
      • -------- --------
      • Custom script: function IndexUnit takes nothing returns boolean
      • Custom script: local integer pdex = udg_UDex
      • -------- --------
      • -------- You can use the boolean UnitIndexerEnabled to protect some of your undesirable units from being indexed --------
      • -------- - Example: --------
      • -------- -- Set UnitIndexerEnabled = False --------
      • -------- -- Unit - Create 1 Dummy for (Triggering player) at TempLoc facing 0.00 degrees --------
      • -------- -- Set UnitIndexerEnabled = True --------
      • -------- --------
      • -------- You can also customize the following block - if conditions are false the (Matching unit) won't be indexed. --------
      • -------- --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • UnitIndexerEnabled Equal to True
        • Then - Actions
          • -------- --------
          • -------- Generate a unique integer index for this unit --------
          • -------- --------
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • UDexRecycle Equal to 0
            • Then - Actions
              • Set UDex = (UDexGen + 1)
              • Set UDexGen = UDex
            • Else - Actions
              • Set UDex = UDexRecycle
              • Set UDexRecycle = UDexNext[UDex]
          • -------- --------
          • -------- Link index to unit, unit to index --------
          • -------- --------
          • Set UDexUnits[UDex] = (Matching unit)
          • Unit - Set the custom value of UDexUnits[UDex] to UDex
          • -------- --------
          • -------- Use a doubly-linked list to store all active indexes --------
          • -------- --------
          • Set UDexPrev[UDexNext[0]] = UDex
          • Set UDexNext[UDex] = UDexNext[0]
          • Set UDexNext[0] = UDex
          • -------- --------
          • -------- Fire index event for UDex --------
          • -------- --------
          • Set UnitIndexEvent = 0.00
          • Set UnitIndexEvent = 1.00
          • Set UnitIndexEvent = 0.00
          • Custom script: set udg_UDex = pdex
        • Else - Actions
      • Custom script: return false
      • Custom script: endfunction
      • -------- --------
      • -------- The next function is called each time a unit enters the map --------
      • -------- --------
      • Custom script: function IndexNewUnit takes nothing returns boolean
      • Custom script: local integer pdex = udg_UDex
      • Custom script: local integer ndex
      • -------- --------
      • -------- Recycle indices of units no longer in-play every (15) units created --------
      • -------- --------
      • Set UDexWasted = (UDexWasted + 1)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • UDexWasted Equal to 15
        • Then - Actions
          • Set UDexWasted = 0
          • Set UDex = UDexNext[0]
          • Custom script: loop
          • Custom script: exitwhen udg_UDex == 0
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Custom value of UDexUnits[UDex]) Equal to 0
            • Then - Actions
              • -------- --------
              • -------- Remove index from linked list --------
              • -------- --------
              • Custom script: set ndex = udg_UDexNext[udg_UDex]
              • Custom script: set udg_UDexNext[udg_UDexPrev[udg_UDex]] = ndex
              • Custom script: set udg_UDexPrev[ndex] = udg_UDexPrev[udg_UDex]
              • Set UDexPrev[UDex] = 0
              • -------- --------
              • -------- Fire deindex event for UDex --------
              • -------- --------
              • Set UnitIndexEvent = 2.00
              • Set UnitIndexEvent = 0.00
              • -------- --------
              • -------- Recycle the index for later use --------
              • -------- --------
              • Set UDexUnits[UDex] = No unit
              • Set UDexNext[UDex] = UDexRecycle
              • Set UDexRecycle = UDex
              • Custom script: set udg_UDex = ndex
            • Else - Actions
              • Set UDex = UDexNext[UDex]
          • Custom script: endloop
          • Custom script: set udg_UDex = pdex
        • Else - Actions
      • -------- --------
      • -------- Handle the entering unit (Matching unit) --------
      • -------- --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Custom value of (Matching unit)) Equal to 0
        • Then - Actions
          • Custom script: call IndexUnit()
        • Else - Actions
      • Custom script: return false
      • Custom script: endfunction
      • -------- --------
      • -------- The next function initializes the core of the system --------
      • -------- --------
      • Custom script: function InitializeUnitIndexer takes nothing returns nothing
      • Custom script: local integer i = 0
      • Custom script: local region re = CreateRegion()
      • Custom script: local rect r = GetWorldBounds()
      • Set UnitIndexerEnabled = True
      • Custom script: call RegionAddRect(re, r)
      • Custom script: call TriggerRegisterEnterRegion(CreateTrigger(), re, Filter(function IndexNewUnit))
      • Custom script: call RemoveRect(r)
      • Custom script: set re = null
      • Custom script: set r = null
      • Custom script: loop
      • Custom script: call GroupEnumUnitsOfPlayer(bj_lastCreatedGroup, Player(i), Filter(function IndexUnit))
      • Custom script: set i = i + 1
      • Custom script: exitwhen i == 16
      • Custom script: endloop
      • -------- --------
      • -------- This is the "Unit Indexer Initialized" event, use it instead of "Map Initialization" for best results --------
      • -------- --------
      • Set UnitIndexEvent = 3.00
      • Set UnitIndexEvent = 0.00
And a test map. I'm using Unit Indexer created by Bribe. Crystal Ball is just an example and it has active ability (Avatar).
 

Attachments

  • Cooldown Items.w3x
    21 KB · Views: 49
Level 10
Joined
Mar 17, 2012
Messages
579
Here is the triggers

Using Item

Undroppable

Unit Indexer

  • Using Item
    • Events
      • Unit - A unit Uses an item
    • Conditions
      • (Item-type of (Item being manipulated)) Equal to Crystal Ball
    • Actions
      • Set cv = (Custom value of (Triggering unit))
      • Set Item[cv] = (Item being manipulated)
      • Set Cooldown[cv] = 5.00
      • Item - Make (Item being manipulated) Undroppable
      • Unit Group - Add (Triggering unit) to User
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Undroppable <gen> is on) Equal to False
        • Then - Actions
          • Trigger - Turn on Undroppable <gen>
        • Else - Actions
  • Undroppable
    • Events
      • Time - Every 0.03 seconds of game time
    • Conditions
    • Actions
      • Unit Group - Pick every unit in User and do (Actions)
        • Loop - Actions
          • Set cv = (Custom value of (Picked unit))
          • Set Cooldown[cv] = (Cooldown[cv] - 0.03)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • Cooldown[cv] Less than or equal to 0.00
            • Then - Actions
              • Item - Make Item[cv] Droppable
              • Trigger - Turn off (This trigger)
            • Else - Actions
  • Unit Indexer
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Custom script: call ExecuteFunc("InitializeUnitIndexer")
      • Custom script: endfunction
      • -------- --------
      • -------- This is the most important function - it provides an index for units as they enter the map --------
      • -------- --------
      • Custom script: function IndexUnit takes nothing returns boolean
      • Custom script: local integer pdex = udg_UDex
      • -------- --------
      • -------- You can use the boolean UnitIndexerEnabled to protect some of your undesirable units from being indexed --------
      • -------- - Example: --------
      • -------- -- Set UnitIndexerEnabled = False --------
      • -------- -- Unit - Create 1 Dummy for (Triggering player) at TempLoc facing 0.00 degrees --------
      • -------- -- Set UnitIndexerEnabled = True --------
      • -------- --------
      • -------- You can also customize the following block - if conditions are false the (Matching unit) won't be indexed. --------
      • -------- --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • UnitIndexerEnabled Equal to True
        • Then - Actions
          • -------- --------
          • -------- Generate a unique integer index for this unit --------
          • -------- --------
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • UDexRecycle Equal to 0
            • Then - Actions
              • Set UDex = (UDexGen + 1)
              • Set UDexGen = UDex
            • Else - Actions
              • Set UDex = UDexRecycle
              • Set UDexRecycle = UDexNext[UDex]
          • -------- --------
          • -------- Link index to unit, unit to index --------
          • -------- --------
          • Set UDexUnits[UDex] = (Matching unit)
          • Unit - Set the custom value of UDexUnits[UDex] to UDex
          • -------- --------
          • -------- Use a doubly-linked list to store all active indexes --------
          • -------- --------
          • Set UDexPrev[UDexNext[0]] = UDex
          • Set UDexNext[UDex] = UDexNext[0]
          • Set UDexNext[0] = UDex
          • -------- --------
          • -------- Fire index event for UDex --------
          • -------- --------
          • Set UnitIndexEvent = 0.00
          • Set UnitIndexEvent = 1.00
          • Set UnitIndexEvent = 0.00
          • Custom script: set udg_UDex = pdex
        • Else - Actions
      • Custom script: return false
      • Custom script: endfunction
      • -------- --------
      • -------- The next function is called each time a unit enters the map --------
      • -------- --------
      • Custom script: function IndexNewUnit takes nothing returns boolean
      • Custom script: local integer pdex = udg_UDex
      • Custom script: local integer ndex
      • -------- --------
      • -------- Recycle indices of units no longer in-play every (15) units created --------
      • -------- --------
      • Set UDexWasted = (UDexWasted + 1)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • UDexWasted Equal to 15
        • Then - Actions
          • Set UDexWasted = 0
          • Set UDex = UDexNext[0]
          • Custom script: loop
          • Custom script: exitwhen udg_UDex == 0
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Custom value of UDexUnits[UDex]) Equal to 0
            • Then - Actions
              • -------- --------
              • -------- Remove index from linked list --------
              • -------- --------
              • Custom script: set ndex = udg_UDexNext[udg_UDex]
              • Custom script: set udg_UDexNext[udg_UDexPrev[udg_UDex]] = ndex
              • Custom script: set udg_UDexPrev[ndex] = udg_UDexPrev[udg_UDex]
              • Set UDexPrev[UDex] = 0
              • -------- --------
              • -------- Fire deindex event for UDex --------
              • -------- --------
              • Set UnitIndexEvent = 2.00
              • Set UnitIndexEvent = 0.00
              • -------- --------
              • -------- Recycle the index for later use --------
              • -------- --------
              • Set UDexUnits[UDex] = No unit
              • Set UDexNext[UDex] = UDexRecycle
              • Set UDexRecycle = UDex
              • Custom script: set udg_UDex = ndex
            • Else - Actions
              • Set UDex = UDexNext[UDex]
          • Custom script: endloop
          • Custom script: set udg_UDex = pdex
        • Else - Actions
      • -------- --------
      • -------- Handle the entering unit (Matching unit) --------
      • -------- --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Custom value of (Matching unit)) Equal to 0
        • Then - Actions
          • Custom script: call IndexUnit()
        • Else - Actions
      • Custom script: return false
      • Custom script: endfunction
      • -------- --------
      • -------- The next function initializes the core of the system --------
      • -------- --------
      • Custom script: function InitializeUnitIndexer takes nothing returns nothing
      • Custom script: local integer i = 0
      • Custom script: local region re = CreateRegion()
      • Custom script: local rect r = GetWorldBounds()
      • Set UnitIndexerEnabled = True
      • Custom script: call RegionAddRect(re, r)
      • Custom script: call TriggerRegisterEnterRegion(CreateTrigger(), re, Filter(function IndexNewUnit))
      • Custom script: call RemoveRect(r)
      • Custom script: set re = null
      • Custom script: set r = null
      • Custom script: loop
      • Custom script: call GroupEnumUnitsOfPlayer(bj_lastCreatedGroup, Player(i), Filter(function IndexUnit))
      • Custom script: set i = i + 1
      • Custom script: exitwhen i == 16
      • Custom script: endloop
      • -------- --------
      • -------- This is the "Unit Indexer Initialized" event, use it instead of "Map Initialization" for best results --------
      • -------- --------
      • Set UnitIndexEvent = 3.00
      • Set UnitIndexEvent = 0.00
And a test map. I'm using Unit Indexer created by Bribe. Crystal Ball is just an example and it has active ability (Avatar).

I allways wanted to ask... I don't get what is Custom Value? Why we need it and what function does it have? :ogre_icwydt:

P.S. Your system is pretty cool, but I solved my problem by setting Wait - 8 seconds (it's Avatar duration) and dropable\undropable function))) Frankly speaking, I didn't know about this function))) I didn't see it)))

Whatever you deserve +rep =) thx)

P.S.S I'd be very thankful if you tell me about Custom Values... why we need them... what they do... :)
 
Last edited:
Level 19
Joined
Aug 8, 2007
Messages
2,765
I allways wanted to ask... I don't get what is Custom Value? Why we need it and what function does it have? :ogre_icwydt:

P.S. Your system is pretty cool, but I solved my problem by setting Wait - 8 seconds (it's Avatar duration) and dropable\undropable function))) Frankly speaking, I didn't know about this function))) I didn't see it)))

Whatever you deserve +rep =) thx)

P.S.S I'd be very thankful if you tell me about Custom Values... why we need them... what they do... :)

Every item and unit has a custom value specifically assigned to it and not to the unit as a whole, defaultly set to 0. So lets say i set this unit's custom value to 5, if i get the custom value of another unit it will say 0 but if i get the value on that unit it will say 5. Unit Indexer sets every unit in-game's custom value to a value only for that unit. So if you had an array per-say, you could say Integer_Array[Custom Value of Unit] and it would return the value that the Unit Indexer set it to
 
Level 12
Joined
Sep 11, 2011
Messages
1,176
Every item and unit has a custom value specifically assigned to it and not to the unit as a whole, defaultly set to 0. So lets say i set this unit's custom value to 5, if i get the custom value of another unit it will say 0 but if i get the value on that unit it will say 5. Unit Indexer sets every unit in-game's custom value to a value only for that unit. So if you had an array per-say, you could say Integer_Array[Custom Value of Unit] and it would return the value that the Unit Indexer set it to

just like hashtables, custom value can save handles too and it's alot easier than hashtables.

for example you want to save a real variable, when you use hashtable you do this :

Save

Load

  • Set handleID = (Key (Triggering unit))
  • Set Time = 5.00
  • Hashtable - Save Time as 0 of handleID in Hashtable
  • Unit Group - Add (Triggering unit) to Group
  • Unit Group - Pick every unit in Group and do (Actions)
    • Loop - Actions
      • Set handleID = (Key (Picked unit))
      • Set Time = ((Load 0 of handleID from Hashtable) - 0.10)
and when you use Custom Value you do this :

Save

Load

  • Set cv = (Custom value of (Triggering unit))
  • Set Times[cv] = 5.00
  • Unit Group - Add (Triggering unit) to Group
  • Unit Group - Pick every unit in Group and do (Actions)
    • Loop - Actions
      • Set cv = (Custom value of (Picked unit))
      • Set Times[cv] = (Times[cv] - 0.10)
just remember that custom value requires Bribe's Unit Indexer to be used
see the difference ? they do the same thing, but not on the same time. we can conclude that :

Spartipillo said:
The downside of hashtables is that they're 3 times slower than variables when saving, and 2 times slower than variables when loading, because requires more arguments (4 to save, 3 to load); arrays just need 1.
 
Last edited:
Level 33
Joined
Mar 27, 2008
Messages
8,035
@TwoVenomous
Just to acknowledge you, that Hashtable is indeed, an array too, however it is 2D Array where we have childKey and parentKey.

Also,
The downside of hashtables is that they're 3 times slower than variables when saving, and 2 times slower than variables when loading, because requires more arguments (4 to save, 3 to load); arrays just need 1.
Pretty bull**** to me, because you can't even detect the "slowness" (to human eyes) of Hashtable compared to Indexing. Trust me, the speed comparison is negligible.
 
Level 10
Joined
Mar 17, 2012
Messages
579
just like hashtables, custom value can save handles too and it's alot easier than hashtables.

for example you want to save a real variable, when you use hashtable you do this :

Save

Load

  • Set handleID = (Key (Triggering unit))
  • Set Time = 5.00
  • Hashtable - Save Time as 0 of handleID in Hashtable
  • Unit Group - Add (Triggering unit) to Group
  • Unit Group - Pick every unit in Group and do (Actions)
    • Loop - Actions
      • Set handleID = (Key (Picked unit))
      • Set Time = ((Load 0 of handleID from Hashtable) - 0.10)
and when you use Custom Value you do this :

Save

Load

  • Set cv = (Custom value of (Triggering unit))
  • Set Times[cv] = 5.00
  • Unit Group - Add (Triggering unit) to Group
  • Unit Group - Pick every unit in Group and do (Actions)
    • Loop - Actions
      • Set cv = (Custom value of (Picked unit))
      • Set Times[cv] = (Times[cv] - 0.10)
just remember that custom value requires Bribe's Unit Indexer to be used
see the difference ? they do the same thing, but not on the same time. we can conclude that :

So we use em just because of simpleness? :ogre_icwydt:
So if I don't use Custom Values - there is nothing bad here?)))
 
Level 12
Joined
Sep 11, 2011
Messages
1,176
@TwoVenomous
Just to acknowledge you, that Hashtable is indeed, an array too, however it is 2D Array where we have childKey and parentKey.

Also,

Pretty bull**** to me, because you can't even detect the "slowness" (to human eyes) of Hashtable compared to Indexing. Trust me, the speed comparison is negligible.

thanks alot for the information. but it did save me time though, i used to be clicking lot of times using hashtable, while using custom value i click less. maybe it's different when i use jass ?

So we use em just because of simpleness?
So if I don't use Custom Values - there is nothing bad here?)))

well, if you don't, and use wait instead, it won't be MUI.
 
Level 33
Joined
Mar 27, 2008
Messages
8,035
thanks alot for the information. but it did save me time though, i used to be clicking lot of times using hashtable, while using custom value i click less. maybe it's different when i use jass ?
Oh, if you want to compare the "time consume", well yeah, basically using CV/Unit Indexer saves a lot of time, really.
Like Spart said, yeah you'll be needing to save 3 to 4 values compared to CV, you only need 1.

But, there's a hidden advantage of Hashtable... which you can save a value to non-exist object in that map yet, this is something CV/Unit Indexer can't beat, other than that, I prefer Indexing.

Basically,
Hashtable = Unit Indexer
BUT
Unit Indexer != Indexing

Because technically, Unit Indexer IS a part of Hashtable (which uses key as to load/save values to).

In Indexing, you will lose speed compared to Unit Indexer because Indexing uses Linear/Binary Search to obtain certain values, while UI just load the key directly accessing the value.

Read here for more info: http://www.hiveworkshop.com/forums/2225726-post6.html
 
Level 12
Joined
Sep 11, 2011
Messages
1,176
But, there's a hidden advantage of Hashtable... which you can save a value to non-exist object in that map yet.

hey, how do i do something like that ? i can't save the item(just example) to a Unit type, there is no such handle Id like that.

  • Untitled Trigger 001
    • Events
      • Unit - A unit Uses an item
    • Conditions
      • (Unit-type of (Triggering unit)) Equal to Paladin
    • Actions
      • Hashtable - Save Handle Of(Item being manipulated) as 0 of (Key (Triggering unit)) in hash
did you mean when i save to a Paladin and i create another Paladin, i can load the item from the new Paladin ?

  • Set tempLoc = (Center of (Playable map area))
  • Unit - Create 1 Paladin for Player 1 (Red) at tempLoc facing Default building facing degrees
  • Item - Create (Item-type of (Load 0 of (Key (Last created unit)) in hash) at (Position of (Last created unit))
  • Custom script : call RemoveLocation (udg_tempLoc)
 
Level 33
Joined
Mar 27, 2008
Messages
8,035
Instructions in the test map;
1. Press ESC
2. It will show up the saved value to a Unit Type - Paladin
3. If the value is 200, well, you have successfully save/load value from/to a Unit Type - Paladin
4. If the value is 0, it fails.

Wait, this is getting offtopic (in fact, thread hijacking lol), we should stop, PM me for further details.

Also,
hey, how do i do something like that ? i can't save the item(just example) to a Unit type,
You cannot save Data Type to a Data Type - such as Item Type to Unit Type
Well, you can do some trick, perhaps saving the Integer ID of that item to a Unit Type.
 

Attachments

  • Save Value To Hashtable.w3x
    12.5 KB · Views: 37
Level 10
Joined
Mar 17, 2012
Messages
579
ZiGOR, do you know MUI ?

If you're talking about JASS, than no, I don't(

If you're talking about multilanguage - I didn't need it yet... I was solving my problems in GUI before... If there's no way to solve some problem besides MUI - I'll have to learn some) I need a good teacher that will explain me basics of MUI :ogre_kawaii:
 
Status
Not open for further replies.
Top