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

Level 5
Joined
Jan 18, 2007
Messages
59
Simple Stun System v1.02b
Pros:

1) Allow to stun for any amount of secs
2) Consists of 49 lines
3) Timer don't expire every 0.01 sec but as u ordered which have to make it fast & furious
3) It is the simpliest system I've ever seen:)

Cons:

It's not tested a lot )
So if u find any bug post it I'll fix it!

*******************
**How to implant:**
*******************

The system is very easy. The only things you'll have to do to implement the system is to:
1) copy the SimpleStunSystem trigger into ur map
2) copy dammy Unit (if u haven't it yet)
3) copy Ability & Buff "Simple Stun"
4) Change the buff of the ability to the buff "Simple Stun"
5) Change the variables in the system DummyId; AbilId; BuffId

Note: Requires vJass
*******************
**How to use: ******
*******************
To use this system u have to have a trigger with the event unit pick up item and in the actions
just write:
function StunUnit takes unit whichunit,real duration, boolean CheckImmunity returns boolean
Arguments:
unit whichunit - Unit that must be stunned //I think it is clear
real duration - duration of the stun
boolean CheckImmunity - whether to chec kmagic immune units or not
returns boolean - returns whether it stuned the unit or not

JASS:
 //***************************************************************
//*                Simple Stun System v1.02
//* -------------------by Matrix---------------------------------
//*           Latest version on [url]http://www.thehelper.net[/url] forums
//*   Function Index
//*
//*   StunUnit(unit whichunit, real duration, boolean CheckImmunity)
//*   
//* unit whichunit - the unit that will be stunned
//* real duration - the duration of the stun
//* boolean CheckImmunity  means it checks if the unit is immune, a building or mechanical in which case it does not stun.    
//NOTE - The smallest possiable stun duration is 0.01 due to limitations with the system and so it will stun for 0.01 seconds even if u pass duration less than 0.01 but bigger then zero
//NOTE - The system supports stunning the same unit twice with no problems based on the largest stun duration like WC3's stun works normally. In other words if u stun unit for 999 seconds and then for 1 second it will be stunned for 999 secs! 
//INTERFACES (inside library)    
//integer Total    
//The number of units currently stunned by the system.
//***************************************************************
//=============================================================
//        How to implant: (Uses Jass NewGen Pack)
//1) copy this trigger into ur map
//2) copy dummy Unit (if u haven't it yet)
//3) copy Ability & Buff "Simple Stun"
//4) Change the buff of the ability to the buff "Simple Stun"
//5) Change the variables in the system DummyId; AbilId; BuffId (See below:)
//=============================================================
//***************************************************************
//**ChangeLog v1.02
//1) Now Double stun on the same unit works properly
//2) Now Calling function with negative amount of sec will do nothing
//3) Now calling function with less amount of sec than 0.01 will set
//it to 0.01
//4) A little bit optimization
//=============================================================
library SimpleStunSystem
globals        
//Set this to the raw data value of the dummy unit that must be used by this system.        
private constant integer ID_DUMMY = 'h000'        
//Set this to the raw data value of the dummy stun ability that must be used by this system.        
private constant integer ID_ABILL = 'A000'        
//Set this to the raw data value of the stun buff that must be used by this system.        
private constant integer ID_BUFF  = 'B000'        
//Contains the number of units stunned via the system ingame at any point in time.        
public integer Total=0        
//Variables used by the system to store the timer used for stun duration and the unit who is stunned.        
private timer array T        
private unit array U    
endglobals 
private function End takes nothing returns nothing
   local integer i = 0
   local timer time = GetExpiredTimer()        
   //Finds which unit the timer went with. 
   loop
       exitwhen time==T[i]
       set i = i + 1
    endloop
    //Gets rid of the timer        
   call PauseTimer(time)        
   call DestroyTimer(time)        
   set time = null        
   //Unstuns the unit 
   call UnitRemoveAbility(U[i],ID_BUFF)        
   //Deallocates the object from the system. 
   set Total=Total-1        
   set T[i]=T[Total]        
   set U[i]=U[Total]        
   set T[Total]=null        
   set U[Total]=null 
endfunction

