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

Simple Stun System

This bundle is marked as useful / simple. Simplicity is bliss, low effort and/or may contain minor bugs.
  • Like
Reactions: Blake8
Simple Stun System

1. very simple
2. 100% save when mixed with OE other stun abilities
3. can target structures


  • SimpleStunSystem
    • Events
      • Map initialization
    • Conditions
    • Actions
      • -------- copy ability and buff in Object Editor, set ability here: --------
      • Set ssz_Abil = SimpleStunSystem
      • -------- use your dummy unit or copy from demo map --------
      • Set ssz_DummyId = Dummy (Vexorian, Anitarf, Infrane)
      • -------- end of configuration --------
      • -------- ----------------------------- --------
      • -------- ----------------------------- --------
      • -------- Stun duration this system can apply is: min 0.50sec, max: 10sec --------
      • -------- Please note this system (unlike others) can be mixed with ObjectEditor stuns without problems --------
      • Custom script: set udg_ssz_Dummy = CreateUnit(Player(15), udg_ssz_DummyId, 0.00, 0.00, 0.00)
      • Unit - Add ssz_Abil to ssz_Dummy
      • Custom script: endfunction
      • Custom script: function UnitApplyStun takes unit target, real duration returns nothing
      • Custom script: local integer level = R2I((duration*2.00)+0.50)
      • Custom script: if duration > 0.00 and target !=null then
      • Custom script: if level==0 then
      • Custom script: set level=1
      • Custom script: elseif level>20 then
      • Custom script: set level=20
      • Custom script: endif
      • Custom script: call SetUnitX(udg_ssz_Dummy, GetUnitX(target))
      • Custom script: call SetUnitY(udg_ssz_Dummy, GetUnitY(target))
      • Custom script: call SetUnitAbilityLevel(udg_ssz_Dummy, udg_ssz_Abil, level)
      • Custom script: call IssueTargetOrderById(udg_ssz_Dummy, 852095, target)
      • Custom script: endif
It uses 20 level ability based on StormBolt with 0.50sec duration step
So it allows to stun from 0.50sec min to 10sec max
Contents

Simple Stun System (Map)

Reviews
MyPad
Untill the author decides to request a re-review, this will be moved to Substandard for the following reasons: Reasons: May cause unintended behavior such as a permanent stun bug, rework of many abilities and such. Serves as an archive for future...

Kazeon

Hosted Project: EC
Level 33
Joined
Oct 12, 2011
Messages
3,449
most of which have bug: perma stun bug, I already looked at 3 system from Hive and they have perma stun bug (systms based on hoof stomp, firebolt)
This one is save.
Using storm bolt, the buff doesn't get applied instantly.
try:
call ApplyStun(unit)
call BJDebugMsg(I2S(GetUnitAbilityLevel(unit, stun buff)))

It's going to print 0. But it's not like that with stomp ability.

I also saw perma stun bug possibility in some stun systems, I contacted the authors but they just never updated it.
It's not something unfixable tho.
 
Level 11
Joined
May 16, 2016
Messages
730
1. Storm Bolt's bullet speed is 10000. Why not set 0 to make it instant?
2. It's limited only by 10 sec.
3. If I want, fo example 0.215 sec, what should I do then?

I guess you haven't heard about hashtables.
Also 20 levels for custom ability? increasing loading time alert!
 
