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

StunMe v1.4

Note

Main Code

How to use it

Issues/Bugs


I know that there are many stun system now but this is a very simple one, GUI friendly and disables the animation of the stunned unit...

JASS:
/*
=====StunMe v1.4
=====by Mckill2009

A very simple Stun System...

REQUIRES:
- CTL by Nesthaurus

INSTRUCTIONS:
- Copy ALL that is in the "StunMe" folder into your map.
- Copy ALL the custom unit/ability/buff to your map.
- Change the DUMMY_ID, STUN_ID and STUN_BUFF raw code if needed.
- DONE!

API:
    static method stun takes unit target, real duration returns nothing
        - Stuns the target unit
        - Stacking is OK
        
    static method stop takes unit target returns nothing
        - Oviously stops the stun  
*/

library StunMe uses CTL

globals
    private constant integer DUMMY_ID = 'xdmx'
    private constant integer STUN_ID = 'ab01'
    private constant integer STUN_BUFF = 'bu01'
    private constant integer STUN_OID = 852095
    private constant string RESTORE_ANIMATION = "stand"
    private unit StunCaster = null
endglobals

struct StunMe extends array
    private unit target
    private static hashtable ht = InitHashtable()
    
    implement CTL
        local real dur
        local integer id
    implement CTLExpire
        set id = GetHandleId(.target)
        set dur = LoadReal(ht, id, 0)
        if dur > 0 and not IsUnitType(.target, UNIT_TYPE_DEAD) then
            call SaveReal(ht, id, 0, dur-0.03125)
        else
            call UnitRemoveAbility(.target, STUN_BUFF)
            call SetUnitTimeScale(.target, 1)
            call SetUnitAnimation(.target, RESTORE_ANIMATION)            
            set .target = null
            call .destroy()
        endif
    implement CTLEnd
    
    private static method onInit takes nothing returns nothing
        set StunCaster = CreateUnit(Player(15), DUMMY_ID, 0, 0, 0)
        call UnitAddAbility(StunCaster, STUN_ID)
        call UnitRemoveAbility(StunCaster, 'Amov')
    endmethod
    
    //API:
    static method stun takes unit target, real duration returns nothing
        local thistype this
        local integer id = GetHandleId(target)
        if LoadReal(ht, id, 0)==0 then
            set this = create()
            call SetUnitTimeScale(target, 0)
            call SetUnitX(StunCaster, GetUnitX(target))
            call SetUnitY(StunCaster, GetUnitY(target))           
            call IssueTargetOrderById(StunCaster, STUN_OID, target)  
            set .target = target
            call SaveReal(ht, id, 0, duration)
        else
            call SaveReal(ht, id, 0, duration+LoadReal(ht, id, 0))
        endif
    endmethod
    
    static method stop takes unit target returns nothing
        call SaveReal(ht, GetHandleId(target), 0, 0)
    endmethod
endstruct

endlibrary

  • StunMe DEMO
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
    • Actions
      • Custom script: call StunMe.stun(GetTriggerUnit(), 5)
      • -------- stack it! --------
      • Wait 4.00 seconds
      • Custom script: call StunMe.stun(GetTriggerUnit(), 7)
      • -------- or just maually remove it --------
      • Wait 3.00 seconds
      • Custom script: call StunMe.stop(GetTriggerUnit())

Tell me all the issues and it will be written here
- Cannot stun invulnerables



- CTL by Nesthaurus
- Adiktuz for suggestions
- PurgeandFire for his fast review



v1.4
- Group removed
- Error message removed coz of a bad bug

v1.3
- Added hashtable for stacking purposes
- Removed stunAddDur
- Methods are replaced by statics
- Easier to apply

v1.2
- Added CTL for 0.03125 duration

v1.1
- Static methods replaced by methods
- Table removed
- LUA objects removed
- Removed unnecessary lines


Keywords:
stun, pause, die, unit, disable, mckill2009, walk, run, fly, swim
Contents

StunMe (Map)

Reviews
23:23, 15th May 2013 PurgeandFire: The updates were made. I personally think the stacking could be a bit different (right now you have additive stacking), but that is a personal issue just for gameplay balancing. :) This system works and is...

Moderator

M

Moderator

23:23, 15th May 2013
PurgeandFire:

The updates were made. I personally think the stacking could be a bit different (right now you have additive stacking), but that is a personal issue just for gameplay balancing. :)

This system works and is simple to use. Approved.
 
Level 29
Joined
Mar 10, 2009
Messages
5,016
Please add a notice that the LUA script won't work in some computers.
Let me guess what's the Group for,to check if the unit has a stun right? You can just use a boolean table,or if the unit has the stun buff.

1.0 loop? What for?

- Im planning to remove the LUA anyway in the next updates with struct methods instead of a static...
- Handle checks doesnt work with Table (tested it before), only integer check, idk why...
- The loop is for the duration, Im surprised you didnt noticed that :(...
 
So right now, your system only support stun durations that are in at least interval of 1.0 second (1.0, 2.0, and so on)... What about if the user wants a non 1 second interval stun (like 1.5 seconds total stun duration)? And I tell you, those kind of intervals are common to stuns...

Also, your system does not support stunning of a unit that is already stunned... again, the occurrence of multiple stun hits on a single unit is pretty common...
 
I believe that for a stun system to be useful it should at least:

1) Allow custom durations (formula based etc)
-> Yours allow it, but limited to "whole number" durations (1.0,2.0,3.0 and so on) because of the 1.0 interval for the timer