function StunUnit takes unit u,real d, boolean CheckImmunity returns boolean
    local unit s = null
    local integer i = 0
    //Checks if the duration is long enough for a stun to be correctly applied and if so then checks if it is to check immunity and if so does so before doing stun actions.    
    if (not CheckImmunity or (not IsUnitType(u,UNIT_TYPE_MAGIC_IMMUNE) and not IsUnitType(u,UNIT_TYPE_MECHANICAL) and not IsUnitType(u,UNIT_TYPE_STRUCTURE))) and d>0 then
    //Loops via a O(n) type loop to check if a unit is already stunned via the system.            
   //If one is it uses that refference if not it then uses a blank reference.
       if d<.01 then
          set d =.01
       endif
       loop
           exitwhen U[i]==u or i>Total
           set i = i+1
       endloop
       if  i<=Total then
          if TimerGetRemaining(T[i])<d then
             call PauseTimer(T[i])
             call TimerStart(T[i],d,false,function End)
          endif
          return true
       endif
      //Creates a dummy and prepairs it so that it can stun.            
      set s = CreateUnit(GetOwningPlayer(u),ID_DUMMY,GetWidgetX(u),GetWidgetY(u),0)            
      call UnitAddAbility(s,ID_ABILL)            
      call UnitApplyTimedLife(s, 'BTLF', 1)   
       if T[Total]==null then
          set T[Total]=CreateTimer()
       endif
       set U[Total]=u
       //Stuns the unit for infinity
       call IssueTargetOrderById(s,852095,u)
       //Cleans up local objects to null to stop leaks. 
       set s = null
       set u = null
       call TimerStart(T[Total],d,false,function End)
       set Total=Total+1
    return true
endif
set u = null
return false
endfunction
endlibrary

Download

Simple Stun System v1.02b
 
Last edited:

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,198
System will bug if you use it to stun the same unit twice.
If you stun a unit for 1 second and then stun it for 10 seconds, the unit will be unstunned after 1 second.
This is due to the lack of a system that checks if a unit has been stunned and if so updates the timer rather than stacking them and bugging.

CheckImmunity!=IsUnitType(u,UNIT_TYPE_MAGIC_IMMUNE)

Why not just

not IsUnitType(u,UNIT_TYPE_MAGIC_IMMUNE)

I am sure that would be faster?

You could also make your system struct based as that is basically what you do.
 
Level 14
Joined
Nov 18, 2007
Messages
816
theres a bug with IsUnitType which occurs when using specific values for the second parameter. This can be avoided by using ==true or ==false.

You dont cleanup s.

JASS:
    set T[Total]=T[i]
    set U[Total]=U[i]
    set T[Total]=null
    set U[Total]=null
thats nonsense. First you assing T/U[Total] a value and then clean those up.

JASS:
    local timer tswp // initializing not necessary
    [...]
    set tswp=T[i]
    set Total = Total - 1
    set T[i]=T[Total]
    set U[i]=U[Total]
    set T[Total]=tswp
    // no, resetting the unit doesnt matter
    [...]
    set tswp=null
fix'd. Seriously, this should have caused some bugs, im surprised noone stumble across them already.

And there are the downsides Dr Super Good already mentioned.

EDIT: Oh and would you please start following some conventions? Especially those for naming globals and those for indenting?

Some other Edits: Corrected the script I provided.

Deaod
 
Last edited:
Level 14
Joined
Nov 18, 2007
Messages
816
thats nonsense. You'd want to preserve the timer, instead of pausing and leaking it (not destroyed, but no way you could ever destroy it). Loosing reference to the unit doesnt matter, but loosing reference to a timer is painful for every player of your map.
 
Level 14
Joined
Nov 18, 2007
Messages
816
1.) You still leak Timers (worst).
2.) You still dont cleanup s (pretty bad).
3.) Stacking stuns still impossible (thats a feature; its up to you if you implement it).
4.) You create a unit even when not necessary (performance problem; minor one).
5.) Your algorithm to clean U and T is broken (and thats really bad).
6.) You dont indent properly.
7.) Its common to name global constants UPPER_CASE, and Capitalize non constant globals.
 
