• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

[GUI-friendly] Disable System (Stun,Silence,Disarm,Snare)

[GUI-friendly] Disable System - GDS v2.5.0


This system allows you to apply disabling (stun/silence/snare/etc.) effects to units. You may also set a duration to make your debuff temporary. Now supports a permanent disable time. Spell-shield (necklace) will absorb these effects.


Note: If you did not alter the "ultimates go through magic immunity" gameplay constant, then the stuns will affect magic-immune units. You will have to filter them out yourself if you don't want them to be stunned.


Note: Feel free to remove special effects from the buffs. They are there only to make testing easier.



1: A dummy unit with the stun ability is created at the start of the game
2: When using the system to stun a unit, the dummy will cast the stun spell on it
3: Whenever a unit is successfully stunned, a timer is created.
4:When that timer expires, everything is cleaned and the unit has the stun buff removed from it



How to import:
  1. Open World Editor. File -> Preferences -> Tick box for "Automatically create unknown variables (...)"
  2. Copy all GSS_ buffs to your map
  3. Copy all GSS_ abilities and set their buffs to the correct GSS_ buff
  4. Copy the unit: GSS_DUMMY
  5. Copy the Ability: GSS_DUMMY Invisible and give it to GSS_DUMMY unit in the Object Editor
  6. Copy the Trigger Category "G Stun System"
  7. Go to the trigger "GSS Setup" and set the variables correctly (follow instructions in trigger comment)



How to use:

Note: Disarm effects do not stack with each other, they will overwrite each other.

Note: Silence does not affect buildings. However, Supersilence will disable their production.


The system comes with integer variables that you can use to more intuitively set the effect type. Alternatively, you can use the following IDs:

IDEffectIDEffectIDEffectIDEffectIDEffect
0Stun1Silence2Disarm (ranged)3Disarm (meele)4Disarm (both)
5Ensnare6Supersilence7Sleep8Entangle9Ethereal


GDS Main Modifier:
This trigger allows you to set conditions that are checked before applying an effect. This allows you to make things like "Stun Resistance", "Silence Resistance" , etc. This also allows you to define different behavior for heroes (like in default wc3). If you have no need for something like this, you can just delete the trigger and always run "GDS Main" instead.

To ignore any conditions that you set in the "GDS Main Modifier" Trigger, simply run "GDS Main" instead. (Allows you to easily make "Universal" abilities that ignore any resistances you may have set.)

You may want to convert it to JASS to make it faster, more readable and to allow for more abstraction (custom functions).

(might add custom events to replace this in the future)​
  • In this example, all Hero units will only be affected for half the duration.
  • Footmen will be stunned (only stunned) for double the duration.
  • If a minimum duration has been defined, makes sure it is applied and resets it.
  • GDS Main Modifier Example
    • Events
    • Conditions
    • Actions
      • Custom script: local real storeDur = udg_GDS_Duration
      • -------- - --------
      • -------- Declare your preload conditions here --------
      • -------- - --------
      • -------- General Modifications --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (GDS_Target is A Hero) Equal to True
        • Then - Actions
          • Set GDS_Duration = (GDS_Duration / 2.00)
          • Game - Display to (All players) the text: (String(GDS_Duration))
        • Else - Actions
      • -------- Effect Specific Modifications --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • GDS_Type Equal to GDS_cSTUN
        • Then - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Unit-type of GDS_Target) Equal to Footman
            • Then - Actions
              • Set GDS_Duration = (GDS_Duration x 2.00)
            • Else - Actions
        • Else - Actions
      • -------- Final Modifications --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • GDS_Duration Less than zEXAMPLE_MinDuration
        • Then - Actions
          • Set GDS_Duration = zEXAMPLE_MinDuration
          • Set zEXAMPLE_MinDuration = 0.00
          • Game - Display to (All players) the text: (String(GDS_Duration))
        • Else - Actions
      • -------- - --------
      • -------- Run Main after your conditions have been checked --------
      • -------- - --------
      • Trigger - Run GDS Main <gen> (ignoring conditions)
      • -------- - --------
      • -------- Restore duration to old duration (for unit group loops) --------
      • -------- - --------
      • Custom script: set udg_GDS_Duration = storeDur
System Actions:

Apply Effect

Reduce Remaining Time

Get Remaining Time

Apply Effect (stacking)

Remove Effect

Remove Effect(2)

Apply Effect (permanent)

After-Application Event


Affect a unit:
  • Set GDS_Type = integer_for_intended_effect
  • Set GDS_Target = your_unit
  • Set GDS_Duration = positive_real
  • Trigger - Run GDS Main Modifier <gen> (ignoring conditions)

Reduce an effect's duration for a unit:
  • Set GDS_Type = your_type
  • Set GDS_Target = your_unit
  • Set GDS_Duration = negative_real
  • Trigger - Run GDS Main <gen> (ignoring conditions)
It's simple, just supply a negative duration. Remember to use "GDS Main" and not "GDS Main Modifier".
For another example, see "Unyielding Resolve" example usage below.
Note: If remaining time becomes less than or equal to 0 after reduction, the effect is immediately removed from the unit