2) Allow the user to define how multiple stuns are handled (like should they stack durations or only the latest stun takes effect or the longest stun etc)
-> You can use static ifs for this

And for these two, the most important is the first one... You should really work on that...
 
THE FALLBACKS OF THE 1 SECOND TIMER INTERVAL AND THE CURRENT STRUCTURE OF THE METHODS

Your system actually has an extra 1 second stun [at least for the first stun that will fire the timer, indefinite value for the other stuns, theoretically they will all have extra 1 second but because of point number 3 (see below) it's actually indefinite] because it only checks the duration condition for stopping at the top of the loop...

Sample:

->Stun duration of 1 second
->Trigger Starts
->After 1 second, check if duration is 0, if not reduce by 1
->Now duration is 0
->Finishes running the loop
->After another second, check if duration is 0, yes?
->Then terminate stun

Total actual duration of the stun? 2 seconds instead of 1... Of course you can tell the users to use a duration of 1 second smaller than the actual but due to the other things that arise from this 1 second interval (as stated on the two other points below) of yours, I won't suggest it...

--------------------------------------------------------------------
Also, your stop method just sets duration to 0, which means it relies on your expired method to activate...

Now imagine this:

Stun duration of 5.0 seconds

After 2.1 seconds, stop method activates

Since your stop method relies on the expired method that runs only every 1.0 second, the stun will only be removed at the 3.0 second mark

That might look really bad when it actually happens in game... Imagine if a unit has a "Remove Stun" ability and a situation like that happens...

--------------------------------------------------------------------

Another fallback is that if a stun happens when the timer is already running... that would result in inaccuracies of the stun duration

Example:

->A stun is fired (first stun)
->Timer starts
->After 0.5 seconds, another unit is stunned
->since the timer is already running, then after just another 0.5 seconds (to make it 1.0 second total), the stun durations will be updated and so the second unit will garner a 1 second stun duration reduction when the actual stun only lasted 0.5 seconds so far...

--------------------------------------------------------------------

This is why you don't use a large interval for timer loops that are event/user-action driven...
 
Last edited:
In either case, consider the following:

- Timer expires.
- After 0.2 seconds, a stun is registered
- Timer expires after 0.8 seconds
- Timer expires after 1 second

The stun intended to be between 0.81 and 1.79 seconds was cranked up to 1.8 seconds. And any stun intended to be 1.81 would be cranked up to 2.8 because of the timer expiration.

Of course, this is not referring to your system in particular, this is referring to the usage of large intervals for state-related libraries ^^

A configurable constant would be fine. (0.03125)

You can also choose to use a library like CTL if you want.
 
Level 29
Joined
Mar 10, 2009
Messages
5,016
@PurgeandFire
Ima update it tonight...thanks for the feedback...

Also, why do you set the unit's position to his current position? (SetUnitX(u, GetUnitX(u)), same for y) I'm just curious.
Coz I miss that I coud make the range of the stun spell to 99999 so that even if he's in the center, he still can cast...

For the method "stunStop", you should also remove the unit from the group. Otherwise he'll still be considered stunned. Speaking of which, why do you need to use a unit group? Can't you just check if the unit has the buff?
That's the main purpose why I use 1/sec interval in the first place, coz you cant just check a buff being applied via 0.03125 or fast intervals, there is a gap between checking buffs, I've tested it before and failed, that's why another method should apply, either a unit group or a hashtable (which Im not applying coz its slow)...

EDIT:
v1.3 is out supports stacking...
 
Last edited:
Level 29
Joined
Mar 10, 2009
Messages
5,016
PurgeandFire said:
Instead you should check if the unit has the buff, or just check if the LoadReal() value is > 0
Updated, Im doing the LoadReal coz checking a buff from a fast interval causes bugs...
I've removed the error messages coz it causes bugs...
Im putting back the SetUnitXY coz it causes bugs if the target is too far to reach by the storm bolt, I can adjust the projectile speed however but I think this setup is just fine...
 
Level 37
Joined
Mar 6, 2006
Messages
9,240
  • The stop should be instant, now there is ]0, 0.03125[ second delay
  • The dummy has unknown ability in the editor
  • You should check if the stun order is succesfull, invulnerables can't be stunned but you halt their animation
  • You should save the duration as 0 when it expires. Imagine stun durations that end up with negative duration. Maybe even flush data from the hashtable
 
Level 29
Joined
Mar 10, 2009
Messages
5,016
  • The stop should be instant, now there is ]0, 0.03125[ second delay
  • The dummy has unknown ability in the editor
  • You should check if the stun order is succesfull, invulnerables can't be stunned but you halt their animation
  • You should save the duration as 0 when it expires. Imagine stun durations that end up with negative duration. Maybe even flush data from the hashtable

- I think that's fine, but I try to find a solution as it will double deallocate if I do that unless the instant doesnt call deallocate
- No usage anyway :D
- Ima check that
- Flush is OK
 
Level 3
Joined
May 28, 2012
Messages
32
Great System! I like it =)!

Very simple and also GUI friendly.

But there is a small VISUAL bug tho. If you kill someone with a spell that uses your stun system, the killed unit will not play the Death animation but the stand animation instead.

If u fix that i'll rate 5/5 instead of 4/5!
 
Top