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

Help with small system conversion to use UnitIndexer by Nastharus

Status
Not open for further replies.
Level 13
Joined
Jul 26, 2008
Messages
1,009
Hi, I have a relatively small system made for me by a member here. What it did was get the last few spells used by the unit and saved them. That way, if the unit casted a spell it could cast it again actively or passively with another button. Or, the last spell used by that unit could be stolen.

I was using AutoIndex at the time. I recently switched to UnitIndexer, and am not sure how to rewrite it for compatibility with UnitIndexer (With AIDs compatibility). It uses the AutoCreate/AutoDestroy modules.

Here is the system in question:
JASS:
library UnitAbility requires UnitIndexer, TimerUtils

    globals
    
        public constant integer     STORED_ABILITIES        = 3
        
    endglobals

    struct abilitydata
        readonly    unit     caster      = null
        readonly    unit     target      = null
        
        readonly    real     castx
        readonly    real     casty
        readonly    real     targetx
        readonly    real     targety
        readonly    real     castAngle
        readonly    real     castRange
        
        readonly    integer  abilityid
        readonly    string   orderstring
        
        method copy takes nothing returns thistype
            local thistype copy = allocate()
            
            set copy.caster     = caster
            set copy.castx      = castx
            set copy.casty      = casty
            set copy.target     = target
            set copy.targetx    = targetx
            set copy.targety    = targety
            set copy.abilityid  = abilityid
            set copy.orderstring= orderstring
            set copy.castAngle  = castAngle
            set copy.castRange  = castRange
            
            return copy
        endmethod
        
        static method create takes nothing returns thistype
            local thistype abil=allocate()
            
            set abil.caster=GetTriggerUnit()
            set abil.castx=GetUnitX(abil.caster)
            set abil.casty=GetUnitY(abil.caster)
            set abil.target=GetSpellTargetUnit()
            set abil.targetx=GetSpellTargetX()
            set abil.targety=GetSpellTargetY()
            set abil.abilityid=GetSpellAbilityId()
            set abil.orderstring=OrderId2String(GetUnitCurrentOrder(abil.caster))
            
            //misc spell-data
            set abil.castAngle=Atan2(abil.targety-abil.casty, abil.targetx-abil.castx) //in radians
            set abil.castRange=SquareRoot((abil.targetx-abil.castx)*(abil.targetx-abil.castx) + (abil.targety-abil.casty)*(abil.targety-abil.casty))
            
            return abil
        endmethod
    endstruct

    struct unitabilities
        readonly    abilitydata array   entry       [STORED_ABILITIES]
        readonly    integer             stored      = 0
        
        method onDestroy takes nothing returns nothing
            local integer i=0
            loop
                exitwhen(i==stored)
                if(entry[i]!=0) then
                    call entry[i].destroy()
                endif
                set i=i+1
            endloop
        endmethod
        
        method addAbility takes abilitydata dat returns boolean
            local integer i=0
            loop
                exitwhen(i==stored)
                if(entry[i]==dat) then
                    return false
                endif
                set i=i+1
            endloop
            if(stored==STORED_ABILITIES) then
                call entry[0].destroy()
                
                set entry[0]=entry[1]
                set entry[1]=entry[2]
                set entry[2]=dat
            else
                set entry[stored]=dat
                set stored=stored+1
            endif
            return true
        endmethod
    endstruct
    
    private struct savedata
        public  unit                source      = null
        public  unit                target      = null
        public  abilitydata         abilData
        
        static method create takes unit source, unit target, abilitydata data1 returns thistype
            local thistype data = allocate()
            
            set data.source     = source
            set data.target     = target
            set data.abilData   = data1
            
            return data
        endmethod
    endstruct
    
    struct unitabilityhistory //requires AutoIndex, TimerUtils
        public  unitabilities   out     
        public  unitabilities   in
    
        private trigger         abilevent   = CreateTrigger() 
        private timer           threadDelay = null
        
        private boolean         skipFlag    = false
        
        method freeze takes boolean flag returns nothing
            if flag then
                call EnableTrigger(abilevent)
            else
                call DisableTrigger(abilevent)
            endif
        endmethod
        method skip takes nothing returns nothing
            set skipFlag = true
        endmethod
        
        method onDestroy takes nothing returns nothing
            call out.destroy()
            call in.destroy()
            
            call DestroyTrigger(abilevent)
            if threadDelay != null then
                call ReleaseTimer(threadDelay)
            endif
        endmethod
    
        static method onAbilEventThreadDelay takes nothing returns nothing
            local savedata data = GetTimerData(GetExpiredTimer())
            
            call thistype[data.source].out.addAbility(data.abilData.copy())
            call thistype[data.target].in.addAbility(data.abilData.copy())
            
            call data.abilData.destroy()
            call ReleaseTimer(GetExpiredTimer())
        endmethod

        static method onAbilEvent takes nothing returns boolean
            local thistype data = thistype[GetTriggerUnit()]
            
            if not data.skipFlag then
                set data.threadDelay = NewTimer()
                
                call SetTimerData(data.threadDelay, savedata.create(GetTriggerUnit(), GetSpellTargetUnit(), abilitydata.create()))
                call TimerStart(data.threadDelay, 0, false, function thistype.onAbilEventThreadDelay)
            endif
            set data.skipFlag = false
            
            return false
        endmethod

        method onCreate takes nothing returns nothing
            set out = unitabilities.create()
            set in  = unitabilities.create()
            call TriggerRegisterUnitEvent(abilevent, me, EVENT_UNIT_SPELL_EFFECT) 
            call TriggerAddCondition(abilevent, Filter(function thistype.onAbilEvent)) 
        endmethod

        implement AutoCreate
        implement AutoDestroy
    endstruct

