• 🏆 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!

[Trigger] Stance Swap Ability - Vanishing Abilities

Status
Not open for further replies.
Level 2
Joined
Oct 16, 2017
Messages
16
Hi everyone,

A week or two ago I posted a thread about making a stance swapping mechanic that retained the cooldowns used in other stances. A person suggested disabling/enabling abilities as stances are swapped which worked fine but I have ran into some issues with it.

As a bit of a prelude I will explain what I mean by stance swapping. It's based on the Warrior class in World of Warcraft, where different abilities required being in a particular stance to be cast. I'm trying to replicate that to a degree, where I will be having 12 different abilities cast between 3 stances. A unit will use a stance and have 4 abilities available, as well as 2 abilities to swap between other stances.

Currently I have 3 stances: Assault, Fortress and Skilled.
When the unit is in Assault stance it should have the Second Wind and Charge ability. In Skilled Stance it should have Shattering Slam. And in Fortress Stance it should have the Shield Slam ability.

Assault Stance (AS) is based on Mana Shield. Skilled Stance (SS) is based on Immolation. Fortress Stance (FS) is based on Windwalk.

My current issue is that the skilled stance and fortress stance when used consecutively will remove all abilities from being available. I think it would be easier to just give examples as per below.

The default stance is assault stance.

AS --> SS --> AS - The trigger works fine, abilities are available in appropriate stances.
AS --> FS --> AS - Same as above.
AS --> SS --> AS --> FS - The Shield Slam ability becomes unavailable in FS and further stance swapping breaks the trigger more.
AS --> FS --> SS --> AS/FS --> Every ability other than the stance abilities vanishes.
AS --> SS --> FS --> AS/SS --> Same as above.

I've went through the trigger plenty of times trying to find a spot where I don't reactivate an ability or deactivate it twice but I can't find it if that is the issue. I was hoping someone else might be able to find the flaw in it.

I have attached screenshots of the triggers used and a test map with the Knight unit with the stances/abilities. Any recommendations or assistance would be appreciated. Thank you.
Knight Stances.png
 

Attachments

  • Stance Swap.w3x
    77.1 KB · Views: 23
Level 39
Joined
Feb 27, 2007
Messages
4,994
  • For future reference: How To Post Your Trigger
  • Why remove and re-add the stance abilities instead of just enabling and disabling them like the others?
  • You could base your 3 stance swapping skills on Channel (Spells - Channel). I presume you used immo/mana/ww to show a buff on the UI bar for each stance? Since Channel does not confer a buff, these can instead be bestowed by dummy abilities with infinite duration or self-targeted auras.
  • The Clean Dummy trigger in your map is entirely unnecessary; give them no model and set to "can't raise, does not decay" and they'll instantly be removed on death anyway. (But maybe I misunderstand the purpose of this trigger because unit types are missing from it.)
  • Don't use the map init event for anything; if you put too much stuff under it you can crash the init thread and then not all of it will run. Used "elapsed game time" events at 0.10 or something instead.

The reason it its bugging out is because Blizzard made the ability UI enable/hide functions work with an 'absolute counter' sort of system. Best explained by an example:
  • An ability on a unit starts with an 'enabled count' of 1 and a 'visible count' of 1.
  • If an ability's enabled count reaches 0 or less it will be disabled until the counter goes > 0.
  • If an ability's visible count reaches 0 or less it will be hidden until the counter goes > 0.
  • Every time you disable an ability its 'enabled count' goes down by 1 (and goes up by 1 when you enable)
  • Every time you hide an ability its 'hidden count' goes down by 1 (and goes up by 1 when you un-hide)

  • If you disable an ability twice in a row, the enable count is now -1. If you enable the ability once its enable count will be 0 so it won't actually be enabled. Enabling it a second time puts the count back to 1 so it is fully enabled.
  • The same is true for hiding.
  • This counter works indefinitely: if you disable an ability 135 times you'll have to enable it 135 times for it to finally become enabled.
  • It also works for going > 1: if you enable 65 times in a row you'll have to disable 65+1 times to get it to be disabled (+1 because the ability started enabled at a count of 1 so you went 1+65 = 66, -65 = 1, -1 = 0 to be disabled)
  • An example from your map:
    • Start Assault
      • Events
        • Map initialization
      • Conditions
      • Actions
        • Unit - For Knight 0000 <gen>, Ability Shattering Slam , Disable ability: True, Hide UI: True
        • Unit - For Knight 0000 <gen>, Ability Shield Slam , Disable ability: True, Hide UI: True
        • Unit - For Knight 0000 <gen>, Ability Shield Slam , Disable ability: True, Hide UI: True //Disabling a second time
        • Wait 2.00 game-time seconds
        • Unit - For Knight 0000 <gen>, Ability Shield Slam , Disable ability: False, Hide UI: False //ABILTY NOT SHOWN HERE
        • Wait 2.00 game-time seconds
        • Unit - For Knight 0000 <gen>, Ability Shield Slam , Disable ability: False, Hide UI: False //ABILITY SHOWN HERE