Get remaining effect time:
  • Set GDS_Type = integer_for_intended_effect
  • Set GDS_Duration = 0.00
  • Set GDS Target = your_unit
  • Trigger - Run GDS Main <gen> (ignoring conditions)
The variable GDS_Remaining is the remaining duration. (0 for units that weren't stunned)

Affect a unit (stacking time):
  • Set GDS_Type = integer_for_intended_effect
  • Set GDS Target = your_unit
  • Set GDS_Duration = 0.00
  • Trigger - Run GDS Main <gen> (ignoring conditions)
  • Set GDS_Duration = GSS_Remaining + positive_real
  • Trigger - Run GDS Main Modifier <gen> (ignoring conditions)

Remove effect from a unit:
JASS:
'Simply remove the effect buff (GDS_BUFF[your_effect]) from the unit. The timer and hashtable
will be cleaned up when the timer expires. Having a running timer and hashtable data for a unit that is
not affected will not cause any problems for the system. Still, if you want cleanup to be instant, use the
method to the right:'

Remove effect from a unit: (instant cleanup)
  • Set GDS_Type = integer_for_intended_effect
  • Set GDS_Target = your_unit
  • Set GDS_Duration = 0.00
  • Unit - Remove GDS_BUFF[GDS_Type] buff from your_unit
  • Trigger - Run GDS Main <gen> (ignoring conditions)

Note: Permanent effects will overwrite any temporary effects, and will set GDS_Reamining time to -1.
Affect a unit (permanently):
  • Set GDS_Type = integer_for_intended_effect
  • Set GDS Target = your_unit
  • Set GDS_Permanent = true
  • Trigger - Run GDS Main <gen> (ignoring conditions)

What is this?:
The unit won't have the disable debuff instantly, it will take somewhere between 0.005 and 0.007 seconds for the unit to be affected. So if you wanted to deal more magic damage by banishing a unit, you couldn't do it just after you executed the Main function. You would have to make a trigger that responds to the custom event: GDS_DebuffEvent becomes Equal to 9.00 (9 is the ID for banish)

To enable an after-application event:
  • Set GDS_RegisterDisable = True
You can set this to True only when you need it and have it be false otherwise :) It's True by default in the testmap for testing purposes.

To respond to an event:
  • Event Usage
    • Events
      • Game - GDS_DebuffEvent becomes Equal to 0.00
      • Game - GDS_DebuffEvent becomes Equal to 1.00
      • (...)
    • Conditions
    • Actions
The Number should be equal to the ID of the debuff you want to detect.




Test Map:

Commands:
-stun <duration> (up to 4 digits) => Stun selected units for <duration>
asd => Stun all units in the map for last used <duration>
show => Show the remaining stun duration for selected units
remove => Removes stun from selected units
-type <integer> => change effect type

Example Usage:

Unyielding Resolve

Unleash Madness

Holy Retribution


Whenever the Tauren Chieftain takes damage, reduce the duration of stun by 5 seconds.

source.gif


  • Unyielding Resolve
    • Events
      • Unit - Tauren Chieftain 0177 <gen> Takes damage
    • Conditions
      • (Damage taken) Greater than 0.00
      • ((Triggering unit) has buff GDS_BUFF[GDS_cSTUN]) Equal to True
    • Actions
      • Set GDS_Type = GDS_cSTUN
      • Set GDS_Target = Tauren Chieftain 0177 <gen>
      • -------- Show time before damage is taken --------
      • Set GDS_Duration = 0.00
      • Trigger - Run GDS Main <gen> (ignoring conditions)
      • Game - Display to (All players) the text: (String(GDS_Remaining))
      • -------- Reduce time for stun --------
      • Set GDS_Duration = -5.00
      • Trigger - Run GDS Main <gen> (ignoring conditions)
      • -------- Show time after damage is taken --------
      • Set GDS_Duration = 0.00
      • Trigger - Run GDS Main <gen> (ignoring conditions)
      • Game - Display to (All players) the text: (String(GDS_Remaining))

Unleash an uncontrollable ammount of arcane power, causing random status effects to nearby enemy units for 5 seconds.

  • Unleash Madness
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Unleash Madness
    • Actions
      • Custom script: local real storeDur = udg_GDS_Duration
      • Custom script: local integer storeTyp = udg_GDS_Type
      • Set GDS_Duration = 5.00
      • Unit Group - Pick every unit in (Units within 500.00 of (Position of (Triggering unit)) matching ((((Owner of (Matching unit)) is an enemy of (Owner of (Triggering unit))) Equal to True) and (((Matching unit) is A structure) Equal to False))) and do (Actions)
        • Loop - Actions
          • Set GDS_Type = (Random integer number between 0 and 9)
          • Set GDS_Target = (Picked unit)
          • Trigger - Run GDS Main Modifier <gen> (ignoring conditions)
      • Custom script: set udg_GDS_Duration = storeDur
      • Custom script: set udg_GDS_Type = storeTyp