endlibrary
 
Level 13
Joined
Jul 26, 2008
Messages
1,009
Thanks Nestharus. It saves now, but unfortunately the system doesn't seem to be doing what it should, as I can't get the last spell cast from units that cast spells.

I did have to make one final adjustment, and perhaps I did this wrong. I edited this line at the bottom based on your demo to this.unit from me:

JASS:
           call TriggerRegisterUnitEvent(abilevent, this.unit, EVENT_UNIT_SPELL_EFFECT)

Modified Library:
JASS:
library UnitAbility requires UnitIndexer, TimerUtils

    globals
    
        public constant integer     STORED_ABILITIES        = 3
        
    endglobals

    struct abilitydata
        readonly    unit     caster      = null
        readonly    unit     target      = null
        
        readonly    real     castx
        readonly    real     casty
        readonly    real     targetx
        readonly    real     targety
        readonly    real     castAngle
        readonly    real     castRange
        
        readonly    integer  abilityid
        readonly    string   orderstring
        
        method copy takes nothing returns thistype
            local thistype copy = allocate()
            
            set copy.caster     = caster
            set copy.castx      = castx
            set copy.casty      = casty
            set copy.target     = target
            set copy.targetx    = targetx
            set copy.targety    = targety
            set copy.abilityid  = abilityid
            set copy.orderstring= orderstring
            set copy.castAngle  = castAngle
            set copy.castRange  = castRange
            
            return copy
        endmethod
        
        static method create takes nothing returns thistype
            local thistype abil=allocate()
            
            set abil.caster=GetTriggerUnit()
            set abil.castx=GetUnitX(abil.caster)
            set abil.casty=GetUnitY(abil.caster)
            set abil.target=GetSpellTargetUnit()
            set abil.targetx=GetSpellTargetX()
            set abil.targety=GetSpellTargetY()
            set abil.abilityid=GetSpellAbilityId()
            set abil.orderstring=OrderId2String(GetUnitCurrentOrder(abil.caster))
            
            //misc spell-data
            set abil.castAngle=Atan2(abil.targety-abil.casty, abil.targetx-abil.castx) //in radians
            set abil.castRange=SquareRoot((abil.targetx-abil.castx)*(abil.targetx-abil.castx) + (abil.targety-abil.casty)*(abil.targety-abil.casty))
            
            return abil
        endmethod
    endstruct

    struct unitabilities
        readonly    abilitydata array   entry       [STORED_ABILITIES]
        readonly    integer             stored      = 0
        
        method onDeindex takes nothing returns nothing
            local integer i=0
            loop
                exitwhen(i==stored)
                if(entry[i]!=0) then
                    call entry[i].destroy()
                endif
                set i=i+1
            endloop
        endmethod
        
        method addAbility takes abilitydata dat returns boolean
            local integer i=0
            loop
                exitwhen(i==stored)
                if(entry[i]==dat) then
                    return false
                endif
                set i=i+1
            endloop
            if(stored==STORED_ABILITIES) then
                call entry[0].destroy()
                
                set entry[0]=entry[1]
                set entry[1]=entry[2]
                set entry[2]=dat
            else
                set entry[stored]=dat
                set stored=stored+1
            endif
            return true
        endmethod
    endstruct
    
    private struct savedata
        public  unit                source      = null
        public  unit                target      = null
        public  abilitydata         abilData
        
        static method create takes unit source, unit target, abilitydata data1 returns thistype
            local thistype data = allocate()
            
            set data.source     = source
            set data.target     = target
            set data.abilData   = data1
            
            return data
        endmethod
    endstruct
    
    struct unitabilityhistory //requires AutoIndex, TimerUtils
        public  unitabilities   out     
        public  unitabilities   in
    
        private trigger         abilevent   = CreateTrigger() 
        private timer           threadDelay = null
        
        private boolean         skipFlag    = false
        
        method freeze takes boolean flag returns nothing
            if flag then
                call EnableTrigger(abilevent)
            else
                call DisableTrigger(abilevent)
            endif
        endmethod
        method skip takes nothing returns nothing
            set skipFlag = true
        endmethod
        
        method onDeindex takes nothing returns nothing
            call out.destroy()
            call in.destroy()
            
            call DestroyTrigger(abilevent)
            if threadDelay != null then
                call ReleaseTimer(threadDelay)
            endif
        endmethod
    
        static method onAbilEventThreadDelay takes nothing returns nothing
            local savedata data = GetTimerData(GetExpiredTimer())
            
            call thistype[data.source].out.addAbility(data.abilData.copy())
            call thistype[data.target].in.addAbility(data.abilData.copy())
            
            call data.abilData.destroy()
            call ReleaseTimer(GetExpiredTimer())
        endmethod

        static method onAbilEvent takes nothing returns boolean
            local thistype data = thistype[GetTriggerUnit()]
            
            if not data.skipFlag then
                set data.threadDelay = NewTimer()
                
                call SetTimerData(data.threadDelay, savedata.create(GetTriggerUnit(), GetSpellTargetUnit(), abilitydata.create()))
                call TimerStart(data.threadDelay, 0, false, function thistype.onAbilEventThreadDelay)
            endif
            set data.skipFlag = false
            
            return false
        endmethod

        method onIndex takes nothing returns nothing
            set out = unitabilities.create()
            set in  = unitabilities.create()
            call TriggerRegisterUnitEvent(abilevent, this.unit, EVENT_UNIT_SPELL_EFFECT) 
            call TriggerAddCondition(abilevent, Filter(function thistype.onAbilEvent)) 
        endmethod

        implement UnitIndexStruct
    endstruct

endlibrary
 
UnitIndexStruct looks for:

JASS:
/*
*           -   These methods don't have to exist. If they don't exist, the code
*           -   that calls them won't even be in the module.
*
*           private method index takes nothing returns nothing
*               -   called when a unit is indexed and passes the filter.
*               -
*               -   thistype this:              Unit's index
*           private method deindex takes nothing returns nothing
*               -   called when a unit is deindexed and is allocated for struct
*               -
*               -   thistype this:              Unit's index
*           private static method filter takes unit unitToIndex returns boolean
*               -   Determines whether or not to allocate struct for unit
*               -
*               -   unit unitToIndex:           Unit being filtered
*/

Rename onIndex to index and onDeindex to deindex.
 
Status
Not open for further replies.
Top