You are disabling and hiding abilities in other stances that already weren't enabled/visible, so their counts are going below 0. Then when you try to enable/show them their counts aren't > 0 so they aren't actually enabled/shown. The only way to fix this is to know which abilities need to be disabled/hidden based on the stance you were in before the stance swap happened. Then only disable/hidden the abilities that were previously enabled/shown but should no longer be. A few arrays (and a simulated 2D array) will help you here (as well as allow an ability to exist in multiple or all stances if you should so choose):
  • Events
    • Time - Elapsed game-time is 0.50 seconds
  • Conditions
  • Actions
    • Set Stance_Count = 3
    • -------- --------
    • Set Stance_Assault = 1
    • Set Stance_Skilled = 2
    • Set Stance_Fortress = 3
    • -------- --------
    • Set Stance[Stance_Assault] = Assault Stance //the ability
    • Set Stance[Stance_Skilled] = Skilled Stance
    • Set Stance[Stance_Fortress] = Fortress Stance
    • -------- --------
    • Set StanceAbil_Count = (StanceAbil_Count + 1)
    • Set StanceAbil[StanceAbil_Count] = Second Wind
    • Set StanceAbil_Active[((StanceAbil_Count x Stance_Count) + Stance_Assault)] = True //this ability active in assault stance
    • Set StanceAbil_Active[((StanceAbil_Count x Stance_Count) + Stance_Skilled)] = False //not active in skilled stance
    • Set StanceAbil_Active[((StanceAbil_Count x Stance_Count) + Stance_Fortress)] = False //not active if Fortress stance
    • -------- --------
    • Set StanceAbil_Count = (StanceAbil_Count + 1)
    • Set StanceAbil[StanceAbil_Count] = Charge
    • Set StanceAbil_Active[((StanceAbil_Count x Stance_Count) + Stance_Assault)] = True
    • Set StanceAbil_Active[((StanceAbil_Count x Stance_Count) + Stance_Skilled)] = False
    • Set StanceAbil_Active[((StanceAbil_Count x Stance_Count) + Stance_Fortress)] = False
    • -------- --------
    • Set StanceAbil_Count = (StanceAbil_Count + 1)
    • Set StanceAbil[StanceAbil_Count] = Shattering Slam
    • Set StanceAbil_Active[((StanceAbil_Count x Stance_Count) + Stance_Assault)] = False
    • Set StanceAbil_Active[((StanceAbil_Count x Stance_Count) + Stance_Skilled)] = True
    • Set StanceAbil_Active[((StanceAbil_Count x Stance_Count) + Stance_Fortress)] = False
    • -------- --------
    • Set StanceAbil_Count = (StanceAbil_Count + 1)
    • Set StanceAbil[StanceAbil_Count] = Shield Slam
    • Set StanceAbil_Active[((StanceAbil_Count x Stance_Count) + Stance_Assault)] = False
    • Set StanceAbil_Active[((StanceAbil_Count x Stance_Count) + Stance_Skilled)] = False
    • Set StanceAbil_Active[((StanceAbil_Count x Stance_Count) + Stance_Fortress)] = True
    • -------- --------
    • -------- Do the initial setup of the unit into assault stance here or whenever the unit is created --------
    • -------- If multiple units of this class can exist then OldStance and NewStance need to be arrays indexed by player number --------
    • Set OldStance = Stance_Assault
    • Unit - For UNIT, Ability Shield Slam , Disable ability: True, Hide UI: True
    • Unit - For UNIT, Ability Shield Slam , Disable ability: True, Hide UI: True
  • Events
    • Unit - A unit starts the effect of an ability
  • Conditions
  • Actions
    • For each (Integer A) from 1 to Stance_Count do (Actions)
      • Loop - Actions
        • If (all conditions are true) then do (then actions) else do (else actions)
          • If - Conditions
            • (Ability being cast) equal to Stance[(Integer A)]
          • Then - Actions
            • Set NewStance = (Integer A)
            • For each (Integer B) from 1 to StanceAbil_Count do (Actions)
              • Loop - Actions
                • If (All conditions are true) then do (Then actions) Else do (Else actions)
                  • If - Conditions
                    • StanceAbil_Active[(((Integer B) x Stance_Count) + NewStance)] equal to true
                    • StanceAbil_Active[(((Integer B) x Stance_Count) + OldStance)] equal to false
                  • Then - Actions
                    • Unit - For (Triggering Unit), ability StanceAbil[(Integer B)]: Disable ability: false, Hide UI: false
                  • Else - Actions
                • If (All conditions are true) then do (Then actions) Else do (Else actions)
                  • If - Conditions
                    • StanceAbil_Active[(((Integer B) x Stance_Count) + NewStance)] equal to false
                    • StanceAbil_Active[(((Integer B) x Stance_Count) + OldStance)] equal to true
                  • Then - Actions
                    • Unit - For (Triggering Unit), ability StanceAbil[(Integer B)]: Disable ability: true, Hide UI: true
                  • Else - Actions
            • Set OldStance = NewStance
            • Custom script: exitwhen true //exit loop early, since there's no reason to check any more
          • Else - Actions
 
