• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

[vJASS] Alloc and Help with a spell

Status
Not open for further replies.
Level 16
Joined
Mar 3, 2006
Messages
1,564
I am creating a spell, and in order to improve it I tried to use Alloc


JASS:
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~ Alloc ~~ By Sevion ~~ Version 1.09 ~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
//  What is Alloc?
//         - Alloc implements an intuitive allocation method for array structs
//
//    =Pros=
//         - Efficient.
//         - Simple.
//         - Less overhead than regular structs.
//
//    =Cons=
//         - Must use array structs (hardly a con).
//         - Must manually call OnDestroy.
//         - Must use Delegates for inheritance.
//         - No default values for variables (use onInit instead).
//         - No array members (use another Alloc struct as a linked list or type declaration).
//
//    Methods:
//         - struct.allocate()
//         - struct.deallocate()
//
//           These methods are used just as they should be used in regular structs.
//
//    Modules:
//         - Alloc
//           Implements the most basic form of Alloc. Includes only create and destroy
//           methods.
//
//  Details:
//         - Less overhead than regular structs
//
//         - Use array structs when using Alloc. Put the implement at the top of the struct.
//
//         - Alloc operates almost exactly the same as default structs in debug mode with the exception of onDestroy.
//
//  How to import:
//         - Create a trigger named Alloc.
//         - Convert it to custom text and replace the whole trigger text with this.
//
//  Thanks:
//         - Nestharus for the method of allocation and suggestions on further merging.
//         - Bribe for suggestions like the static if and method names.
//         - PurgeandFire111 for some suggestions like the merging of Alloc and AllocX as well as OnDestroy stuff.
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
library Alloc    
    module Alloc
        private static integer instanceCount = 0
        private thistype recycle
    
        static method allocate takes nothing returns thistype
            local thistype this
    
            if (thistype(0).recycle == 0) then
                debug if (instanceCount == 8190) then
                    debug call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, "Alloc ERROR: Attempted to allocate too many instances!")
                    debug return 0
                debug endif
                set instanceCount = instanceCount + 1
                set this = instanceCount
            else
                set this = thistype(0).recycle
                set thistype(0).recycle = thistype(0).recycle.recycle
            endif

            debug set this.recycle = -1
    
            return this
        endmethod
    
        method deallocate takes nothing returns nothing
            debug if (this.recycle != -1) then
                debug call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, "Alloc ERROR: Attempted to deallocate an invalid instance at [" + I2S(this) + "]!")
                debug return
            debug endif

            set this.recycle = thistype(0).recycle
            set thistype(0).recycle = this
        endmethod
    endmodule
endlibrary

but I don't know how to implement it in my spell.

Here is a sample of my codes:


JASS:
    private struct MislData
        unit Caster
        unit Missile
        location CastPoint
        real Distance
        real Damage
        real Radius
        real face
        
        static method MissileMove takes nothing returns nothing
            local MislData dat
            local integer i = 0
            local real X = 0
            local real Y = 0
            local location loc
            loop
                exitwhen i >= mindex
                set dat = temp_mdat[i]
                set dat.Distance = dat.Distance - M_DIST
                set X = GetUnitX(dat.Missile)
                set Y = GetUnitY(dat.Missile)
                set loc = GetUnitLoc(dat.Missile)
                if DistanceBetweenPoints(loc,dat.CastPoint) < M_DIST then
                    set mindex = mindex - 1
                    set temp_mdat[i] = temp_mdat[mindex]
                    set i = i - 1
                    call NovaData.NovaCreate(dat.Caster , dat.Damage , dat.Radius , GetUnitX(dat.Missile) , GetUnitY(dat.Missile))
                    call dat.destroy()
                else
                    set X = X + M_DIST * Cos(dat.face)
                    set Y = Y + M_DIST * Sin(dat.face)
                    call SetUnitPosition(dat.Missile,X,Y)
                endif
                call RemoveLocation(loc)
                set i = i + 1  // this index loops through all the casters
            endloop
        endmethod

        static method MissileCreate takes unit u , location target returns MislData
            local MislData dat = MislData.allocate()
            local real x1
            local real y1
            local real x2
            local real y2
            local real dx
            local real dy
            set temp_mdat[mindex] = dat
            set dat.Caster = u
            set x1 = GetUnitX(dat.Caster)
            set y1 = GetUnitY(dat.Caster)
            set dat.CastPoint = target
            set x2 = GetLocationX(dat.CastPoint)
            set y2 = GetLocationY(dat.CastPoint)
            set dat.Distance = 0
            set dx = x2 - x1
            set dy = y2 - y1
            set dat.Distance = SquareRoot(dx * dx + dy * dy)
            set dat.face = Atan2(y2 - y1, x2 - x1)
            set dat.Missile = CreateUnit(GetOwningPlayer(dat.Caster),M_UNIT_ID,x1,y1,dat.face * bj_RADTODEG)
            call SetUnitPosition(dat.Missile,x1,y1)
            set dat.Damage = NovaDamage(GetUnitAbilityLevel(u , ABILTY_ID))
//call BJDebugMsg(R2S(dat.Damage))
            set dat.Radius = NovaRadius(GetUnitAbilityLevel(u , ABILTY_ID))
            if mindex == 0 then
                call TimerStart(mtm,M_TIMER_INTERVAL,true,function MislData.MissileMove)
            endif
            set mindex = mindex + 1
            return dat
        endmethod
        
        method onDestroy takes nothing returns nothing
            call KillUnit(.Missile)
            set .Missile = null
            set .face = 0
            call RemoveLocation(.CastPoint)
            if mindex == 0 then
                call PauseTimer(mtm)
            endif
        endmethod
    endstruct