Stun a target enemy units for 2 seconds. This stun can't have it's duration reduced at cast time (ignores stun resistance, but something like Unyielding Resolve would work).

  • Minimum Duration Stun
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Holy Retribution
    • Actions
      • Set GDS_Type = GDS_cSTUN
      • Set GDS_Duration = 2.00
      • Set zEXAMPLE_MinDuration = 2.00
      • Set GDS_Target = (Target unit of ability being cast)
      • Trigger - Run GDS Main Modifier Example <gen> (ignoring conditions)




Code:
  • GDS Setup
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Hashtable - Create a hashtable
      • Set GDS_Hashtable = (Last created hashtable)
      • Custom script: call SaveLocationHandle(udg_GDS_Hashtable, 2 , 99 , GetRectCenter(bj_mapInitialPlayableArea))
      • Set GDS_cSTUN = 0
      • Set GDS_cSILENCE = 1
      • Set GDS_cDISARM_R = 2
      • Set GDS_cDISARM_M = 3
      • Set GDS_cDISARM_B = 4
      • Set GDS_cSNARE = 5
      • Set GDS_cSUPERSILENCE = 6
      • Set GDS_cSLEEP = 7
      • Set GDS_cENTANGLE = 8
      • Set GDS_cETHEREAL = 9
      • -------- - --------
      • -------- SET THE CORRECT PARAMETERS HERE --------
      • -------- - --------
      • Set GDS_ABIL[GDS_cSTUN] = GDS_STUN
      • Set GDS_BUFF[GDS_cSTUN] = GDS_STUN (Pause)
      • -------- - --------
      • Set GDS_ABIL[GDS_cSILENCE] = GDS_SILENCE
      • Set GDS_BUFF[GDS_cSILENCE] = GDS_SILENCE
      • -------- - --------
      • Set GDS_ABIL[GDS_cDISARM_R] = GDS_DISARM_R
      • Set GDS_BUFF[GDS_cDISARM_R] = GDS_DISARM_R
      • -------- - --------
      • Set GDS_ABIL[GDS_cDISARM_M] = GDS_DISARM_M
      • Set GDS_BUFF[GDS_cDISARM_M] = GDS_DISARM_M
      • -------- - --------
      • Set GDS_ABIL[GDS_cDISARM_B] = GDS_DISARM_BOTH
      • Set GDS_BUFF[GDS_cDISARM_B] = GDS_DISARM_BOTH
      • -------- - --------
      • Set GDS_ABIL[GDS_cSNARE] = GDS_SNARE
      • Set GDS_BUFF[GDS_cSNARE] = GDS_SNARE
      • -------- - --------
      • Set GDS_ABIL[GDS_cSUPERSILENCE] = GDS_SUPERSILENCE
      • Set GDS_BUFF[GDS_cSUPERSILENCE] = GDS_SUPERSILENCE
      • -------- - --------
      • Set GDS_ABIL[GDS_cSLEEP] = GDS_SLEEP
      • Set GDS_BUFF[GDS_cSLEEP] = GDS_SLEEP
      • -------- - --------
      • Set GDS_ABIL[GDS_cENTANGLE] = GDS_ENTANGLE
      • Set GDS_BUFF[GDS_cENTANGLE] = GDS_ENTANGLE
      • -------- - --------
      • Set GDS_ABIL[GDS_cETHEREAL] = GDS_ETHEREAL
      • Set GDS_BUFF[GDS_cETHEREAL] = GDS_ETHEREAL
      • -------- - --------
      • For each (Integer A) from 0 to 9, do (Actions)
        • Loop - Actions
          • Unit - Create 1 GDS_Dummy for Neutral Passive at (Load 99 of 2 in GDS_Hashtable) facing Default building facing degrees
          • Unit - Add GDS_ABIL[(Integer A)] to (Last created unit)
          • Set GDS_DUMMY[(Integer A)] = (Last created unit)
      • Custom script: call RemoveLocation(LoadLocationHandle(udg_GDS_Hashtable, 2, 99))
      • -------- - --------
      • -------- YOU SHOULDN'T TOUCH ANYTHING BELOW THIS --------
      • -------- - --------
      • -------- Order Strings --------
      • Set GDS_ORDERS[0] = thunderbolt
      • Set GDS_ORDERS[1] = soulburn
      • Set GDS_ORDERS[2] = drunkenhaze
      • Set GDS_ORDERS[3] = drunkenhaze
      • Set GDS_ORDERS[4] = drunkenhaze
      • Set GDS_ORDERS[5] = ensnare
      • Set GDS_ORDERS[6] = doom
      • Set GDS_ORDERS[7] = sleep
      • Set GDS_ORDERS[8] = entanglingroots
      • Set GDS_ORDERS[9] = banish
      • -------- - --------
      • Player Group - Make (All players) treat (Player group((Owner of GDS_DUMMY[0]))) as an Neutral with shared vision
      • Set GDS_DebuffEvent = 0.40
      • Custom script: set udg_GDS_zMIN = 0.006
      • Skip remaining actions
      • Set GDS_Duration = 0.00
      • Set GDS_Remaining = 0.00
      • Set GDS_Target = No unit
      • Set GDS_Type = 0
      • Set GDS_zMIN = 0.00
      • Set GDS_Permanent = False
      • Set GDS_RegisterDisable = False