Level 2
Joined
Oct 16, 2017
Messages
16
  • For future reference: How To Post Your Trigger
  • Why remove and re-add the stance abilities instead of just enabling and disabling them like the others?
  • You could base your 3 stance swapping skills on Channel (Spells - Channel). I presume you used immo/mana/ww to show a buff on the UI bar for each stance? Since Channel does not confer a buff, these can instead be bestowed by dummy abilities with infinite duration or self-targeted auras.
  • The Clean Dummy trigger in your map is entirely unnecessary; give them no model and set to "can't raise, does not decay" and they'll instantly be removed on death anyway. (But maybe I misunderstand the purpose of this trigger because unit types are missing from it.)
  • Don't use the map init event for anything; if you put too much stuff under it you can crash the init thread and then not all of it will run. Used "elapsed game time" events at 0.10 or something instead.

Thanks for your response Pyro.
  • Apologies about the posts formatting with the trigger screenshot.
  • I remove and re-add the stance abilities as even with the order to disable windwalk/manashield/immolation they would not get deactivated. This resulted in the deactivate version of those abilities staying on the UI. With the removal I didn't have that problem, and as the 3 stances didn't have cooldowns I didn't see a problem here.
  • I used Immo/mana/ww for two versions, one is the buff like you said. The other was due to the abilities being Insta-Cast Self Buff's that didn't interrupt any of the units current orders. I would imagine that a dummy-channel spell would cause the units order to stop for a moment?
  • I'll have to look into the Clean Dummy Trigger to figure out what its purpose is in the main map.
  • I'll bear the map init triggers in mind, thanks for the advise.

Finally, thanks for the time put into the explanation and the workaround. I'll give it a go!
 
Last edited:
Level 2
Joined
Oct 16, 2017
Messages
16
Alright I gave it a go and I believe I got all the variables set to the correct type, and I believe I got the indexing correct for OldStance and NewStance.

Currently the hero will start off in AS and when swapped to SS will lose the ability charge and gain the ability Shattering Slam. The hero however will not lose the ability Second Wind.
Swapping back to AS after this will not remove Shattering Slam.
Similarly swapping to FS will turn off the ability Charge, and will give the ability Shattering Slam while retaining Second Wind instead of activating Shield Slam.
Swapping back to AS after this will not remove Shattering Slam.