Level 14
Joined
Nov 18, 2007
Messages
816
1.) Ok, here we go:
Here is a tutorial introducing to leaks in general.
You are leaking a Timer because you may loose all references to a timer object (no variable holds a pointer to the object in the memory), yet you didnt destroy it. And because you dont have any reference to that object you cant ever destroy it in the future. Leaking one timer isnt that horrible, but within a system like this you can possibly leak hundreds of them, making the map using this system unplayable.

2.) Cleaning s means setting it to null (its a local variable of type handle referencing a unit, even after you returned true/false).

4.) cut
JASS:
       set s = CreateUnit(GetOwningPlayer(u),DummyId,GetUnitX(u),GetUnitY(u),0)
       call UnitAddAbility(s,AbilId)
       call UnitApplyTimedLife(s, 'BTLF', 1.)
and insert after
JASS:
       if T[Total]==null then
          set T[Total]=CreateTimer()
       endif

5.) Look at my first post. Thats the way its done. Did you even bother understanding what my first post was about?

7.) Nevermind.
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,198
How about a little comparison.

Which system is better, his revision from his old one or my revision from his old one.
JASS:
library SimpleStunSystem
    //Simple system used to stun a unit.
    //The script was based on an old version of Matrix's SimpleStunSystem
    //Minor changes made by Dr Super Good (80%+ of credit must go to Matrix as he did most of the code)
    
    //Notes from Dr Super Good
    //I fixed up the code so it does not leak.
    //I also added support to allow a unit to be stunned twice without any problems.
    //I properly indented the entire script to make it easilly readable.
    //I fully playtested the system catching minor bugs.
    //Caught the bug resulting in units not getting stunned if stunned for less than 0.05 seconds (is possiable to go as low as 0.005 some times but 0.05 was the smallest safe number I could find).
    //Added detailed commenty to the system to make it easier to learn from or use.
    
    //FUNCTIONS ADDED (outside library)
    
    //function StunUnit takes unit u,real d, boolean CheckImmunity returns boolean
    //u = which unit to stun
    //d = stun duration (how long).
    //CheckImmunity  means it checks if the unit is immune, a building or mechanical in which case it does not stun.
    //NOTE - The smallest possiable stun duration is 0.05 due to limitations with the system and so it will not stun for durations smaller than that.
    //NOTE - The system supports stunning the same unit twice with no problems but the strun will expire based on the last stun and any past stun duration are ignored like WC3's stun works normally.
 
    //INTERFACES (inside library)
 
    //integer Total
    //The number of units currently stunned by the system.
    
    globals
        //Set this to the raw data value of the dummy unit that must be used by this system.
        private constant integer ID_DUMMY = 'h000'
        //Set this to the raw data value of the dummy stun ability that must be used by this system.
        private constant integer ID_ABILL = 'A000'
        //Set this to the raw data value of the stun buff that must be used by this system.
        private constant integer ID_BUFF  = 'B000'

        //Contains the number of units stunned via the system ingame at any point in time.
        public integer Total=0
        
        //Variables used by the system to store the timer used for stun duration and the unit who is stunned.
        private timer array T
        private unit array U
    endglobals

    private function End takes nothing returns nothing
        local integer i=0
        local timer time = GetExpiredTimer()
        //Finds which unit the timer went with.
        loop
            exitwhen time==T[i]
            set i = i + 1
        endloop
        //Gets rid of the timer
        call PauseTimer(time)
        call DestroyTimer(time)
        set time = null
        //Unstuns the unit
        call UnitRemoveAbility(U[i],ID_BUFF)
        //Deallocates the object from the system.
        set Total=Total-1
        set T[i]=T[Total]
        set U[i]=U[Total]
        set T[Total]=null
        set U[Total]=null
    endfunction

    function StunUnit takes unit u,real d, boolean CheckImmunity returns boolean
        local integer i=0
        local unit s
        //Checks if the duration is long enough for a stun to be correctly applied and if so then checks if it is to check immunity and if so does so before doing stun actions.
        if d>=0.05 and (not CheckImmunity or (not IsUnitType(u,UNIT_TYPE_MAGIC_IMMUNE) and not IsUnitType(u,UNIT_TYPE_MECHANICAL) and not IsUnitType(u,UNIT_TYPE_STRUCTURE))) then
            //Loops via a O(n) type loop to check if a unit is already stunned via the system.
            //If one is it uses that refference if not it then uses a blank reference.
            loop
                exitwhen u==U[i] or i==Total
                set i = i + 1
            endloop
            //Creates a dummy and prepairs it so that it can stun.
            set s = CreateUnit(GetOwningPlayer(u),ID_DUMMY,GetWidgetX(u),GetWidgetY(u),0)
            call UnitAddAbility(s,ID_ABILL)
            call UnitApplyTimedLife(s, 'BTLF', 1)
            //Checks if it found that unit already stunned, and if not it then adds it to the system.
            if U[i]==null then
                set T[Total]=CreateTimer()
                set U[Total]=u
                set Total=Total+1
            endif
            //Stuns the unit for infinity
            call IssueTargetOrderById(s,852095,u)
            //Cleans up local objects to null to stop leaks.
            set s = null
            set u = null
            //Starts the timer to expire when the stun must end.
            //This is done in such a way it overwrides any previous stunning for that unit like W3C normally does.
            call TimerStart(T[i],d,false,function End)
            return true
        endif
        //Local leak prevention.
        set u = null
        return false
    endfunction