JASS:
function GDSDebuffApplied takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local integer tHandle = GetHandleId(t)
    local integer stunType = LoadInteger(udg_GDS_Hashtable, tHandle , 1)
    local unit u = LoadUnitHandle(udg_GDS_Hashtable, tHandle , 0)

    if GetUnitAbilityLevel( u , udg_GDS_BUFF[stunType]) != 0 then
      
        call FlushChildHashtable(udg_GDS_Hashtable, GetHandleId(t))
        call PauseTimer(t)
        call DestroyTimer(t)

        set udg_GDS_DebuffEvent = stunType
        set udg_GDS_Target = u
        set udg_GDS_DebuffEvent = 0.5
    else
        call TimerStart(t, udg_GDS_zMIN, false, function GDSDebuffApplied) 
    endif
    set u = null
    set t = null
endfunction

function GDSDebuffEnd takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local integer tHandle = GetHandleId(t)
    local integer stunType = LoadInteger(udg_GDS_Hashtable, tHandle , 2)
    local unit u = LoadUnitHandle(udg_GDS_Hashtable, tHandle , 0)
    local integer uHandle = LoadInteger(udg_GDS_Hashtable, tHandle , 1)

    call UnitRemoveAbility(u, udg_GDS_BUFF[stunType])

    call FlushChildHashtable(udg_GDS_Hashtable, GetHandleId(t))
    call PauseTimer(t)
    call DestroyTimer(t)
    call RemoveSavedHandle(udg_GDS_Hashtable, uHandle , stunType)

    set u = null
    set t = null
endfunction

function GDSMain takes nothing returns nothing
    local timer t
    local timer timerOld = LoadTimerHandle(udg_GDS_Hashtable, GetHandleId(udg_GDS_Target) , udg_GDS_Type )
    local real duration = udg_GDS_Duration
    local boolean hadTimer = timerOld != null

  
    set udg_GDS_Remaining = TimerGetRemaining(timerOld)
//Check if user wants a permanent debuff
    if udg_GDS_Permanent then
        set udg_GDS_Permanent = false
        if hadTimer then

            call FlushChildHashtable(udg_GDS_Hashtable, GetHandleId(timerOld))
            call PauseTimer(timerOld)
            call DestroyTimer(timerOld)
            call RemoveSavedHandle(udg_GDS_Hashtable, GetHandleId(udg_GDS_Target) , udg_GDS_Type)

            set timerOld = null
        else
            if IssueTargetOrder( udg_GDS_DUMMY[udg_GDS_Type], udg_GDS_ORDERS[udg_GDS_Type], udg_GDS_Target ) or GetUnitAbilityLevel(udg_GDS_Target , udg_GDS_BUFF[udg_GDS_Type]) != 0 then
                set udg_GDS_Remaining = -1 //-1 for infinite duration
            else
                set udg_GDS_Remaining = 0
            endif
        endif

        if udg_GDS_RegisterDisable then
            set t = CreateTimer()
            call SaveUnitHandle(udg_GDS_Hashtable, GetHandleId(t) , 0 , udg_GDS_Target)
            call SaveInteger(udg_GDS_Hashtable , GetHandleId(t) , 1 , udg_GDS_Type)
            call TimerStart(t, udg_GDS_zMIN, false, function GDSDebuffApplied)
            set t = null              
        endif

        return
    endif
//Check if user wants to reduce duration of stun (check for negative duration)
    if duration < -udg_GDS_zMIN and udg_GDS_Remaining > udg_GDS_zMIN then  //Check for reduction
        if -duration > udg_GDS_Remaining then  //Check if reduction goes below 0
            call UnitRemoveAbility(udg_GDS_Target , udg_GDS_BUFF[udg_GDS_Type])
            set duration = 0
        else
            set duration = udg_GDS_Remaining - duration //Change duration so it passes the checks
        endif
    endif

//Check if the desired duration is higher than remaining time
    if  udg_GDS_Remaining < duration and duration > udg_GDS_zMIN and hadTimer then

        if hadTimer then
            set t = timerOld
        else
            set t = CreateTimer()
            set timerOld = null
        endif
    else
        //Check if unit has buff, clean hashtable, destroy timer and set remaining time to 0
        if GetUnitAbilityLevel(udg_GDS_Target, udg_GDS_BUFF[udg_GDS_Type]) == 0 then

            call FlushChildHashtable(udg_GDS_Hashtable, GetHandleId(timerOld))
            call PauseTimer(timerOld)
            call DestroyTimer(timerOld)
            call RemoveSavedHandle(udg_GDS_Hashtable, GetHandleId(udg_GDS_Target) , udg_GDS_Type)

            set timerOld = null

            if duration < udg_GDS_zMIN then
                set udg_GDS_Remaining = 0
                return
            endif

            set t = CreateTimer()

        else

            if hadTimer then
                set timerOld = null
            else          
                set udg_GDS_Remaining = -1
            endif
            return      
        endif    
    endif


//Check was successful, proceed to attempt to stun
    if not IssueTargetOrder( udg_GDS_DUMMY[udg_GDS_Type], udg_GDS_ORDERS[udg_GDS_Type], udg_GDS_Target ) and GetUnitAbilityLevel(udg_GDS_Target , udg_GDS_BUFF[udg_GDS_Type]) == 0 then
        set timerOld = null
        set udg_GDS_Remaining = 0
        return //unable to stun, do nothing
    endif
