1. Updated Resource Submission Rules: All model & skin resource submissions must now include an in-game screenshot. This is to help speed up the moderation process and to show how the model and/or texture looks like from the in-game camera.
    Dismiss Notice
  2. DID YOU KNOW - That you can unlock new rank icons by posting on the forums or winning contests? Click here to customize your rank or read our User Rank Policy to see a list of ranks that you can unlock. Have you won a contest and still havn't received your rank award? Then please contact the administration.
    Dismiss Notice
  3. We have recently started the 16th edition of the Mini Mapping Contest. The theme is mini RPG. Do check it out and have fun.
    Dismiss Notice
  4. Dismiss Notice
  5. The Highway to Hell has been laid open. Come along and participate in the 5th Special Effect Contest.
    Dismiss Notice
  6. Check out the Staff job openings thread.
    Dismiss Notice
Dismiss Notice
60,000 passwords have been reset on July 8, 2019. If you cannot login, read this.

[System] Stun

Discussion in 'JASS Resources' started by iAyanami, Jun 5, 2011.

  1. iAyanami

    iAyanami

    Joined:
    Dec 3, 2010
    Messages:
    143
    Resources:
    10
    Spells:
    8
    Tutorials:
    1
    JASS:
    1
    Resources:
    10
    Code (vJASS):

    library StunSystem uses Table

    //********************************************************************************
    //              Stun - Version 1.2.0.0 - By iAyanami aka Ayanami
    //********************************************************************************
    //
    //    Stun:
    //         - An easy to use system that stuns units
    //         - Able to keep track of the remaining stun duration
    //
    //    Requirements:
    //         - JASS NewGen
    //         - Table
    //
    //    Functions:
    //         - Stun.apply takes unit whichUnit, real duration, boolean stack returns nothing
    //           * whichUnit is the target to be stunned
    //           * duration is the duration of the stun
    //           * stack is to determine if the stun should be a stacking one or not
    //           * true - the stun will stack, the duration of the stun will add up with the previous duration
    //           * false - the stun will not stack, the unit will be stunned for the longer stun duration
    //
    //         - Stun.getDuration takes unit whichUnit returns real
    //           * whichUnit is the target to check
    //           * returns the remaining stun duration
    //
    //         - Stun.stop takes unit whichUnit returns nothing
    //           * removes stun from the target
    //
    //    How to import:
    //         - Copy the whole "Stun" Trigger Folder into your map
    //         - Save the map. Close and re-opem the map.
    //         - You should have a new unit (Stun Dummy), ability (Stun (System)) and buff (Stun (System)) created
    //         - Read through the Configuration part of the code
    //
    //    Credits:
    //         - Bribe for Table
    //
    //********************************************************************************
    //                                CONFIGURABLES
    //********************************************************************************

    globals
        // timer period. lower the value, the more accurate but might cause decrease in
        // performance
        private constant real PERIOD = 0.03125

        // raw code of ability "Stun (System)"
        private constant integer ABILID = 'ASTN'
       
        // raw code of buff "Stun (System)"
        private constant integer BUFFID = 'BSTN'
       
        // raw code of unit "Stun Dummy"
        private constant integer STUNID = 'sTUN'
    endglobals

    //********************************************************************************
    //                                     CODE
    //********************************************************************************

    // initialization
    module Init
        private static method onInit takes nothing returns nothing
            set table = Table.create()
            set caster = CreateUnit(Player(13), STUNID, 0, 0, 0)
           
            call UnitAddAbility(caster, ABILID)
        endmethod
    endmodule

    struct Stun extends array
        private unit u
        private real dur

        private thistype next
        private thistype prev
       
        private static Table table
        private static timer t = CreateTimer()
        private static unit caster
        private static integer count = 0
       
        // remove the stun and deallocate
        private method destroy takes nothing returns nothing
            call UnitRemoveAbility(this.u, BUFFID)
           
            if this.next != 0 then
                set this.next.prev = this.prev
            endif
               
            set this.prev.next = this.next
            set this.dur = 0
            set this.prev = thistype(0).prev
            set thistype(0).prev = this
           
            if thistype(0).next == 0 then
                call PauseTimer(t)
            endif
               
            call table.remove(GetHandleId(this.u))
        endmethod
       
        // iterating through all instances every PERIOD
        private static method iterate takes nothing returns nothing
            local thistype this = thistype(0)
           
            loop
                set this = this.next
                exitwhen this == 0
                if this.dur <= 0 or IsUnitType(this.u, UNIT_TYPE_DEAD) or GetUnitTypeId(this.u) == 0 then
                    call this.destroy()
                else
                    set this.dur = this.dur - PERIOD
                endif
            endloop
        endmethod
       
        // immediately removes stun for the specified unit
        // ex: call Stun.stop(whichTarget)
        static method stop takes unit u returns nothing
            local integer id = GetHandleId(u)
           
            if table.has(id) then
                call thistype(table[id]).destroy()
            endif
        endmethod
       
        // gets the duration left for stun, not stunned units always return 0
        // ex: local real r = Stun.getDuration(whichTarget)
        static method getDuration takes unit u returns real
                return thistype(table[GetHandleId(u)]).dur
        endmethod
       
        // stunning specified target and to see if the stun is a stacking one or not
        // ex: call Stun.apply(whichTarget, 5.0, false)
        static method apply takes unit u, real dur, boolean b returns nothing
            local thistype this
            local integer id = GetHandleId(u)
           
            if table.has(id) then
                set this = table[id]
            else    
                if thistype(0).prev == 0 then
                    set count = count + 1
                    set this = count
                else
                    set this = thistype(0).prev
                    set thistype(0).prev = thistype(0).prev.prev
                endif
               
                if thistype(0).next == 0 then
                    call TimerStart(t, PERIOD, true, function thistype.iterate)
                else
                    set thistype(0).next.prev = this
                endif
               
                set this.next = thistype(0).next
                set thistype(0).next = this
                set this.prev = thistype(0)
                set table[id] = this
                set this.u = u
                set this.dur = 0
               
                call IssueTargetOrder(caster, "firebolt", this.u)
            endif
           
            if b and dur > 0 then
                set this.dur = this.dur + dur
            else
                if this.dur < dur then
                    set this.dur = dur
                endif
            endif
        endmethod

        implement Init
    endstruct

    endlibrary
     


    Examples:

    Basic ability that stuns a target for 2.0 seconds and non-stacking.
    • Stun
      • Events
        • Unit - A unit Starts the effect of an ability
      • Conditions
        • (Ability being cast) Equal to Stun
      • Actions
        • Custom script: call Stun.apply(GetSpellTargetUnit(), 2.0, false)


    This time, a more flexible stun. Stuns depending on the caster's agility and non-stacking.
    • Stun
      • Events
        • Unit - A unit Starts the effect of an ability
      • Conditions
        • (Ability being cast) Equal to Stun
      • Actions
        • Set TempInt = (Agility of (Triggering unit) (Include bonuses))
        • Custom script: call Stun.apply(GetSpellTargetUnit(), udg_TempInt, false)


    Basic ability that stuns a target for 2.0 seconds and stacks.
    • Stun
      • Events
        • Unit - A unit Starts the effect of an ability
      • Conditions
        • (Ability being cast) Equal to Stun
      • Actions
        • Set TempInt = (Agility of (Triggering unit) (Include bonuses))
        • Custom script: call Stun.apply(GetSpellTargetUnit(), udg_TempInt, true)


    Closing:
    I'm open to any more possible functions that can be implemented into this system. Do suggest some. Thanks!

    Changelogs:
    Version 1.2.0.0:
    - Removed Alloc
    - Renamed .get to .getDuration
    - Renamed .use to .apply
    - Made a check to start/pause timer accordingly, rather than letting it run forever
    - Added a GetUnitTypeId(this.u) == 0 check
    - Used a module initializer
    Version 1.1.0.0:
    - Fixed minor bugs
    - Renamed library to StunSystem
    - Added a boolean parameter to Stun.use function to allow user to specify if the stun is a stacking one or not
    - Added a new function, Stun.stop which removes stun from the specified unit
    Version 1.0.0.0:
    - Release.
     

    Attached Files:

    • Stun.w3x
      File size:
      65.9 KB
      Views:
      379
    Last edited: Mar 31, 2012
  2. Magtheridon96

    Magtheridon96

    Joined:
    Dec 12, 2008
    Messages:
    6,006
    Resources:
    26
    Maps:
    1
    Spells:
    8
    Tutorials:
    7
    JASS:
    10
    Resources:
    26
    I don't recommend using the UnitAlive native (WC3 Optimizer breaks it)
    Here's an idea for a function:
    static method stop takes nothing returns nothing


    edit

    You should change the first line to this:
    library StunSystem requires Table, Alloc
    (Since Stun is too generic and it's already used by J4L)
     
  3. Adiktuz

    Adiktuz

    Joined:
    Oct 16, 2008
    Messages:
    9,674
    Resources:
    23
    Models:
    2
    Packs:
    1
    Maps:
    1
    Spells:
    16
    Tutorials:
    1
    JASS:
    2
    Resources:
    23
    hmmm... a custom stun system... might be usefull... ^_^
     
  4. PurgeandFire

    PurgeandFire

    Code Moderator

    Joined:
    Nov 11, 2006
    Messages:
    7,426
    Resources:
    18
    Icons:
    1
    Spells:
    4
    Tutorials:
    9
    JASS:
    4
    Resources:
    18
    set u = null


    Parameters don't need to be nulled.

    ----

    Also, I didn't test it, but your system might break under certain circumstances. For example, consider this situation:

    Unit gets stunned for 6 seconds. Immediately afterward, the same unit gets stunned for 1 second. The stun ends up lasting only 1 second.

    You'll probably have to do something like:
    Code (vJASS):
    if this.dur < dur then
        set this.dur = dur
    endif


    Or something along those lines.

    EDIT: Sorry I accidentally used ljass tags instead of jass tags. :p
     
    Last edited: Jun 6, 2011
  5. iAyanami

    iAyanami

    Joined:
    Dec 3, 2010
    Messages:
    143
    Resources:
    10
    Spells:
    8
    Tutorials:
    1
    JASS:
    1
    Resources:
    10
    I always used to think that a new stun would override the old one. Guess I was wrong @_@. Will fix it.

    EDIT
    Updated to Version 1.1.0.0

    EDIT
    Just want to ask, does this belong here or would the Spell Submission Section be better?
     
    Last edited: Jun 6, 2011
  6. Magtheridon96

    Magtheridon96

    Joined:
    Dec 12, 2008
    Messages:
    6,006
    Resources:
    26
    Maps:
    1
    Spells:
    8
    Tutorials:
    7
    JASS:
    10
    Resources:
    26
    It definitely belongs here :)
    Any vJass system/snippet that has no object data (other than an externalblock that is) belongs here :)

    edit

    Basicly, the Jass section allows you to implement systems into your maps without having to go through the trouble of handling a testmap :p
     
  7. Nestharus

    Nestharus

    Joined:
    Jul 10, 2007
    Messages:
    6,146
    Resources:
    8
    Spells:
    3
    Tutorials:
    4
    JASS:
    1
    Resources:
    8
    I'll make an Lua/UnitIndexer version of this =).
     
  8. Magtheridon96

    Magtheridon96

    Joined:
    Dec 12, 2008
    Messages:
    6,006
    Resources:
    26
    Maps:
    1
    Spells:
    8
    Tutorials:
    7
    JASS:
    10
    Resources:
    26
    D:< That's mean!
     
  9. Bribe

    Bribe

    Joined:
    Sep 26, 2009
    Messages:
    8,083
    Resources:
    25
    Maps:
    3
    Spells:
    10
    Tutorials:
    3
    JASS:
    9
    Resources:
    25
    "if this.dur <= 0 or IsUnitType(this.u, UNIT_TYPE_DEAD) then"

    This line should be appended with "or GetUnitTypeId(this.u) == 0" because, if a unit is removed or exploded, UNIT_TYPE_DEAD will return "false".

    Either this or use the UnitAlive native.
     
  10. Magtheridon96

    Magtheridon96

    Joined:
    Dec 12, 2008
    Messages:
    6,006
    Resources:
    26
    Maps:
    1
    Spells:
    8
    Tutorials:
    7
    JASS:
    10
    Resources:
    26
    I'd go with "this" ;)
    The UnitAlive native should be avoided until LuckyParser is released :p
     
  11. Bribe

    Bribe

    Joined:
    Sep 26, 2009
    Messages:
    8,083
    Resources:
    25
    Maps:
    3
    Spells:
    10
    Tutorials:
    3
    JASS:
    9
    Resources:
    25
    If you set "dur" to 0 from within the destroy method, you can shorten this:

    Code (vJASS):
        static method get takes unit u returns real
            local integer id = GetHandleId(u)
           
            if table.has(id) then
                return thistype(table[id]).dur
            else
                return 0.
            endif
        endmethod


    To this:

    Code (vJASS):
        static method get takes unit u returns real
            return thistype(table[GetHandleId(u)]).dur
        endmethod


    Also, 0.03125 is more practical for the timer.

    This still needs to have the GetUnitTypeId == 0 check to compliment the UNIT_TYPE_DEAD.

    The timer should not *always* be running.

    The initializer should be a module.

    You don't need to require Alloc from this. If you recycle using the "prev" variable then you can also eliminate an array that Alloc generates.

    Stun.get -> Stun.getDuration

    Stun.use -> Stun.apply
     
  12. Adiktuz

    Adiktuz

    Joined:
    Oct 16, 2008
    Messages:
    9,674
    Resources:
    23
    Models:
    2
    Packs:
    1
    Maps:
    1
    Spells:
    16
    Tutorials:
    1
    JASS:
    2
    Resources:
    23
    would using

    GetUnitTypeId(u) == 0

    be the same as just using

    u == null?
     
  13. Bribe

    Bribe

    Joined:
    Sep 26, 2009
    Messages:
    8,083
    Resources:
    25
    Maps:
    3
    Spells:
    10
    Tutorials:
    3
    JASS:
    9
    Resources:
    25
    No, because the handle ID is not 0, because remember variables are pointers to handle IDs.
     
  14. iAyanami

    iAyanami

    Joined:
    Dec 3, 2010
    Messages:
    143
    Resources:
    10
    Spells:
    8
    Tutorials:
    1
    JASS:
    1
    Resources:
    10
    Updated to v1.2.0.0
     
  15. Bribe

    Bribe

    Joined:
    Sep 26, 2009
    Messages:
    8,083
    Resources:
    25
    Maps:
    3
    Spells:
    10
    Tutorials:
    3
    JASS:
    9
    Resources:
    25
    I like it. Approved.
     
  16. -Kobas-

    -Kobas-

    Joined:
    Jan 17, 2010
    Messages:
    5,895
    Resources:
    28
    Icons:
    1
    Tools:
    2
    Maps:
    10
    Spells:
    4
    Template:
    5
    Tutorials:
    6
    Resources:
    28
    Epic script indeed :)
    But I must report small error, in your examples you use wrong method.
    Instead something like
    call Stun.use(GetSpellTargetUnit(), udg_TempInt, true)

    there should be
    call Stun.apply(GetSpellTargetUnit(), udg_TempInt, true)

    It isn't big deal but still it can make trouble to some people :)
     
  17. Magtheridon96

    Magtheridon96

    Joined:
    Dec 12, 2008
    Messages:
    6,006
    Resources:
    26
    Maps:
    1
    Spells:
    8
    Tutorials:
    7
    JASS:
    10
    Resources:
    26
    Nestharus, you posted in the wrong thread again ._.
    Also, you should really go to sleep bro D:
     
  18. Nestharus

    Nestharus

    Joined:
    Jul 10, 2007
    Messages:
    6,146
    Resources:
    8
    Spells:
    3
    Tutorials:
    4
    JASS:
    1
    Resources:
    8
    Yea, I know, I'm hella tired =o. Haven't gone to bed yet and it's 7 am and I've been up for like 4 days straight ^)^.
     
  19. Laiev

    Laiev

    Joined:
    Oct 11, 2008
    Messages:
    273
    Resources:
    1
    Template:
    1
    Resources:
    1
    I'm with you Nestharus, you know -.- while is 11 pm to you, is 4 am for me D: and I'm always talking with you lol.
     
  20. Nestharus

    Nestharus

    Joined:
    Jul 10, 2007
    Messages:
    6,146
    Resources:
    8
    Spells:
    3
    Tutorials:
    4
    JASS:
    1
    Resources:
    8
    Design implementation of this is incorrect.

    Needs to be rewritten. The design implementation of my own Stun resource is also incorrect, so both should be graveyarded in light of a good implementation.


    The good implementation is a core that takes effects and applies them using a dummy caster. From here, the effect resources are just simple Lua scripts or maps with objects in them =). As there are only a limited number of effects, one thread can be created that contains all of them similar to j4l's Status resource (but better of course).


    I don't have time to code this now, so whoever gets it coded first wins (unless ofc their implementation is bad, in which case I will overtake you with my own and tell you that you have been pwned, fuahahhaa). Let the best one win and let this one and mine rest in peace in the graveyard where they belong.