endlibrary

The above was based on his 1.01 sytem code and not his newest one.
I did not make most of the code, I purly improved appon it and am thus not entitaled to much of the credits for the above.

This addressed most of the problems people were complaining about I hope.
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,198
Sure, as long as somewhere you say some changes were made by me (I do not ask for credit, just a mentioning).

My system's stun tried its best to emulate blizzard's where the last used stun on a unit tells the duration. However due to limatations 0.05 seconds is the smallest stun I could manage to do without it bugging (unstunning the unit before it was stunned) which means the system is not perfect.

If you make the dummy unit facing the correct angle you should be able to reduce that to 0.005 which is an improvement. To do this I think it must be made so it faces the target and so saves time rotating.
 
Level 14
Joined
Nov 18, 2007
Messages
816
JASS:
library SimpleStunSystem
    globals
        private constant integer DUMMYUNITID    = 'h000' // the rawcode of dummy unit
        private constant integer STUNABILID     = 'A000' // the rawcode of simple stun ability
        private constant integer STUNBUFFID     = 'B000' // the rawcode of simple stun buff
        
        // This is shit. Don't touch shit.
        
        public integer Total=0
        private timer array T
        private unit array U
    endglobals

    private function End takes nothing returns nothing
        local integer i=0
        local timer t = GetExpiredTimer()
        loop
            exitwhen t==T[i]
            set i=i+1
        endloop
        call UnitRemoveAbility(U[i],STUNBUFFID) // unstun the unit.
        // some recycling
        set Total=Total-1
        set T[i]=T[Total]
        set U[i]=U[Total]
        set T[Total]=t
        set U[Total]=null
    endfunction
    
    
    // ************************************************************************************************
    // * Main and only function available outside this library
    // * 
    // *    PARAMETERS:
    // *     * unit u: the unit to stun
    // *     * real d: the duration of the stun
    // *     * boolean StunMagicImmune: checks whether Magic Immune units can be stunned
    // *     * boolean StunMechanic: checks whether Mechanic units can be stunned
    // *     * boolean stack: checks whether this stun can be stacked onto an existing one (by this system).
    // *
    // *    EXAMPLE:
    // *     * call StunUnit(u, 2, false, true, true)
    // *        This stuns u for 2 seconds if there isnt already another stun caused by this system,
    // *        else the stun will be stacked. Magic immune units can't be stunned, but mechanic units can.
    // *
    // ************************************************************************************************
    function StunUnit takes unit u,real d, boolean StunMagicImmue, boolean StunMechanic, boolean stack returns boolean
        local unit s
        local integer i = 0
        if (not StunMagicImmue or IsUnitType(u,UNIT_TYPE_MAGIC_IMMUNE)==false) and (not StunMechanic or IsUnitType(u, UNIT_TYPE_MECHANICAL)==false) and d>0.05 and IsUnitType(u, UNIT_TYPE_STRUCTURE)==false then // IsUnitType()==true/false due to a blizzard bug; not needed for UNIT_TYPE_HERO
            
            loop
                exitwhen U[i]==u or i>=Total
                set i=i+1
            endloop
            
            if i<Total then
                if stack then
                    call PauseTimer(T[i])
                    call TimerStart(T[i],d+TimerGetRemaining(T[i]),false,function End)
                    return true
                else
                    if d>TimerGetRemaining(T[i]) then
                        call PauseTimer(T[i])
                        call TimerStart(T[i],d,false,function End)
                        return true
                    endif
                    return false
                endif
            endif
            
            if T[Total]==null then
                set T[Total]=CreateTimer()
            endif
            set U[Total]=u
            
            set s = CreateUnit(GetOwningPlayer(u),DUMMYUNITID,GetUnitX(u),GetUnitY(u),0)
            call UnitAddAbility(s,STUNABILID)
            call UnitRemoveAbility(s, 'amov')
            call UnitApplyTimedLife(s, 'BTLF', 1.)
            call IssueInstantTargetOrderById(s,852095,u,u) // stun the unit.
            set s = null
            
            call TimerStart(T[Total],d,false,function End)
            set Total=Total+1
            return true
        endif
        return false
    endfunction
