• 🏆 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!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

[Spell] Need a charge system (in GUI)

Status
Not open for further replies.
Level 12
Joined
May 16, 2020
Messages
660
Hi guys,

For my map I want to have several abilities which don’t have a cooldown, but instead hold “charges”.


Details:

A charge is basically the amount of times you can use a spell freely before it goes on cooldown. Upon casting the ability, one charge is spent.

Once all charges are spent, the spell changes to a passive icon and cannot be cast anymore. The passive icon displays the remaining charge cooldown. As soon as 1 charge is gained, the spell changes to its active icon again and no cooldown is visible anymore (but in the background the charges are still recharging).

For passive cooldown see here: Passive ability with cooldown - Best method!

A charge starts charging as soon as one charge is spent. Only one charge can recharge at a time. The current amount of viable charges should be displayed as buff (I will make icons via photoshop which show “1”, “2” etc.).

I found only one other thread on hive which is about the same topic, but the solution there doesn’t sound exactly like what I want: Ability with charges

I tried to do the system myself, but I didn’t know how to re-name each remaining charge once a charge “recharged” (so that in a loop I can specify which charge I’m referring to next and take this as cooldown for the passive ability if the spell is cast another time).

Can someone please help create a system for this in GUI, which can be applied to different spells?

Cheers
 
Level 12
Joined
May 16, 2020
Messages
660
This is what I have so far. However, it bugs at several places:
  1. General: If I cast the ability in quick succession, the cd is a lot lower than what it should be
  2. General: The CD is not correctly displayed within the passive ability
  3. Second trigger: For some reason the trigger only display the numbers for Shrapnel_CDCounter[1], but nothing beyond. I guess this is already the first reason for point #2
***