Have I misinterpreted something in your previous post?

  • Stance System Setup
    • Events
      • Time - Elapsed game time is 0.50 seconds
    • Conditions
    • Actions
      • Set Stance_Count = 3
      • -------- --------
      • Set Stance_Assault = 1
      • Set Stance_Skilled = 2
      • Set Stance_Fortress = 3
      • -------- Assault --------
      • Set StanceAbil_Count = (StanceAbil_Count + 1)
      • Set StanceAbil[StanceAbil_Count] = Second Wind
      • Set StanceAbil_Active[((StanceAbil_Count + Stance_Count) + Stance_Assault)] = True
      • Set StanceAbil_Active[((StanceAbil_Count + Stance_Count) + Stance_Skilled)] = False
      • Set StanceAbil_Active[((StanceAbil_Count + Stance_Count) + Stance_Fortress)] = False
      • -------- --------
      • Set StanceAbil_Count = (StanceAbil_Count + 1)
      • Set StanceAbil[StanceAbil_Count] = Charge
      • Set StanceAbil_Active[((StanceAbil_Count + Stance_Count) + Stance_Assault)] = True
      • Set StanceAbil_Active[((StanceAbil_Count + Stance_Count) + Stance_Skilled)] = False
      • Set StanceAbil_Active[((StanceAbil_Count + Stance_Count) + Stance_Fortress)] = False
      • -------- Tactical --------
      • Set StanceAbil_Count = (StanceAbil_Count + 1)
      • Set StanceAbil[StanceAbil_Count] = Shattering Slam
      • Set StanceAbil_Active[((StanceAbil_Count + Stance_Count) + Stance_Assault)] = False
      • Set StanceAbil_Active[((StanceAbil_Count + Stance_Count) + Stance_Skilled)] = True
      • Set StanceAbil_Active[((StanceAbil_Count + Stance_Count) + Stance_Fortress)] = False
      • -------- --------
      • -------- Defensive --------
      • Set StanceAbil_Count = (StanceAbil_Count + 1)
      • Set StanceAbil[StanceAbil_Count] = Shield Slam
      • Set StanceAbil_Active[((StanceAbil_Count + Stance_Count) + Stance_Assault)] = False
      • Set StanceAbil_Active[((StanceAbil_Count + Stance_Count) + Stance_Skilled)] = False
      • Set StanceAbil_Active[((StanceAbil_Count + Stance_Count) + Stance_Fortress)] = True
      • -------- --------
  • Stance Execution
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
    • Actions
      • For each (Integer A) from 1 to Stance_Count, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Ability being cast) Equal to Stance[(Integer A)]
            • Then - Actions
              • Set NewStance[(Player number of (Owner of (Triggering unit)))] = (Integer A)
              • For each (Integer B) from 1 to StanceAbil_Count, do (Actions)
                • Loop - Actions
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • StanceAbil_Active[(((Integer B) x Stance_Count) + NewStance[(Player number of (Owner of (Triggering unit)))])] Equal to True
                      • StanceAbil_Active[(((Integer B) x Stance_Count) + OldStance[(Player number of (Owner of (Triggering unit)))])] Equal to False
                    • Then - Actions
                      • Unit - For (Triggering unit), Ability StanceAbil[(Integer B)], Disable ability: False, Hide UI: False
                    • Else - Actions
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • StanceAbil_Active[(((Integer B) x Stance_Count) + NewStance[(Player number of (Owner of (Triggering unit)))])] Equal to False
                      • StanceAbil_Active[(((Integer B) x Stance_Count) + OldStance[(Player number of (Owner of (Triggering unit)))])] Equal to True
                    • Then - Actions
                      • Unit - For (Triggering unit), Ability StanceAbil[(Integer B)], Disable ability: True, Hide UI: True
                    • Else - Actions
              • Set OldStance[(Player number of (Owner of (Triggering unit)))] = NewStance[(Player number of (Owner of (Triggering unit)))]
              • Custom script: exitwhen true
            • Else - Actions
 

Attachments

  • Stance Swap1.1.w3x
    60.7 KB · Views: 20
Status
Not open for further replies.
Top