Snippet Stack Safety (Pack)

Discussion in 'Systems and Snippets' started by Jesus4Lyf, Jul 23, 2009.

  1. Jesus4Lyf

    Jesus4Lyf Good Idea™

    Ratings:
    +394 / 0 / -0
    Stack Safety​

    (Snippet Pack)​


    Requirements:
    - Jass NewGen
    - AIDS (required by all)

    Overview Description:
    This is essentially a snippet pack based on recording the level of certain things so that they are not prematurely removed due to poor multi-instancability in the native functions. Released by request. :)


    Pause Safety:
    JASS:
    library PauseSafety uses AIDS
        private struct UnitData extends array
            //! runtextmacro AIDS()
            integer pauseLevel
            private method AIDS_onDestroy takes nothing returns nothing
                set this.pauseLevel=0
            endmethod
        endstruct
        function SafePause takes unit whichUnit, boolean flag returns nothing
            local UnitData dat=UnitData[whichUnit]
            if flag then
                set dat.pauseLevel=dat.pauseLevel+1
                call PauseUnit(whichUnit,true)
            else
                set dat.pauseLevel=dat.pauseLevel-1
                if dat.pauseLevel<=0 then
                    call PauseUnit(whichUnit,false)
                    set dat.pauseLevel=0
                endif
            endif
        endfunction
    endlibrary
    Pause safety allows you to use unit pausing without worry about unpause having poor multi-instancing. Example: Spell pauses a unit for 5 seconds. Spell is cast twice, exactly 4 seconds apart. Usually, this would result in the second instance lasting 1 second. Using SafePause(unit, pause/unpause boolean), the pause count is recorded, so only when the last pause is released will the unit be unpaused.

    Invulnerability Safety:
    JASS:
    library InvulnerableSafety uses AIDS
            private struct UnitData extends array
            //! runtextmacro AIDS()
            integer invulnLevel
            private method AIDS_onDestroy takes nothing returns nothing
                set this.invulnLevel=0
            endmethod
        endstruct
        function SafeInvulnerable takes unit whichUnit, boolean flag returns nothing
            local UnitData dat=UnitData[whichUnit]
            if flag then
                set dat.invulnLevel=dat.invulnLevel+1
                call SetUnitInvulnerable(whichUnit,true)
            else
                set dat.invulnLevel=dat.invulnLevel-1
                if dat.invulnLevel<=0 then
                    call SetUnitInvulnerable(whichUnit,false)
                    set dat.invulnLevel=0
                endif
            endif
        endfunction
    endlibrary
    Same principle as PauseSafety. If two spells make a unit invulnerable for 5 seconds, and cast 4 seconds apart, the second instance will only last 1 second. With SafeInvulnerable(unit, invulnerable/vulnerable boolean), it will be made vulnerable after the last invulnerability has been revoked (the number of invulnerabilities on a unit is once again recorded).
     
    • Like Like x 3
  2. Renendaru

    Renendaru (Evol)ution is nothing without love.

    Ratings:
    +309 / 0 / -0
    Nice snippet, definitely going to use this.

    Edit: Stress tested SafePause and it worked like a charm, units were never perma stunned.
     
    • Like Like x 1
  3. Jesus4Lyf

    Jesus4Lyf Good Idea™

    Ratings:
    +394 / 0 / -0
    Beautiful. Thanks for test and comment (+rep). :)
     
  4. Viikuna

    Viikuna No Marlo no game.

    Ratings:
    +265 / 0 / -0
    I did functions like these too once. Library had invulnerable, pause, show unit , set pathing and other stuff like that.

    They are usefull, but you should make them use GetUnitUserData instead of AIDS, so they can work with any indexing system people use ( as long as it is unit user data based ).
     
  5. Kenny

    Kenny Back for now.

    Ratings:
    +202 / 0 / -0
    Awesome idea, these have been needed for a long time. I'm surprised no one has thought of submitting something like this before. And AIDS makes it so simple.

    Oh, and the script for SafeInvulnerable uses: PauseUnit() not SetUnitInvulnerable() or whatever it is. May want to quickly change that.

    Anywho, these are mad. Nice work. :thup:
     
    • Like Like x 1
  6. Viikuna

    Viikuna No Marlo no game.

    Ratings:
    +265 / 0 / -0
    Well, it is one of the cool sides of unit indexing. It gets even cooler when you start to play with vertex color, scale, timescale and other such properties.

    ( The newest UnitProperties version has that stuff, but Cassiel hasnt released it yet in wc3c if I remember correctly )
     
  7. Gwypaas

    Gwypaas hook DoNothing MakeGUIUsersCrash

    Ratings:
    +50 / 0 / -0
    Or just use the new standarized function GetUnitId() that all unit indexing system on Wc3c uses so you can just swap between them without any problem. And monopolizing UnitUserData fails really hard.
     
  8. Viikuna

    Viikuna No Marlo no game.

    Ratings:
    +265 / 0 / -0
    Yea, thats what I meant. You should use that GetUnitIndex or GetUnitUserData or whatever function that works for any indexing system.

    edit. Well yea, that GetUnitIndex is probably better, since not all of those systems use UnitUserData.
     
  9. Jesus4Lyf

    Jesus4Lyf Good Idea™

    Ratings:
    +394 / 0 / -0
    >the script for SafeInvulnerable uses: PauseUnit() not SetUnitInvulnerable() or whatever it is. May want to quickly change that.
    Thanks kenny, fixed. :thup:
     
  10. Kenny

    Kenny Back for now.

    Ratings:
    +202 / 0 / -0
    A friend of mine just told me how useful these were for what he was working on, but he said he had a need for a pathing one as well, a quick update would be nice. :D

    JASS:
    library PathingSafety uses AIDS
        private struct UnitData extends array
            //! runtextmacro AIDS()
            integer pathLevel
            private method AIDS_onDestroy takes nothing returns nothing
                set this.pathLevel=0
            endmethod
        endstruct
        function SafePathing takes unit whichUnit, boolean flag returns nothing
            local UnitData dat=UnitData[whichUnit]
            if not flag then
                set dat.pathLevel=dat.pathLevel+1
                call SetUnitPathing(whichUnit,false)
            else
                set dat.pathLevel=dat.pathLevel-1
                if dat.pathLevel<=0 then
                    call SetUnitPathing(whichUnit,true)
                    set dat.pathLevel=0
                endif
            endif
        endfunction
    endlibrary


    JASS:
    library ShowUnitSafety uses AIDS
        private struct UnitData extends array
            //! runtextmacro AIDS()
            integer showLevel
            private method AIDS_onDestroy takes nothing returns nothing
                set this.showLevel=0
            endmethod
        endstruct
        function SafeShowUnit takes unit whichUnit, boolean flag returns nothing
            local UnitData dat=UnitData[whichUnit]
            if not flag then
                set dat.showLevel=dat.showLevel+1
                call ShowUnit(whichUnit,false)
            else
                set dat.showLevel=dat.showLevel-1
                if dat.showLevel<=0 then
                    call ShowUnit(whichUnit,true)
                    set dat.showLevel=0
                endif
            endif
        endfunction
    endlibrary


    (I had a spare minute or two, there you go. :))
     
  11. Kuberr24

    Kuberr24 Well-Known Member

    Ratings:
    +28 / 0 / -0
    Is my world editor broken? If I use pause or hide unit on unit x, then later use it later on another unit, the timing is alright, it doesn't screw up the second pause/hide by making it last only until the other unit becomes unpaused/shown

    EDIT: oops I understand, you mean if this happens on the SAME unit.

    well I simply use a hashtable to store a boolean value for unit X. if boolean "is_this_unit_still_under_the_effect_of_the_spell" is true, then I don't unpause. Seems more simple then importing AIDS + a whole bunch of functions.
     
  12. Jesus4Lyf

    Jesus4Lyf Good Idea™

    Ratings:
    +394 / 0 / -0
    >well I simply use a hashtable to store a boolean value for unit X. if boolean "is_this_unit_still_under_the_effect_of_the_spell" is true, then I don't unpause. Seems more simple then importing AIDS + a whole bunch of functions.

    It's not. XD
    But use what you will.

    Actually, checking for a buff is a terrible way to do this. What if you have 50 spells in a map? :D

    What if 3 pause a unit at once? Gosh, you're in trouble. :p

    kenny!, I'll review that when I get home and add it and such. Thanks! :thup:
     
  13. Romek

    Romek Super Moderator Staff Member

    Ratings:
    +961 / 0 / -0
    Demo Map?
    I believe you've got more space now.
     
  14. Jesus4Lyf

    Jesus4Lyf Good Idea™

    Ratings:
    +394 / 0 / -0
    Bah. I'll get ya a demo map some time. <_<

    Kenny!, did you test those? I think it should be "if not flag then"... :thup:
     
  15. Kuberr24

    Kuberr24 Well-Known Member

    Ratings:
    +28 / 0 / -0
    I don't need newgen. I don't need to import anything. I don't use global variables anywhere. It's perfectly MUI. I don't check for buffs with pause because paused units their buffs never expire....

    I'm not sure why you assume otherwise?

    it's basicly local handle vars with a safe hashtable instead of a gamecache
    The only thing *some people might dislike* is the fact I use dynamic timers to time my effects.
     
  16. Jesus4Lyf

    Jesus4Lyf Good Idea™

    Ratings:
    +394 / 0 / -0
    I used to use GUI. You can use whatever you like. :D

    This tool is just for those who want nice easy JASS stuff. A lot of people use PauseUnit and don't realise that well, it's naturally poor for MUI. :p

    Even dynamic timers are fine in my books as long as they're not destroyed and still left running. :)
     
  17. Kenny

    Kenny Back for now.

    Ratings:
    +202 / 0 / -0
    Hahaha, no I didn't I just wrote them up on the spot, and yes they should be "if not flag then".

    My bad. :p But yeah they should be fine after you fix that I guess.
     
  18. Darthfett

    Darthfett Super Mod

    Ratings:
    +614 / 0 / -0
    The code is written well (as usually), and it's very useful. I only wish I had thought of it first. :p

    Approved!
     
  19. Bribe

    Bribe vJass errors are legion

    Ratings:
    +67 / 0 / -0
    I hate to bump an old thread, but this library is currently split into four libraries... I have consolidated it into something much more mainstreamed using the two functions provided by Jesus4Lyf and the other two provided by Kenny;

    JASS:
    library SafetyStack requires AIDS
        
        /**
         * API
         * ¯¯¯
         * call SafePause($unit)
         * call SafeShow($unit)
         * call SafeInvulnerable($unit)
         * call SafePathing($unit)
         */
        
        private struct UnitData extends array
            //! textmacro SafetyStack__Vars takes TitleA,TitleB,TitleC,TitleD
            integer $TitleA$Size
            integer $TitleB$Size
            integer $TitleC$Size
            integer $TitleD$Size
            
            static method assign takes nothing returns boolean
                local thistype dat = AIDS_GetIndexOfEnteringUnit()
                set dat.$TitleA$Size=0
                set dat.$TitleB$Size=0
                set dat.$TitleC$Size=0
                set dat.$TitleD$Size=0
                return false
            endmethod
            //! endtextmacro
            //! runtextmacro SafetyStack__Vars("Pause","Show","Invulnerable","Pathing")
            
            static method onInit takes nothing returns nothing
                call AIDS_RegisterOnEnter(Filter(function thistype.assign))
            endmethod
            
        endstruct
        
        //! textmacro SafetyStack__Func takes Title, Func, Swap
                function Safe$Title$ takes unit whichUnit, boolean flag returns nothing
                    local UnitData dat=GetUnitId(whichUnit)
                    if $Swap$ (flag) then
                        set dat.$Title$Size=dat.$Title$Size+1
                        call $Func$(whichUnit,flag)
                    else
                        set dat.$Title$Size=dat.$Title$Size-1
                        if dat.$Title$Size<=0 then
                            set dat.$Title$Size=0
                            call $Func$(whichUnit,flag)
                        endif
                    endif
                endfunction
        //! endtextmacro
        //! runtextmacro SafetyStack__Func("Pause","PauseUnit","")
        //! runtextmacro SafetyStack__Func("Show","ShowUnit","not")
        //! runtextmacro SafetyStack__Func("Invulnerable","SetUnitInvulnerable","")
        //! runtextmacro SafetyStack__Func("Pathing","SetUnitPathing","not")
        
    endlibrary
     
  20. Kenny

    Kenny Back for now.

    Ratings:
    +202 / 0 / -0
    Unfortunately, this snippet is now outdated thanks to Status. So this should probably be in the graveyard or something anyway.

    Also, I don't think you used AIDS correctly in your snippet (you need to use: //! runtextmacro AIDS()) and your first textmacro is a bit useless.

    But a good idea turning four libraries into one. :)
     

Share This Page