//Check again for duration reduction (negative duration)  
    if udg_GDS_Duration < 0 then
        set duration = duration + 2*udg_GDS_Duration //Change duration to reduced duration
    endif
//Save Hashtable values only if a new timer has been created  
    if not hadTimer then
        call SaveUnitHandle(udg_GDS_Hashtable, GetHandleId(t) , 0 , udg_GDS_Target)
        call SaveInteger(udg_GDS_Hashtable , GetHandleId(t) , 1 , GetHandleId(udg_GDS_Target))
        call SaveInteger(udg_GDS_Hashtable , GetHandleId(t) , 2 , udg_GDS_Type)
        call SaveTimerHandle(udg_GDS_Hashtable, GetHandleId(udg_GDS_Target) , udg_GDS_Type , t)
    endif
  

    call TimerStart(t, duration , false, function GDSDebuffEnd)
  
  
    set udg_GDS_Remaining = duration
  

    if udg_GDS_RegisterDisable then
        set t = CreateTimer()
        call SaveUnitHandle(udg_GDS_Hashtable, GetHandleId(t) , 0 , udg_GDS_Target)
        call SaveInteger(udg_GDS_Hashtable , GetHandleId(t) , 1 , udg_GDS_Type)
        call TimerStart(t, 2*udg_GDS_zMIN, false, function GDSDebuffApplied)              
    endif
  
    set timerOld = null
    set t = null
  
endfunction



//===========================================================================
function InitTrig_GDS_Main takes nothing returns nothing
    set gg_trg_GDS_Main = CreateTrigger(  )
    call TriggerAddAction( gg_trg_GDS_Main, function GDSMain )
endfunction

Updates:

x.y.z
x => Code Changes to Setup AND Main
y => Code changes to Setup or Main
z => Changes to test map
v1.0.0 - Initial Release
v1.1.0 - Changed code in order to support Reincarnation
v2.0.0 - Post
v2.1.0 - Post
v2.2.0 - Post
v2.2.1 - Test Map commands are now displayed in the test map.
v2.3.0 - Added method of duration reduction and added Unyielding Resolve example
v2.3.1 - Fixed Test Map "Stun all" trigger
v2.3.2 - Fixed "StunEnd" function and added Unleash Madness example
v2.3.3 - Post
v2.4.0 - Support for invisible units and permanent duration
v2.4.1 - Changes to description and small changes to test map & added stun to map name
v2.5.0 - Post

Special Thanks:
-Menag: Made a WurstScript system which inspired me to make this one for GUI
-Reventhous: Thought of name "Disable" instead of "Stun"
-Tasyen: Gave the idea for the intuitive variables with the name of the effects.
Contents

Guhun's Stun & Disable System - GDS (Map)

Reviews
Tank-Commander
The system is simple, short well made and a lot of effort went into building the test map. There are clear useful applications of the system and there are no notable flaws with it for a GUI-Friendly disable system that I could see
We already have a bunch of these...

But they work differently, from what I've seen, and don't have the option to get elapsed time. They also require a Unit Indexer, which this does not, and are based on another ability that can't stun buildings (but bypasses spell shield, which blocks this). Anyway, this is getting updated to something a lot more useful soon. (thought of it just after posting this :S ).
 
Will you work with the SilenceEx approach? Because I think it was good to have all these stuff working with if, if combined.

What do you mean by taking that approach? :S

I'll add diferent silences based on the awesome knowledge providade by that guide, but I don't know about adding complex things like permanent silence of an ability :S
 
What do you mean by taking that approach? :S
I used an other approach (cargo ability) here, which works fine as standalone. But It only can handle disabling attack, for example.
And if I was about to add more possibilities, like you probably want, I said that I think it's probably good to work with the SilenceEx approach explained in the linked thread.
 
I used an other approach (cargo ability) here, which works fine as standalone. But It only can handle disabling attack, for example.
And if I was about to add more possibilities, like you probably want, I said that I think it's probably good to work with the SilenceEx approach explained in the linked thread.

Aaaah. I was going to use drunken haze to disable attacks, since it's basically the same as thunderbolt :S Though drunken haze doesn't stack with itself, so if I want to disable both attacks, I can use your system and use drunken haze for only 1 type of attack (ranged or meele)
 
GSS Clean Death should be in GSS Main trg.

Well, it's not really needed because all the leaks would get cleared eventually when the timer expired, it's just there as a small performance boost :s

Even if I moved it to main, it would still require the creation of a trigger, so the amount of memory used by your map would be the same :s Isn't it better that it stay more explicit?

This system is all about disabling target, I think you should name this system to "[GUI-friendly] Disable system".
Hmmm, I like that name actually. Still think people will search for Stun system more, pity there aren't any tags for the spell section =/

But I guess I'll change the name, since it's more fitting :)


Having a GUI system that allows you to stun, snare, silence, etc would be awesome.

Yeah, I'm excited to get this system in a really good/useful state.