P.S. : I am not a pro-vJasser so make your answers/help clear, please. And thanks in advance.
 
Make that struct extend an array:
private struct MislData extends array

And type in implement Alloc

JASS:
        location CastPoint
        real Distance
        real Damage
        real Radius
        real face

        // HERE!!!
        
        static method MissileMove takes nothing returns nothing
            local MislData dat
            local integer i = 0
            local real X = 0
            local real Y = 0
            local location loc
 
Level 16
Joined
Mar 3, 2006
Messages
1,564
Thanks, Magtheridon96, it worked. I needed only to change minor things.

<<< EDIT >>>

It didn't work for the following code though:

JASS:
    private struct NovaData extends array
        unit Caster
        unit array Nova[NOVA_SIZE]
        real expand
        real Cx
        real Cy
        player Owner
        group dGroup // Already Damaged Units Group
        real dmg
        real rad
        
        implement Alloc

        static method NovaExpand takes nothing returns nothing
            local NovaData dat
            local integer i = 0
            local integer j
            local real x
            local real y
            local real a
            local unit u

            loop // this loop cycles through all the casters which have cast the spell
                exitwhen i >= nindex
                set dat = temp_ndat[i]
                // Nova Expanding
                set j = 0
                set a = 0
                set dat.expand = dat.expand + N_DIST

                loop // loop for moving the nova units
                    exitwhen j >= NOVA_SIZE
                    set x = dat.Cx + dat.expand * Cos( a * bj_DEGTORAD )
                    set y = dat.Cy + dat.expand * Sin( a * bj_DEGTORAD )
                    call SetUnitX( dat.Nova[j] , x )
                    call SetUnitY( dat.Nova[j] , y )
                    set j = j + 1
                    set a = a + dA
                endloop
                // Damage Units that the nova has reached
                set iFilter = dat

                call GroupEnumUnitsInRange(TempGroup, dat.Cx, dat.Cy, dat.expand, Filter(function NovaData.MatchingUnit))
                loop
                    set u = FirstOfGroup(TempGroup)
                    exitwhen u == null
                    call GroupAddUnit(dat.dGroup, u)
                    if IsUnitType(u,UNIT_TYPE_STRUCTURE) then
                        call UnitDamageTarget(dat.Caster, u, BUILDN_FACTOR*dat.dmg, false, false, ATKTYPE, DMGTYPE, null)
                    else
                        call UnitDamageTarget(dat.Caster, u, UNIT_FACTOR*dat.dmg, false, false, ATKTYPE, DMGTYPE, null)
                    endif

                    call GroupRemoveUnit(TempGroup, u)
                endloop

                if dat.expand >= dat.rad then // check if the nova has reached its max AoE
                    set nindex = nindex - 1
                    set temp_ndat[i] = temp_ndat[nindex]
                    set i = i - 1
                    call DestroyGroup(dat.dGroup)  // CHANGE 1
                    
                    set j = 0

                    loop
                        exitwhen j >= NOVA_SIZE
                        call KillUnit(dat.Nova[j])
                        set dat.Nova[j] = null
                        set dat.expand = 0
                        set j = j + 1
                    endloop

                    if nindex == 0 then
                        call PauseTimer(ntm)
                    endif

                endif

                set i = i + 1
            endloop

            set u = null

        endmethod

        static method NovaCreate takes unit caster , real damage , real radius, real posX, real posY returns NovaData
            local NovaData dat = NovaData.allocate()
            local integer i = 0
            local real A = 0.00
            set dat.Caster = caster
            set dat.Owner = GetOwningPlayer(dat.Caster)
            set dat.Cx = posX
            set dat.Cy = posY
            set dat.dmg = damage
            set dat.rad = radius
            set dat.dGroup = CreateGroup()

            loop
                exitwhen i >= NOVA_SIZE
                set dat.Nova[i] = CreateUnit( dat.Owner , N_UNIT_ID , dat.Cx , dat.Cy , A )
                set A = A + dA
                set i = i + 1
            endloop

            if nindex == 0 then
                call TimerStart(ntm,N_TIMER_INTERVAL,true,function NovaData.NovaExpand)
            endif

            set temp_ndat[nindex] = dat
            set nindex = nindex + 1
            return dat
        endmethod
       
        static method MatchingUnit takes nothing returns boolean
        local boolean m1 = FALSE
        local boolean CheckDone = FALSE
        local boolean mF = FALSE
        local boolean mG = FALSE
        local boolean mS = FALSE
        
            if FRIENDLY == 1 then
                if IsUnitEnemy(GetFilterUnit(),iFilter.Owner) then
                    set m1 = TRUE
                endif
            else
                set m1 = TRUE
            endif
            
            if FLYING == 1 then
                if IsUnitType(GetFilterUnit(),UNIT_TYPE_FLYING) and CheckDone == FALSE then
                set CheckDone = TRUE
                set mF = TRUE
                set mG = TRUE
                set mS = TRUE
                endif
            endif
            
            if GROUND == 1 then
                if IsUnitType(GetFilterUnit(),UNIT_TYPE_GROUND) and CheckDone == FALSE then
                set CheckDone = TRUE
                set mF = TRUE
                set mG = TRUE
                set mS = TRUE
                endif
            endif

            if STRUCTURE == 1 then
                if IsUnitType(GetFilterUnit(),UNIT_TYPE_STRUCTURE) and CheckDone == FALSE then
                set CheckDone = TRUE
                set mF = TRUE
                set mG = TRUE
                set mS = TRUE
                endif
            endif
            return GetWidgetLife(GetFilterUnit()) >= .405 and m1 and  mF and mG and mS and not IsUnitInGroup(GetFilterUnit(),iFilter.dGroup)
        endmethod

    endstruct
 
Status
Not open for further replies.
Top