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 haven't received your rank award? Then please contact the administration.
    Dismiss Notice
  3. Lead your forces to battle in the 15th Techtree Contest. The call is yours, commander!
    Dismiss Notice
  4. The reforging of the races is complete. Come see the 14th Techtree Contest Results.
    Dismiss Notice
  5. It's time to choose your horse in the race - the 32nd Modeling Contest Poll is up!
    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.

[vJASS] Optimizing my spell

Discussion in 'Triggers & Scripts' started by dardas, Oct 5, 2012.

  1. dardas

    dardas

    Joined:
    Sep 12, 2008
    Messages:
    649
    Resources:
    0
    Resources:
    0
    Well, hello.
    I've made a vjass spell, using a struct, after a year of being away from WC in general.. Been quite a hassle, but managed to put something together,
    the problem is, I'm not sure if its as efficient as possible.

    Anyhow, about the spell:
    Its a single unit ability, called Chained Dagger.
    Technically, once cast on a unit, it gets replaced with a new ability for duration seconds.
    after the duration is passed, it restores the original ability.
    Right now it works quite well, but theres a 0.5 second lag or something around that at the first cast of the spell.

    heres the code:
    Chained Dagger

    Code (vJASS):

    library ChainedDagger initializer onInit/*
    */
     uses                                /*
    */
         SpellEvent                      /*
    */
         TimerUtils
       
        struct ChainedDagger
           
            public static integer Ability_Identifier = 'A001'
            public static integer NewAbility_Identifier = 'A002'
            public static integer AuraSpellBook_Identifier = 'A005'
           
            public static timer Timer
            public static real TimerSpeed = 0.032
           
            public static thistype array Instances
            public static integer Counter = 0
           
            public unit caster
            public unit target
            public real duration
            public integer id
            public boolean started
           
            public static method create takes unit caster, unit target, real duration returns thistype
                local thistype d = thistype.allocate()
                set d.caster = caster
                set d.target = target
                set d.duration = duration
                set d.id = d.assignIdentifier()
                set d.started = false
                return d
            endmethod
           
            public method assignIdentifier takes nothing returns integer
                set Instances[ChainedDagger.Counter] = this
                set ChainedDagger.Counter = ChainedDagger.Counter + 1
                return ChainedDagger.Counter - 1
            endmethod
           
            static method operator [] takes integer id returns thistype
                if (id >= Counter) then
                    return -1
                endif
                return Instances[id]
            endmethod
           
            public method startCast takes nothing returns nothing
                local player p = GetOwningPlayer(.caster)
               
                call SetPlayerAbilityAvailable(p, ChainedDagger.Ability_Identifier, false)
                call UnitAddAbility(.caster, ChainedDagger.NewAbility_Identifier)
                call SetUnitAbilityLevel(.caster, ChainedDagger.NewAbility_Identifier, GetUnitAbilityLevel(.caster, ChainedDagger.Ability_Identifier))
                call UnitAddAbility(.target, ChainedDagger.AuraSpellBook_Identifier)
               
                set .started = true
               
                set p = null
            endmethod
           
            public method stopCast takes nothing returns nothing
                local player p = GetOwningPlayer(.caster)
               
                call SetPlayerAbilityAvailable(p, ChainedDagger.Ability_Identifier, true)
                call UnitRemoveAbility(.caster, ChainedDagger.NewAbility_Identifier)
                call UnitRemoveAbility(.target, ChainedDagger.AuraSpellBook_Identifier)
               
                set p = null
                call .destroy()
            endmethod
           
            private method destroy takes nothing returns nothing
                //Fix the indexing system
                local integer cnt = 0
                local integer max = ChainedDagger.Counter
               
                loop
                set ChainedDagger[cnt].id = ChainedDagger[cnt].id - 1
                set cnt = cnt + 1
                exitwhen cnt <= max
                endloop
                set ChainedDagger.Instances[.id] = -1
               
                //Remove the leaking data
                set .caster = null
                set .target = null
                set .started = false
            endmethod
           
            public static method onUpdate takes nothing returns nothing
                local integer data
                local thistype d
               
                if (ChainedDagger.Counter <= 0) then
                    set ChainedDagger.Counter = 0
                    call ReleaseTimer(ChainedDagger.Timer)
                endif
               
                set data = GetTimerData(ChainedDagger.Timer)
               
                set d = ChainedDagger[data]
               
                if (d.started == true) then
                    set d.duration = d.duration - ChainedDagger.TimerSpeed
                    if (d.duration <= 0) then
                        call d.stopCast()
                    endif
                endif
               
                if (data < ChainedDagger.Counter - 1) then
                    call SetTimerData(ChainedDagger.Timer, data + 1)
                else
                    call SetTimerData(ChainedDagger.Timer, 0)
                endif
            endmethod
           
            public static method onSpellCast takes nothing returns nothing
                local unit caster = SpellEvent.CastingUnit
                local unit target = SpellEvent.TargetUnit
                local real duration = 3 // 3 seconds so I could test the lag thingy, it only happens on the first run.
                                        // there's going to be an equation used by it, but should suffice for now.
               
                local thistype d = thistype.create(caster, target, duration)
                call d.startCast()
                if (ChainedDagger.Counter == 1) then
                    set ChainedDagger.Timer = NewTimerEx(0)
                    call TimerStart(ChainedDagger.Timer, ChainedDagger.TimerSpeed, true, function ChainedDagger.onUpdate)
                endif
               
                set caster = null
                set target = null
            endmethod
           
        endstruct
       
        public function onInit takes nothing returns nothing
            call RegisterSpellCastResponse(ChainedDagger.Ability_Identifier, ChainedDagger.onSpellCast)
        endfunction
       
    endlibrary
     



    P.S: I've always been bad at explaining stuff, tell me if I should give more details regarding something.. ><
    Thanks for the help in advance.
     
  2. defskull

    defskull

    Joined:
    Mar 27, 2008
    Messages:
    7,978
    Resources:
    17
    Spells:
    17
    Resources:
    17
    Why don't you preload the ability associated with it ?
     
  3. dardas

    dardas

    Joined:
    Sep 12, 2008
    Messages:
    649
    Resources:
    0
    Resources:
    0
    The lag is really the least of my problems I guess, something in the code must've caused the lag, or wc became really screwed up in the year I was gone, lol.
     
  4. defskull

    defskull

    Joined:
    Mar 27, 2008
    Messages:
    7,978
    Resources:
    17
    Spells:
    17
    Resources:
    17
    Try this;
    • SPELLS PRELOADING
      • Events
        • Map initialization
      • Conditions
      • Actions
        • Custom script: local unit u = CreateUnit(Player(15), 'hfoo', 0.00, 0.00, 0.00)
        • Custom script: call UnitAddAbility(u, 'A002')
        • Custom script: call UnitAddAbility(u, 'A005')
        • Custom script: call RemoveUnit(u)
        • Custom script: set u = null


    You must preload the abilities associated with that spell to prevent lag on first cast.
    The lag would occur at the Loading Screen (increasing its Loading Speed by bit).
    Rather than lag on first cast, better for you to load it in Loading Screen right ?

    I did not test it yet (because I don't have vJASS) but I highly anticipate it would be this as the solution to the first cast lag issues.
     
  5. PurgeandFire

    PurgeandFire

    Code Moderator

    Joined:
    Nov 11, 2006
    Messages:
    7,426
    Resources:
    18
    Icons:
    1
    Spells:
    4
    Tutorials:
    9
    JASS:
    4
    Resources:
    18
    It might be because of TimerUtils. Vexorian updated it so that it would do the init on the first "NewTimer" call rather than on actual initialization. This was because people were complaining about the initialization method--that it would not work if you use the function in a module initializer. Vexorian opted to do an evaluation upon first call rather than doing a module initializer, so that might be why you get the lag.

    Perhaps try using this instead?
    http://www.hiveworkshop.com/forums/graveyard-418/system-timerutilsex-204500/

    See if it fixes it.

    Otherwise, it might be the ability as defskull said.
     
  6. dardas

    dardas

    Joined:
    Sep 12, 2008
    Messages:
    649
    Resources:
    0
    Resources:
    0
    Meh, apparently defskull's idea fixed it, thats kinda odd, never happend to me before,
    also, switched to TimerUtilsEx..

    Well, is there any way to improve the code? The build of the struct, etc..
    That was the actual question, after all xD
     
  7. defskull

    defskull

    Joined:
    Mar 27, 2008
    Messages:
    7,978
    Resources:
    17
    Spells:
    17
    Resources:
    17
    It only happens to abilities that has 4 levels and beyond.
    Just like DotA, you preload abilities associated with that Hero when you picked the Hero, that is why there is a lag when a new Hero enters the map, it is actually preloading it.
     
  8. baassee

    baassee

    Joined:
    Nov 14, 2008
    Messages:
    3,220
    Resources:
    17
    Spells:
    14
    Tutorials:
    3
    Resources:
    17
    Why is everything public? I mean it's in a library, the struct ain't private, thus you can reach the struct even without the public keyword.