UPDATE:
-Version 2.1.0:

-Name changed from Stun System to Disable System
-Added GDS Main Modifier Trigger
-Fixed SUPERSILENCE not working on aerial units
 
Last edited:
Nice System had recently a similar idea.

You could make it more easy to use by implementing constant integers which point directly to the specific effect. That would make copying more stricted and avoid constantly switching to the GDS trigger to look for the Right index of the wanted effect.


Do you intent to inser the other Disables too?
  • sleep
  • hex
  • entangled (Nightelf Spell - Immobile + Disarm)
  • cyclone (Nightelf Spell - Stun + Invurnable)
  • Banish (Making Ethernal, Bloodmage Spell)
 
Last edited:
Level 10
Joined
Aug 21, 2010
Messages
316
Well, it's not really needed because all the leaks would get cleared eventually when the timer expired, it's just there as a small performance boost :s

Even if I moved it to main, it would still require the creation of a trigger, so the amount of memory used by your map would be the same :s Isn't it better that it stay more explicit?

The point is, one system, one trigger nothing else
You can check whether the unit is dead directly into the main code.
GSS Clean Death trigger is redundant.
 
Last edited:
Nice System had recently a similar idea.

You could make it more easy to use by implementing constant integers which point directly to the specific effect. That would make copying more stricted and avoid constantly switching to the GDS trigger to look for the Right index of the wanted effect.


Do you intent to inser the other Disables too?
  • sleep
  • hex
  • entangled (Nightelf Spell - Immobile + Disarm)
  • cyclone (Nightelf Spell - Stun + Invurnable)
  • Banish (Making Ethernal, Bloodmage Spell)

I was going to add those, except Hex. Because you can't really choose the model for hex, so I don't know how useful that would be for most people :S


What you suggested would result in too many triggers, I think. How about a function that converts a string to an integer, if someone really has trouble remembering? Like "call GDSType("stun")" will set GDS_Type to 0? Would be better to just write it down or write it in a text file that's open :S

And what do you mean that it would make copying more stricted?

The point is, one system, one trigger nothing else
You can check whether the unit is dead directly into the main code.
GSS Clean Death trigger is redundant.

I dunno about the death thing, now. It's not really that useful, tbh. I just noticed it doesn't check for every negative effect. I'll think of something.

I believe the recent memory hack got built in natives for this, which means this can be done with one line.