Last edited:
Level 18
Joined
Nov 21, 2012
Messages
835
@Fruit Forest
yeah, I know it is far from perfect, multilevel abilites increases loading time-true but on current pc's it's not significant, it has limitations as you mentioned, but overall savety is most importand in my opinion. Do you think hashtables can solve perma stun bug? If you have idea how, please share.
@Quilnez
i know stomp is instant but only problem with stomp is: this lags when making aoe stuns at least on my laptop (truth is: it's now new but still..)
i tested delay between issue order thunderbolt and buff appear on target: it is 0.004sec (tested on 2 pc's)
about bug:
It's not something unfixable tho.
It is unfixable unless whole idea will be changed
Systems that using firebolt/stormbolt with ability duration set to 9999 and checking in loop remaining time and then removing buff when time<=0 are wrong coded.
Imagine that system is running (few unit are stunned), timer is running (or loop trigger is on) and you 0.002sec before next timer tick applying new stun. (there is non 0 chance to do that) Remember 0.004sec gap. What happend: in nearest timer tick target has no buff (yet) so it is removed from stun-group. A moment after firebolt landing on unit/buff appears and cause unit is perma stunned.

Most importand: interaction with any other stun ability
how stun buffs works in war3:
2 stuns on unit:
warcraft updates buff icon (last casted stun is visible), but not effect overhead
and game chooses longer duration between new duration and remaining one

so if user mix stun system with any other stun ability:
1.a unit is stuned by the system
2.while stunned, it is stuned by other ability:
game will remove old (stunSystem) buff, will apply new buff (effect overhead will not be changed) and chooses longer duration (which is stunSystem, cause it is set to 99999)
so unit has no stunSystem buff on it.. you cannot remove it, when checking GetUnitAbilityLevel(u, BUFF) it will be 0. But it will remain stunned by 99999sec
its not fixable in this form since we have no way to get stun remamning time comes form abilities.

This tiny snippet is 100% save, I know its limitations but still can be usefull
 
Level 22
Joined
Feb 6, 2014
Messages
2,466
The trick is to use a timer instead of periodically looping. When a currently stunned unit is applied a new stun with a greater duration than the previous, then retrieve the instance timer and reset the timer to a new timeout (call TimerStart(...) again).

Here's the one I'm using in my map which I made a long time ago to serve as an example
JASS:
library Stun uses TimerUtilsEx, Table, DummyRecycler
 
/*
    Stun.create(unit, duration, additiveTime)
        - Stun a unit for a certain duration preventing it from doing anything.
        - Duration of zero means infinite.
        - Buff indicator appears.
 
    this.destroy()
        - Destroy a Stun instance.
*/

    globals
        private constant integer STUN_SPELL = 'AStn'
        private constant integer STUN_BUFF = 'BPSE'
    endglobals
 
    struct Stun extends array
        implement Alloc
     
        private unit u
        private unit dummy
        private timer t
     
        private static Table tb
        private static trigger trg
        private static group g = CreateGroup()
        private static integer counter = 0
     
        method destroy takes nothing returns nothing
            call UnitRemoveAbility(this.u, STUN_BUFF)
            call GroupRemoveUnit(thistype.g, this.u)
            call thistype.tb.remove(GetHandleId(this.u))
            call UnitRemoveAbility(this.dummy, STUN_SPELL)
            call RecycleDummy(this.dummy)
            call ReleaseTimer(this.t)
            set this.u = null
            set this.dummy = null
            set this.t = null
            call this.deallocate()
        endmethod
     
        private static method expire takes nothing returns nothing
            call thistype(GetTimerData(GetExpiredTimer())).destroy()
        endmethod
     
        private static method onDeath takes nothing returns boolean
            local thistype this = thistype.tb[GetHandleId(GetTriggerUnit())]
            if this != 0 then
                call this.destroy()
            endif
            return false
        endmethod
     
        private static method add takes nothing returns nothing
            call TriggerRegisterUnitEvent(thistype.trg, GetEnumUnit(), EVENT_UNIT_DEATH)
        endmethod
     
        static method create takes unit u, real duration, boolean stack returns thistype
            local integer id = GetHandleId(u)
            local thistype this = thistype.tb[id]
            local real prevDuration
            local unit dummy
            if this != 0 then
                set prevDuration = TimerGetRemaining(this.t)
            else
                set this = thistype.allocate()
                set this.u = u
                set this.t = NewTimerEx(this)
                set thistype.tb[id] = this
                set prevDuration = 0
            endif
            if stack then
                set duration = prevDuration + duration
            elseif duration < prevDuration then
                return this
            endif
            if duration > 0 then
                call TimerStart(this.t, duration, false, function thistype.expire)
            endif
            if prevDuration == 0 then
                set this.dummy = GetRecycledDummyAnyAngle(GetUnitX(u), GetUnitY(u), 0)
                call SetUnitOwner(this.dummy, GetOwningPlayer(u), false)
                call PauseUnit(this.dummy, false)
                call UnitAddAbility(this.dummy, STUN_SPELL)
                call IssueTargetOrderById(this.dummy, ORDER_thunderbolt, u)
                set thistype.counter = thistype.counter + 1
                if thistype.counter > 10 then
                    set thistype.counter = 0
                    call DestroyTrigger(thistype.trg)
                    set thistype.trg = CreateTrigger()
                    call TriggerAddCondition(thistype.trg, Filter(function thistype.onDeath))
                    call ForGroup(thistype.g, function thistype.add)
                endif
                call TriggerRegisterUnitEvent(thistype.trg, u, EVENT_UNIT_DEATH)
                call GroupAddUnit(thistype.g, u) 
            endif
            return this
        endmethod
     
        private static method onInit takes nothing returns nothing
            set thistype.tb = Table.create()
            set thistype.trg = CreateTrigger()
            call TriggerAddCondition(thistype.trg, Filter(function thistype.onDeath))
        endmethod
     
    endstruct
 
endlibrary
 
Last edited:
Level 18
Joined
Nov 21, 2012
Messages
835
@Fruit Forest
thanks! it seems the stun duration was the problem, no hash :)
you set it to 0 and now in-game comparison is safer it partly solves perma stun bug, few systems like By Ayanami must be fixed by setting duration to 0 instead of 3600 or 99999 in OE,
delay cap is the same for missle speed:0 and 10000, i see no diffrence, its still 0.004sec
interactions System<->OE spells are safer now but not perfect: like unit stunned for 7sec by System and MountainKing bash it for 0.50sec right after - unit lose 7sec stun and is stunned for 0.50sec but I have to think about that, not sure if it is solvable at all?

Also there's alternative to Flux library (w/o timerUtils) like catch StunEvent and then register unit,
you can catch this by checking unit's order GetIssuedOrderId() == 851973 and then after 0sec timer (one for whole map) check for stunSystemBuff. If it has buff-it was stunned by System and can be added to group or something..
 
Level 11
Joined
May 16, 2016
Messages
730
interactions System<->OE spells are safer now but not perfect: like unit stunned for 7sec by System and MountainKing bash it for 0.50sec right after - unit lose 7sec stun and is stunned for 0.50sec but I have to think about that, not sure if it is solvable at all?
It can be solvable but you have to use trigger spells. Which means you need dummy target spell (chain lightning with no effects), a dummy which shots from the caster position, damage detect system which detects the damage caused by the dummy and condition: if stored in hash value is greater than the current bullet's value, then do stun else do nothing. The system you tried to make acutally is much more complicated.
delay cap is the same for missle speed:0 and 10000, i see no diffrence, its still 0.004sec
It's because you moves your dummy. My one just stay on one place and cast from there. Don't need to to create X,Y coordiantates of the victim. (but it doesn't rallly matter since your execution of trigger is works) however it doesn't count invisibility. Because you dummy is neutral passive and it probably doesn't share vision with the target - you can just move your dummy to engage the stun, but the dummy doesnt see the target because of invisibility.
 
Level 18
Joined
Nov 21, 2012
Messages
835
I dont know if it is right place but I fast looked in all stun system on Hive:
Stun System (v0.05) By Losam
by Losam: based on storm bolt, checks for buff in loop trigger, may cause perma stun
StunMe v1.4
by Mckill2009: based on storm bolt, stun duration in OE must be fixed, it uses CTL library (I dont know how this lib works),so Im not sure if it's save like Flux' solution?
since it doesnt check for buff in loop, this one should work fine
[GUI]Stun system v1.6
by KhaosMachine: based on WarStomp - its bugged, should be changed/removed
Stun Engine v.1.1
by BPower: based on WarStomp - its bugged, should be changed/removed
[GUI] AlternativeStunSystem v1.1
by Vladadamm: it uses PauseUnit (not related)
[GUI]Simple Stun System v1.0 [UnitIndexer Version]
by baassee: based on thunder bolt, not looking for buff in loop, should work fine

why WarStomp cannot be used: it doesnt work for duration set in OE to 0sec (like we can and should do with thunderbolt ability) so it is set by authors to 3600sec. Its very dangerous: if stunned unit (by system) is stuned again by any ability = perma stun.
 
Last edited:
Level 22
Joined
Feb 6, 2014
Messages
2,466
yeah, with separate timer for each unit you're save as long as you remember to not use any stun ability, only your library :)
but most systems even do not have warning "do not use stun abi except imported stun system"
and i bet users can forget (or just wants to use some stun abi except system)
I don't understand why a user would use another stun ability if he/she already has a stun system. The problem with this is the high-leveled ability which increases Loading Time (as mentioned by Fruit Forest) and it only allows you to stun at discrete intervals, you can't stun a unit for 3.1415 seconds.
 
Level 11
Joined
May 16, 2016
Messages
730
why WarStomp cannot be used: it doesnt work for duration set in OE to 0sec (like we can and should do with thunderbolt ability) so it is set by authors to 3600sec. Its very dangerous: if stunned unit (by system) is stuned again by any ability = perma stun.
Duuuude you can create triggered war stomp. just use group variable and pickk all in range then create the dummy and do stuff. If you try to implement stun system you have to decline all standard stun abilities.
 
I dont know if it is right place but I fast looked in all stun system on Hive:
Thanks for bringing the discussion up. I honestly did never code myself a stun system, so idk all critical points.

y Mckill2009: based on storm bolt, stun duration in OE must be fixed, it uses CTL library (I dont know how this lib works),so Im not sure if it's save like Flux' solution?
CTL will probably result in same as the first one you mentioned with "perma stun bug".

by Vladadamm: it uses PauseUnit (not related)
Hm, yes that's not really a stun system. I'm not sure it should be named as one.

by baassee: based on thunder bolt, not looking for buff in loop, should work fine
But it's not instant, or?

Warstomp is a good method, but then one need to ban object editor stuns,
and bolt is not instant, but object editor stun is allowed?

Is the required bolt duration calculateable? Maybe there can be a combination of both, that at first a unit is instantly stunned by warstomp for the ("short") duration until the bolt comes, and then the bolt overrides the stun and so it becomes instant + fixed?
 
Level 18
Joined
Nov 21, 2012
Messages
835
I don't understand why a user would use another stun ability if he/she already has a stun system.
Because it is so easier. Tell gui user to ban all this abilites:
  • stasis trap
  • bash
  • storm bolt
  • war stomp
  • impale
  • inferno
  • firebolt
  • frostbolt
  • hurl boulder (creepthunderbolt)
  • cluster rockets
  • volcano
  • rain of chaos (archimonde)
and trigger them all instead ...
Even Bribe in his GUI Knockback used until recenty (until a year ago or so) Inferno ability to detect pathing. I personally expirenced perma stun bug by using together his GUI KB + stun system by BPower :(

I belive warstomp is not acceptable with 3600sec duration, however IcemanBo idea is very interesting.
For now these two systems are save: by Mckill2009, by baassee. But if mixed with other stun abi's system stun will be overwriten (annoying for player when 7sec system-stun is replaced by 1sec stun comes from Inferno for example)
There's solution to re-order stun (if buff has gone) to get desired duration. To do that we have to periodicaly check for buff, and remembering 0.004sec delay (order issued --> bolt landing on victim) we got IcemanBo option or adding a counter and check for buff after ~0.50 or so (to be sure missle has reach target). This 0.004sec gap I tested on single player only, it should be checked in multiplayer game to get info if it is constant or varies.

PS And please dont comment this primitive trigger I submitted about invisibility and duration 0.50sec step because it becomes now about stun systems generally.
 
Level 22
Joined
Feb 6, 2014
Messages
2,466
I guess I'm not the kind of guy that relies on Object Editor-based abilities. Making spells using triggers is the surest way to achieve almost full control of your gameplay mechanics. Say I want a Spell that reflects a Storm Bolt. Or I want a Storm Bolt spell that increases damage the longer the time it has travelled. Those can only be achieved by triggering Storm Bolt itself which is not really hard to do and even easier if you use some Missile system. The point is, if a person ever wants something more than just default WC3 spells, in my opinion triggering them is a better option as it allows you to have almost full control for future changes.
 
Internal checks should provide duration logics instead of making 0.5sec steps.

The call function is not inside a library, so it's not ensured to be put on top of compiled code.
It should support pure GUI usage I believe from current state, or just switch to pure vJASS lib.

Stun must happen instantly.

In case you make it happen to work instant + compatible with object editor data, I see it as useful.
 
Level 18
Joined
Nov 21, 2012
Messages
835
Thanks for reminde me about this.
I would like to put it off for a few days cause I belive I found a way to make an 'stun event'. When finished I'll upload it in spell section for review , this may be a part of real stun system which allows to use OE spells and meets your recommendations IcemanBo


edit
I give up.
Cannot solve problem when ranged stunner (storm bolt like) dies before launched missle lands on victim. And it won't fire order 851973. If anyone interested in details let me know.
 
Last edited:
Level 18
Joined
Nov 21, 2012
Messages
835
By the way: systems based on "war stomp" should warn the user to not use any OE stun abilities (including bash, stasis trap, etc, listed those abilities on previous page), to avoid permanent stun bug

To avoid permanent stun bug and have instant stun we have to use "war stomp" with 0.50sec duration and then "storm bolt" with 0sec duration.
And cooperation with OE stuns is possible in 2 ways
  1. OE stuns will overwrite System Stuns
  2. System Stuns will overwrite OE stuns
1st behavior is default (no additional code needed)
2nd option require re-apply stun if stun-system-buff has gone
unfortunatelly both options are far from perfect.

About Stun Event:
I tryed to build an event based on JASS/script.j at master · nestharus/JASS · GitHub
it uses EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER with 851973 order where GetOrderedUnit() is stunned unit, GetOrderTargetUnit() is a stunner. It was very promising as "Stun applied event". This event (851973) fires only if target is not yet stunned. However it wont fire if Initial Stunner dies or is removed from the game before stunning missle lands on target. (There's no danger for "war stomp" as it is instant)

(additionally for storm bolt-like abilities caster will always damage target by 0.00damage at the moment when missle lands [even if caster dies during missle is flying, but NOT when caster is removed from game during missle is flying].

For Storm Bolt I noticed for multiple stuns without gaps that the first stunner (Initial Stunner) from above event is remembered by game engine. Even if target is stunned by multiple units and stun duration is increased, Initial Stunner will deal 0.00 damage to target when stun expires. But only if Initial Stunner is alive at the moment when stun expires and if Initial Stunner caused 0.00damage at the begining.
It happend also (0.00dmg event at stun expire moment) for Bash ability, didnt test more.

The reason I gave up is red text above
 
Top