endlibrary
Here is another corrected/improved version. It supports (should support at least) stun stacking.
The forth parameter of the function StunUnit checks whether this stun should be stacked with a stun (of this system) already applied to that unit.

Quick Changelog:
- renamed constant globals, fixed indentation, added (very) few comments.
- improved timer recycling (no need to ever destroy a timer)
- fixed all known memory leaks
- added a stun stacking feature
- some performance optimizations
 
Last edited:

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,198
hgjghg, too sorry to rune your claim, but the spell you linked to can not be downloaded publically and thus can not be evidence that this is stolen. Thus I would need to see a publically available version of that spell inorder to say if it was stolen to make this or not.

Also the code that is currently at the top was based on my edited code, so eithor the system there leaked alot which would make no sense (WC3C does not approve crap) or else your claim is false.

Also who the hell is bru? Who are you for that matter, as you are new here.

---Now for something completly different.

Deaod, my version was already leakless.
Your version also probably is not any more efficent than mine ("CheckImmunity==false" is slower than "not CheckImmunity" if I am not mistaken).
Timer recycling within 1 system is stupid and pointless as it leaves to overall more timer objects at 1 time, rather use a separate timer recycle system globably within your map for maximum efficency (in my case thats 2 simple function changes).
Stun stacking is pointless as any implimentation of it would result in a rigged spell, thus blizzard does not nativly stack stuns.
Your version also does not check immunities properly like mine does, as mechanical units and buildings should also be stun immune.
Also your documentation is lacking, mine had a lot better description on why I used evey thing that I did.

Still not a bad improvememnt.

--- finally.

Matrix, I would strongly recomend making it 0.05 the smallest stun, as I did encounter situations where 0.04 would perma stun a unit. To reduce this you need to create the unit to face the target I think but currently anything below 0.05 may bug at certain times.
 
Level 2
Joined
Jan 24, 2006
Messages
14
System leak a lot cos its "author" changed data management from RB+Cache to stack.

There is original submission from wc3campaigns.
 

Attachments

  • CustomStunSystem v1.w3x
    20.2 KB · Views: 112
Level 2
Joined
Jan 24, 2006
Messages
14
Change line order != "remix".
You did nothing to improve code.

Dr Super Good
To evoid cast fails remove 'Amov' ability from dummy casters.
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,198
The cast always works, but the problem is the delay between casting and the unit getting affected by it due to the dummy having to rotate.
Thus the timer removes the buff with very small timmings before the buff is applied and so the unit remains stunned.

The fact that the gamecache version may probably be faster than this also is another thing to concider as this suffers from a O(n) opperation which may slow it down dtrastically.
 
Level 2
Joined
Jan 24, 2006
Messages
14
Dr Super Good
If you remove 'Amov' dummy wont rotate anymore, it will cast spell ignoring facing.
 
Top