Main trigger:
  • Shrapnel
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Shrapnel
    • Actions
      • Set VariableSet Shrapnel_Index = (Shrapnel_Index + 1)
      • Set VariableSet Shrapnel_RechargeTime = 5.00
      • Game - Display to (All players) the text: (String(Shrapnel_Index))
      • Set VariableSet Shrapnel_Caster = (Triggering unit)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Shrapnel Charge Recharge <gen> is on) Equal to False
        • Then - Actions
          • Set VariableSet Shrapnel_CDCounter[Shrapnel_Index] = Shrapnel_RechargeTime
          • Trigger - Turn on Shrapnel Periodic <gen>
          • Countdown Timer - Start Shrapnel_Periodic as a Repeating timer that will expire in 0.50 seconds
          • Trigger - Turn on Shrapnel Charge Recharge <gen>
          • Countdown Timer - Start Shrapnel_Timer as a Repeating timer that will expire in Shrapnel_RechargeTime seconds
        • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Shrapnel_Index Equal to 3
        • Then - Actions
          • Unit - Remove Shrapnel from Shrapnel_Caster
          • Unit - Add Shrapnel (Disabled CD) to Shrapnel_Caster
          • Ability - Set Ability: (Unit: Shrapnel_Caster's Ability with Ability Code: Shrapnel (Disabled CD))'s Real Level Field: Cooldown ('acdn') of Level: 0 to (Shrapnel_RechargeTime - Shrapnel_CDCounter[1])
          • Unit - Add Cargo Hold (Meat Wagon - Dummy Disabled) to Shrapnel_Caster
        • Else - Actions
Trigger to keep track of the cooldown which I want to add to the passive ability:
  • Shrapnel Periodic
    • Events
      • Time - Shrapnel_Periodic expires
    • Conditions
    • Actions
      • For each (Integer Shrapnel_Loop) from 1 to Shrapnel_Index, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • Shrapnel_CDCounter[Shrapnel_Loop] Greater than 0.00
            • Then - Actions
              • Set VariableSet Shrapnel_CDCounter[Shrapnel_Loop] = (Shrapnel_CDCounter[Shrapnel_Loop] - 0.50)
              • Game - Display to (All players) the text: (String(Shrapnel_CDCounter[Shrapnel_Loop]))
            • Else - Actions
Trigger to recharge the charges and remove passive ability once at least one charge is available:
  • Shrapnel Charge Recharge
    • Events
      • Time - Shrapnel_Timer expires
    • Conditions
    • Actions
      • Set VariableSet Shrapnel_Index = (Shrapnel_Index - 1)
      • Game - Display to (All players) the text: (String(Shrapnel_Index))
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Shrapnel_Index Equal to 2
        • Then - Actions
          • Unit - Remove Cargo Hold (Meat Wagon - Dummy Disabled) from Shrapnel_Caster
          • Unit - Remove Shrapnel (Disabled CD) from Shrapnel_Caster
          • Unit - Add Shrapnel to Shrapnel_Caster
        • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Shrapnel_Index Equal to 0
        • Then - Actions
          • Countdown Timer - Pause Shrapnel_Timer
          • Trigger - Turn off (This trigger)
          • Countdown Timer - Pause Shrapnel_Periodic
          • Trigger - Turn off Shrapnel Periodic <gen>
        • Else - Actions
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,555
You'd want to use a Hashtable in the case of a spell like this so you can keep track of the Cooldowns (Charge Restore Time) of multiple casts on the same unit.

That being said, I figured i'd try my hand at making the spell with just a Unit Indexer, and it turned out alright.
  • Cast Shrapnel
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Shrapnel (Hero)
    • Actions
      • Set VariableSet CV = (Custom value of (Triggering unit))
      • Set VariableSet Level = (Level of (Ability being cast) for (Triggering unit))
      • Unit - Remove Shrapnel_Ability[Shrapnel_Charges[CV]] from (Triggering unit)
      • -------- --------
      • -------- Remove Charge --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Shrapnel_Charges[CV] Equal to 1
        • Then - Actions
          • -------- 0 charges --------
          • Set VariableSet Shrapnel_Charges[CV] = (Shrapnel_Charges[CV] - 1)
          • Unit - Remove Shrapnel_Buff[1] buff from (Triggering unit)
          • Unit - Add Shrapnel_Ability[0] to (Triggering unit)
          • Unit - For (Triggering unit), Ability Shrapnel_Ability[0], Disable ability: True, Hide UI: False
          • Unit - For (Triggering unit), Ability Shrapnel_Ability[0], Disable ability: False, Hide UI: False
          • Unit - For Unit (Triggering unit), Set cooldown of ability (Ability being cast), Level: (Level - 1) to Shrapnel_Cooldown[Level]
        • Else - Actions
          • -------- 1 to 3 charges --------
          • Unit - Remove Shrapnel_Buff[Shrapnel_Charges[CV]] buff from (Triggering unit)
          • Set VariableSet Shrapnel_Charges[CV] = (Shrapnel_Charges[CV] - 1)
          • Unit - Add Shrapnel_Ability[Shrapnel_Charges[CV]] to (Triggering unit)
          • Unit - For (Triggering unit), Ability Shrapnel_Ability[Shrapnel_Charges[CV]], Disable ability: True, Hide UI: False
          • Unit - For (Triggering unit), Ability Shrapnel_Ability[Shrapnel_Charges[CV]], Disable ability: False, Hide UI: False
      • -------- --------
      • Wait Shrapnel_Cooldown[Level] seconds
      • -------- --------
      • -------- Add Charge --------
      • Set VariableSet CV = (Custom value of (Triggering unit))
      • Set VariableSet Level = (Level of Shrapnel (Hero) for (Triggering unit))
      • Unit - Remove Shrapnel_Ability[Shrapnel_Charges[CV]] from (Triggering unit)
      • Unit - For Unit (Triggering unit), end cooldown of ability Shrapnel (Hero)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Shrapnel_Charges[CV] Equal to 0
        • Then - Actions
          • -------- 0 charges --------
          • Set VariableSet Shrapnel_Charges[CV] = (Shrapnel_Charges[CV] + 1)
          • Unit - Remove Shrapnel_Buff[0] buff from (Triggering unit)
          • Unit - Add Shrapnel_Ability[1] to (Triggering unit)
          • Unit - For (Triggering unit), Ability Shrapnel_Ability[1], Disable ability: True, Hide UI: False
          • Unit - For (Triggering unit), Ability Shrapnel_Ability[1], Disable ability: False, Hide UI: False
          • Unit - For Unit (Triggering unit), Set cooldown of ability Shrapnel (Hero), Level: (Level - 1) to 0.00
        • Else - Actions
          • -------- 1 to 3 charges --------
          • Unit - Remove Shrapnel_Buff[Shrapnel_Charges[CV]] buff from (Triggering unit)
          • Set VariableSet Shrapnel_Charges[CV] = (Shrapnel_Charges[CV] + 1)
          • Unit - Add Shrapnel_Ability[Shrapnel_Charges[CV]] to (Triggering unit)
          • Unit - For (Triggering unit), Ability Shrapnel_Ability[Shrapnel_Charges[CV]], Disable ability: True, Hide UI: False
          • Unit - For (Triggering unit), Ability Shrapnel_Ability[Shrapnel_Charges[CV]], Disable ability: False, Hide UI: False
          • Unit - For Unit (Triggering unit), Set cooldown of ability (Ability being cast), Level: (Level - 1) to 0.00
-I have 4 hidden Endurance Aura abilities that are used to represent the Charge buffs. These are added/removed whenever you cast Shrapnel.
-The primary ability has a cooldown of 0 seconds, which I change to 5.00 seconds when you cast your last charge. After 5.00 seconds of casting the spell, I reset it's cooldown and increase the charge count by 1.
-When the charge count increases from 0 to 1+ I set the abilities cooldown back to 0.00 seconds again.
-The only downside is that the visual cooldown indicator on the ability won't reflect the true time left to regain a charge. This feature would require you to keep track of each cooldown of each charge at all times (Hashtable handles this well).
-Things like Refresher Orb (resetting all ability cooldowns) will break this unless you design around it.

Side Note:
That passive ability cooldown system has become a lot easier now that we have this:
  • Unit - For Unit (Triggering unit), start cooldown of ability Exhume Corpses " over "10.00 seconds.
So if you want Passive abilities with cooldowns, you still have to use Exhume Corpses, but you can trigger it's cooldown easily with the above action.
 

Attachments

  • Shrapnel Example 1.w3m
    21 KB · Views: 38
Last edited:
Level 12
Joined
May 16, 2020
Messages
660
Thanks a lot Uncle. Two things:
  1. It's correct to have a "fixed" cooldown of X seconds to internally keep track of when a charge becomes available, but the displayed cooldown should not necessarily be X seconds. Currently the fixed cooldown results in a charge becoming available (and thus removing the passive ability), much earlier than "Shrapnel_Cooldown[Level]" would suggest. This is the reason why in my previous post I used "Shrapnel Periodic", to keep track how much cooldown should actually be displayed.
  2. Is it safe to use "wait"..? I want this to be MUI, and I always thought waits prevent a spell from being MUI.
 
Level 12
Joined
Feb 5, 2018
Messages
521
Is it safe to use "wait"..? I want this to be MUI, and I always thought waits prevent a spell from being MUI.

Yes. This spell is made in a way that the wait does not break things. There are multiple ways of making wait safe.
1) Local variables
2) Dynamic Indexing
3) Hashtables
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,555
It's safe to use Waits with Triggering Unit, it's the only Event Response that works like this (it's essentially a local variable).

If you tried to reference something like Target unit of ability being cast after a Wait you'd see that it wouldn't work.

And yeah, my version functions correctly, it's only a visual issue with the displayed cooldown. A Hashtable would be nice to keep track of each Charges restore time.

The Hashtable could look SOMETHING like this, I might throw it together in a little bit:
  • Events:
  • A unit starts the effect of an ability
  • Actions:
  • Save 5.00 as Shrapnel_Charges[cv] of Key(Triggering Unit) in ShrapnelHashtable
  • Set Variable Shrapnel_Charges[cv] = Shrapnel_Charges[cv] - 1
  • Add triggering unit to ShrapnelGroup
  • Turn on ShrapnelTimer
Then in ShrapnelTimer:
  • Events:
  • Every 0.05 seconds
  • Actions:
  • Pick every unit in ShrapnelGroup
  • Set cv = Custom value of picked unit
  • For each IntegerA from 1 to 3:
  • Set Variable LoadValue = ((Load IntegerA of Key(Picked Unit) in ShrapnelHashtable) - 0.05)
  • Save LoadValue as Shrapnel_Charges[cv] of Key(Triggering Unit) in ShrapnelHashtable
  • If LoadValue <= 0.00 then: Set Variable Shrapnel_Charges[cv] = Shrapnel_Charges[cv] + 1, etc...
 
Level 12
Joined
May 16, 2020
Messages
660
Thanks you two.

@Uncle: Regarding Hashtables: Can this Hastable be used only for this specific spell, or can other spells (which also use a charge system) also use this hashtable?

Ideally I'd like to have a system which other spells can also use (I will probably have like 15-20 spells with Charges), but if that's not possible then I guess a hashtable for each spell is also OK.
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,555
Thanks you two.

@Uncle: Regarding Hashtables: Can this Hastable be used only for this specific spell, or can other spells (which also use a charge system) also use this hashtable?

Ideally I'd like to have a system which other spells can also use (I will probably have like 15-20 spells with Charges), but if that's not possible then I guess a hashtable for each spell is also OK.
A system like that is possible although i'm sure it will be a headache to manage.

Anyway, here's a version using a Hashtable. I left in the debug messages so you can see what's going on.

I also made an interesting discovery. It turns out that ability Cooldowns run at 1/2 the speed of a Timer/Periodic Event. Meaning 10.00 seconds of Cooldown is equivalent to 20.00 seconds of Elasped Time.
Edit: Not sure if this discovery is accurate as my other version that I posted a few comments down doesn't have this issue. Not too sure what's going on here.

You'll see I manage this by running my Loop every 0.10 seconds and reducing the duration by 0.05 each time. This cuts the speed in half and syncs the Timer up with the Ability Cooldown.

Edit: Forgot to clear the Hashtable Children. Re-uploaded.
 

Attachments

  • Shrapnel Example 2.w3m
    23.5 KB · Views: 33
Last edited:
Level 12
Joined
May 16, 2020
Messages
660
Amazing - thank you!

I will first try to understand what is happending and experiment a bit with the passive ability (aestetic-wise I think I prefer the passive solution over showing cooldown in the active ability, but I will have to compare both). Will let you know if anything pops up.

***

Edit: Just realized that something doesn't work as intended: Currently the charges recharge all at once. However, they should recharge sequentally, i.e. charge 1 (10 sec) > charge 2 (10 sec) > charge 3 (10 sec) etc.

How would I need to adjust the trigger in this case?
 
Last edited:

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,555
Amazing - thank you!

I will first try to understand what is happending and experiment a bit with the passive ability (aestetic-wise I think I prefer the passive solution over showing cooldown in the active ability, but I will have to compare both). Will let you know if anything pops up.

***

Edit: Just realized that something doesn't work as intended: Currently the charges recharge all at once. However, they should recharge sequentally, i.e. charge 1 (10 sec) > charge 2 (10 sec) > charge 3 (10 sec) etc.

How would I need to adjust the trigger in this case?
Oh doy, I don't know what I was thinking when I designed it like that. I guess that can be used for something else. I'll fix it real quick.

Edit:
Uploaded v.3. This one doesn't require a Hashtable and works properly. Also, the cooldown/timer thing sorted itself out, no idea why it doesn't work in the previous setup.
 

Attachments

  • Shrapnel Example 3.w3m
    22.2 KB · Views: 47
Last edited:
Status
Not open for further replies.
Top