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

In need of assistance..

Status
Not open for further replies.
Level 7
Joined
Oct 14, 2008
Messages
340
Alright so here's the deal, I have no idea whats wrong with my code here, gone over it tons of times.. so I'll once again harness the helpful power of the hive. Basically "trueshot" is a passive ability that adds +1 agility for X amount of time on every successful attack. The current code works fine for one unit, but when another hero steps in.. all hell breaks loose.. Really not sure whats wrong with my code.. Can anyone help? Maybe tell me how inefficient it might be too :p

JASS:
library Trueshot initializer init

    private struct agibonus
        unit u
        
        static agibonus array ab
        static integer index = 0
        
        method onDestroy takes nothing returns nothing
            set .u = null
        endmethod
        
        static method timerExpire takes nothing returns nothing
            local agibonus a = agibonus.ab[0]
            local integer i = 1
            call SetHeroAgi(a.u, GetHeroAgi(a.u, false)-1, true)
            call a.destroy()
            call DestroyTimer(GetExpiredTimer())
            
            loop
                exitwhen i > agibonus.index
                set agibonus.ab[i-1] = agibonus.ab[i]
                set i = i+1
            endloop
            set agibonus.index = agibonus.index-1
        endmethod
        
        static method create takes unit u, integer slvl returns agibonus
            local agibonus a = agibonus.allocate()
            local timer tim = CreateTimer()
            local real time = 3.5+(0.5*slvl)
            set a.u = u
            call SetHeroAgi(u, GetHeroAgi(u, false)+1, true)
            set agibonus.ab[agibonus.index] = a
            set agibonus.index = agibonus.index+1
            call TimerStart(tim, time, false, function agibonus.timerExpire)
            
            return a
        endmethod
    endstruct
    
    private struct data
        unit attacker
        unit attacked
        integer slvl
        trigger dmgtrigger
        triggeraction act
        timer tim
        
        static data array dat
        static integer index = 0
        
        method onDestroy takes nothing returns nothing
            call TriggerRemoveAction(.dmgtrigger, .act)
            call DestroyTrigger(.dmgtrigger)
            set .attacker = null
            set .attacked = null
        endmethod
        
        static method timerExpire takes nothing returns nothing
            local timer tim = GetExpiredTimer()
            local data d
            local integer i = 0
            local integer q = 0
            local integer z = 0
            local boolean b = false
            
            loop
                exitwhen i > data.index
                exitwhen b == true
                set d = data.dat[i]
                if d.tim == tim then
                    set b = true
                    call DestroyTimer(tim)
                    call d.destroy()
            
                    loop
                        set q = data.index
                        set z = i+1
                        set data.dat[z-1] = data.dat[z]
                        set z = z+1
                        exitwhen z > q
                    endloop
                    set data.index = data.index-1
                endif
                set i = i+1
            endloop
        endmethod
        
        static method dmgTriggerActions takes nothing returns nothing
            local unit src = GetEventDamageSource()
            local unit u = GetTriggerUnit()
            local integer i = 0
            local integer q = 0
            local integer z = 0
            local boolean b = false
            local data d
            loop
                exitwhen i > data.index
                exitwhen b == true
                set d = data.dat[i]
                if d.attacker == src and d.attacked == u then
                    set b = true
                    call agibonus.create(d.attacker, d.slvl)
                    call PauseTimer(d.tim)
                    call DestroyTimer(d.tim)
                    call d.destroy()
                    loop
                        set q = data.index
                        set z = i+1
                        set data.dat[z-1] = data.dat[z]
                        set z = z+1
                        exitwhen z > q
                    endloop
                    set data.index = data.index-1
                    
                endif
                set i = i + 1
            endloop
            set src = null
            set u = null
        endmethod
        
        static method create takes unit attacker, unit attacked returns data
            local data d = data.allocate()
            set d.attacker = attacker
            set d.attacked = attacked
            set d.slvl = GetUnitAbilityLevel(d.attacker, 'A00K')
            set d.dmgtrigger = CreateTrigger()
            set d.tim = CreateTimer()
            call TriggerRegisterUnitEvent(d.dmgtrigger, d.attacked, EVENT_UNIT_DAMAGED)
            set d.act = TriggerAddAction(d.dmgtrigger, function data.dmgTriggerActions)
            call TimerStart(d.tim, 1.0, false, function data.timerExpire)
            set data.dat[data.index] = d
            set data.index = data.index+1
            
            return d
        endmethod
    endstruct

    private function Eval takes nothing returns boolean
        if GetUnitAbilityLevel(GetAttacker(), 'A00K') > 0 then
            call data.create(GetAttacker(), GetTriggerUnit())
        endif
        return false
    endfunction

    private function init takes nothing returns nothing
        local trigger trg = CreateTrigger()
        call TriggerRegisterAnyUnitEventBJ(trg, EVENT_PLAYER_UNIT_ATTACKED)
        call TriggerAddCondition(trg, Condition(function Eval))
    endfunction
endlibrary
 
Level 7
Joined
Oct 14, 2008
Messages
340
Well I know what the difference is between libraries and scopes, I was asking ikill how I would benefit from using a scope instead of a library.
 
Level 9
Joined
Aug 21, 2008
Messages
533
Jasshelper said:
Sometimes, you don't want the code to go to the top of your script (it is not really a function library) yet you's; still want to use the private keyword for a group of globals and functions. This is the reason we defined the scope keyword
So if you dont want the code at the top of your script, you can use scopes. Maybe you need a function which isnt in a library.. or something normally you could use a library i think.

Jasshelper said:
Scopes support initializer just like libraries, there is a difference in implementation and it is that they use a normal call rather than an ExecuteFunc call, if you need a heavy process to init a scope, better use a library initializer or call a subfunction using ExecuteFunc from the scope initializer.
So if you want to execute it on map init, better use a library. But by calling the scope by a ExecuteFunc, you still may use it.
 
Status
Not open for further replies.
Top