Well, the memory hack is against EULA and TOS (not that I really have an issue with that, but some people might). And I'm pretty sure it can't be pulled off using the normal editor (it's pretty complicated to use without THs NewGen) and probably will get patched by the Blizzard Classics team =/
 
I didn't said using Strings. What i suggested is that you make for each effect an integer variable which has the right index and its name contains the effect.
This allows it to select with the predifined WE set action pretty easy.
Something like this.
  • Nahkampf-Initialisierung
    • Ereignisse
      • Map initialization
    • Bedingungen
    • Aktionen
      • Set GDS_CONSTANT_STUN = 0
      • Set GDS_CONSTANT_SILENCE = 1
      • Set GDS_CONSTANT_DISARM_R = 2
      • Set GDS_CONSTANT_DISARM_M = 3
      • Set GDS_CONSTANT_DISARM_BOTH = 4
      • -------- The later usage --------
      • Set GDS_Type = GDS_CONSTANT_SILENCE
Indeed Hex will look wierd with the not reducing expiring time which is shown in the unit Interface.

Stricted
If you use this constants inside your init-Trigger setuping the right spells will be pretty clear if copied into map allready containing allot of spells which might showing allready made spells.
  • set GSS_ABIL[GDS_CONSTANT_STUN] = GSS_STUN
  • set GSS_BUFF[GDS_CONSTANT_STUN] = GSS_STUN (Pause)
 
I didn't said using Strings. What i suggested is that you make for each effect an integer variable which has the right index and its name contains the effect.
This allows it to select with the predifined WE set action pretty easy.
Something like this.
  • Nahkampf-Initialisierung
    • Ereignisse
      • Map initialization
    • Bedingungen
    • Aktionen
      • Set GDS_CONSTANT_STUN = 0
      • Set GDS_CONSTANT_SILENCE = 1
      • Set GDS_CONSTANT_DISARM_R = 2
      • Set GDS_CONSTANT_DISARM_M = 3
      • Set GDS_CONSTANT_DISARM_BOTH = 4
      • -------- The later usage --------
      • Set GDS_Type = GDS_CONSTANT_SILENCE
Indeed Hex will look wierd with the not reducing expiring time which is shown in the unit Interface.

Stricted
If you use this constants inside your init-Trigger setuping the right spells will be pretty clear if copied into map allready containing allot of spells which might showing allready made spells.
  • set GSS_ABIL[GDS_CONSTANT_STUN] = GSS_STUN
  • set GSS_BUFF[GDS_CONSTANT_STUN] = GSS_STUN (Pause)

Aaaah, now I get what you mean.

Well, that's going to create a lot of variables, but it IS pretty useful. I'll post an update soon.

UPDATE: v2.2.0
-Added Sleep, Entangle and Ethereal effects
-Created integer variables for each effect to increase QoL and readability
-Moved old setup and GDS Clean Death to obsolete folder
-Changed ability, buff and Dummy names from GSS to GDS

UPDATE: v2.3.0
-Added method of reducing remaining effect time
-Created an example usage: Unyielding Resolve
 
Last edited:
I like this System and tried it out, again, found 2 problems:
  1. System does not affect Invisible Units. (You could solve that by changing the dummie casters owner to the same as the Target's one) EDIT: Or by Allowing Vision for the Dummie Caster owner over the Target.
  2. It Leaks 10 Locations in your Init-Trigger: at the Creation of the dummie casters.
 
Last edited:
I like this System and tried it out, again, found 2 problems:
  1. System does not affect Invisible Units. (You could solve that by changing the dummie casters owner to the same as the Target's one) EDIT: Or by Allowing Vision for the Dummie Caster owner over the Target.
  2. It Leaks 10 Locations in your Init-Trigger: at the Creation of the dummie casters.

Oh, I know about it not affecting invisible units and have been working on fixing that (well that was easy to fix) and other things.

I'm uploading it now with the new features (possible permanent duration and an event that runs just after a unit dies) and with that invisible unit bug fixed.


About the leaked locations, I didn't want to add a new point variable just to stop 10 non-repeating leaks :S Don't know how much memory a location leak takes, but it's definitely minimal. EDIT: Nvm, just thought of a way to fix that.


UPDATE: 2.4.0

-Support for permanent duration added
-Support to get the time just after an effect is applied (time will likely be less than 0.006 seconds)

-Made DUMMY unit invisible so it would not reveal a piece of the map when casting the ability.
-Fixed a bug that prevented invisible units from being affected (requires that owner of GDS_DUMMY units have vision from all players.)
-Removed location leaks in setup trigger
-Added advanced GDS Main Modifer example.
-Expanded test map to 256x256 to test stunning units that are very far away from the GDS_DUMMY units.
-Added test map command <permanent> to toggle that the next stun be permanent. Call this command again to untoggle.
-Added Example for Event usage (well, it simply sends some game messages)
 
Last edited:
Version 2.5.0:

-Fixed an error when cleaning Hashtable: changed RemoveSavedInteger to RemoveSavedHandle in GDSDebuffEnd function
-Removed Debug message when a stun fails
-Updated code in description and changed title

I recommend users who have downloaded a previous version and imported it into their map to download this newest version and import it instead, as the error described above could cause memory leaks.
 
Level 7
Joined
Feb 9, 2021
Messages
301
You can alter the FX used by the buffs using the Object Editor, it doesn't require any coding.

The problem is this changes FX for every spell. Therefore, it is impossible to have different FXs for a frozen unit and stunned unit. Essentially, they are both stunned but require different FX. Same can be applied to other buffs.

It would be great if it was possible to customise the buff for each spell. Otherwise, if a user wants to freeze a unit, the unit will have a buff of "stunned", which does not look nice. This problem also might appear in some other instances.
 
Last edited:
The problem is this changes FX for every spell. Therefore, it is impossible to have different FXs for a frozen unit and stunned unit. Essentially, they are both stunned but require different FX. Same can be applied to other buffs.

It would be great if it was possible to customise the buff for each spell. Otherwise, if a user wants to freeze a unit, the unit will have a buff of "stunned", which does not look nice. This problem also might appear in some other instances.

That's exactly why I recommend that the buff FX be removed in the description, because in most cases the FX should be controlled by the spell itself, not by the stun debuff. They are only included in the map because it makes testing easier.

Adding an FX for every occasion is beyond the scope of this system, as it only handles the initial application of the stun debuff itself and the total stun duration for each unit. It does not keep track of each individual stun application. That is better handled by a dedicated buff system (which is the main reason for which permanent stuns were added, as those systems generally use their own timers and would only use this system to cast the stunning abilities) or by the spell itself.

In the case of freezing a unit instead of stunning it, you might be able to get around it by adding a new stun type and a new ability and buff for it. Though this doesn't really scale very well, if you need a lot of different stun types it might be better to just use a dedicated buff system to avoid flooding your object editor.
 
Level 7
Joined
Feb 9, 2021
Messages
301
That's exactly why I recommend that the buff FX be removed in the description, because in most cases the FX should be controlled by the spell itself, not by the stun debuff. They are only included in the map because it makes testing easier.

Adding an FX for every occasion is beyond the scope of this system, as it only handles the initial application of the stun debuff itself and the total stun duration for each unit. It does not keep track of each individual stun application. That is better handled by a dedicated buff system (which is the main reason for which permanent stuns were added, as those systems generally use their own timers and would only use this system to cast the stunning abilities) or by the spell itself.

In the case of freezing a unit instead of stunning it, you might be able to get around it by adding a new stun type and a new ability and buff for it. Though this doesn't really scale very well, if you need a lot of different stun types it might be better to just use a dedicated buff system to avoid flooding your object editor.

Thanks for your answers. It seems like I need to look at this topic in more detail. As I am just a beginner, I thought you might help me to guide me in the right direction. In my map, I want to have items that reduce negative buffs durations (stuns, charms, slows and etc)[similar to MR shoes in LoL], and I want to have items that can remove certain negative effects from the unit (either casted by an ally to a friendly unit or casted by stunned/charmed/slowed unit itself (similar to QSS in LoL). What is the best way to approach this? Maybe you can recommend some systems posted or something else.

Another question I have is I have a spell that should deal damage more to frozen units (doesn't matter who froze the unit). Is it better to track frozen units through buffs or add them to a group or some other way?

Thank you in advance. I would really appreciate your advice.
 


That really depnends on how complex you want your systems to be. If it's something like Divinty OS or Pokemon, where most status effects are standardized, then this system should work pretty well. You would just need to add a new stun ability for frozen units (just copy the stun ability and buff from the object editor and then change the name/FX) and for whatever new status effects you need.

An example of a non-standardized game is WoW, in which Rogues have two stuns: Cheap Shot and Kidney Shot. Each one can be individually removed, they don't share the same "stunned" buff. If status effects are not standardized, then you will probably need a dedicated buff system (I'm not very familiar with any of the ones available, as I generally use my own). This is not the type of scenario this system was meant to handle by itself (though you could still use it just to apply the actual stun using permanent stuns and then control the duration with individual buffs).

As for a unit removing disabling effects from itself, that's not really possible, as you can't issue orders while the unit is unable to act. The best you could do is some sort of custom UI solution that doesn't depend on the unit receiving orders, just on the player clicking a button.

To deal more damage to frozen units, I would use a standardized frozen debuff. Then when casting that ability you just need to check for the presence of that buff.
 
Level 7
Joined
Feb 9, 2021
Messages
301
That really depnends on how complex you want your systems to be. If it's something like Divinty OS or Pokemon, where most status effects are standardized, then this system should work pretty well. You would just need to add a new stun ability for frozen units (just copy the stun ability and buff from the object editor and then change the name/FX) and for whatever new status effects you need.

An example of a non-standardized game is WoW, in which Rogues have two stuns: Cheap Shot and Kidney Shot. Each one can be individually removed, they don't share the same "stunned" buff. If status effects are not standardized, then you will probably need a dedicated buff system (I'm not very familiar with any of the ones available, as I generally use my own). This is not the type of scenario this system was meant to handle by itself (though you could still use it just to apply the actual stun using permanent stuns and then control the duration with individual buffs).

As for a unit removing disabling effects from itself, that's not really possible, as you can't issue orders while the unit is unable to act. The best you could do is some sort of custom UI solution that doesn't depend on the unit receiving orders, just on the player clicking a button.

To deal more damage to frozen units, I would use a standardized frozen debuff. Then when casting that ability you just need to check for the presence of that buff.


I think I will need different stun buffs. I have a MOBA, and I use stun to stop casters from using other abilities and etc. A follow up on frozen debuff. What spell can I base it off? I can't use bolt because of the same orderID.
 
I think I will need different stun buffs. I have a MOBA, and I use stun to stop casters from using other abilities and etc. A follow up on frozen debuff. What spell can I base it off? I can't use bolt because of the same orderID.
You can use bolt, the system creates one dummy for each ability to avoid order id issues (though I guess to be as efficient as possible it should use just one dummy and then add the ability when needed, didn't think of that at the time :peasant-confused:)
 
Level 7
Joined
Feb 9, 2021
Messages
301
That really depnends on how complex you want your systems to be. If it's something like Divinty OS or Pokemon, where most status effects are standardized, then this system should work pretty well. You would just need to add a new stun ability for frozen units (just copy the stun ability and buff from the object editor and then change the name/FX) and for whatever new status effects you need.

An example of a non-standardized game is WoW, in which Rogues have two stuns: Cheap Shot and Kidney Shot. Each one can be individually removed, they don't share the same "stunned" buff. If status effects are not standardized, then you will probably need a dedicated buff system (I'm not very familiar with any of the ones available, as I generally use my own). This is not the type of scenario this system was meant to handle by itself (though you could still use it just to apply the actual stun using permanent stuns and then control the duration with individual buffs).

As for a unit removing disabling effects from itself, that's not really possible, as you can't issue orders while the unit is unable to act. The best you could do is some sort of custom UI solution that doesn't depend on the unit receiving orders, just on the player clicking a button.

To deal more damage to frozen units, I would use a standardized frozen debuff. Then when casting that ability you just need to check for the presence of that buff.
I finally got to the stage of needing your system, and I am planning to use this buff system with yours [vJASS] - Buff System. If I use your system for permanent stun and track it with a buff system, I will end up having two buffs instead of one. How can I avoid having two buffs on the unit? I think in the example you mentioned, they don't run into this problem.

Another problem is in this case I can't apply buff reduction, since stuns on your system are permanent.
 
I found a bug: In rare use cases a unit can become stunned permanently. The best way I know to re-create it is in this test map if you have the Paladin cast Flame Nova on the Peasants enough times the unit that gets hit will become permanently stunned. It may take you at least 3 minutes of spamming flame nova but it does happen. This has also happened to me with other abilities using this system but this is the easiest to re-create.
 

Attachments

  • Guhun Stun System permastun bug.w3x
    174.7 KB · Views: 2
Top