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

Spell Runthrough

Status
Not open for further replies.
Level 9
Joined
Apr 23, 2011
Messages
460
I'm in the process of fixing up several spells, however I haven't time to test this spell properly and continue debugging. Can anyone find any obvious problems with the coding itself? Thought I'd post this while I work on other spells.

JASS:
library ArcaneLock uses TimerUtils, RegisterPlayerUnitEvent
    globals
        private constant integer SPELL_ID    = 'ArcL'
        private constant real RADIUS         = 350.
        private constant real DURATION       = 6.
        private constant integer BUFFLASTS   = 4
        private constant integer DUMM_ID     = 'dumy'
        private constant integer DUMM_SPELL  = 'Alok'
        private constant real MP_FACTOR      = .025
        private constant integer TIMEOUT     = 5
        private constant string EYECANDY     = ""
        private constant real DRAIN          = .04
        private group enumGroup              = CreateGroup()
        private group enumGroupSafe          = CreateGroup()
    endglobals
    
    struct ArcaneLock
        private real originX
        private real originY
        private unit caster
        private group boundEnemies = CreateGroup()
        private location origin
        private timer looping = CreateTimer()
        private integer counter
        private integer timeout
        private effect eyecandy
        private timer buffLoop = CreateTimer()
        private integer buffLeft
       
        private method onDestroy takes nothing returns nothing
            call DestroyGroup(this.boundEnemies)
            set this.caster = null
            set this.boundEnemies = null
            set this.origin = null
            set this.looping = null
            set this.eyecandy = null
            set this.buffLoop = null
        endmethod
       
        private static method getPointDistance takes location a, location b returns real
            local real x = GetLocationX(b) - GetLocationX(a)
            local real y = GetLocationY(b) - GetLocationY(a)
            return SquareRoot(x * x + y * y)
        endmethod
        
        private method groupLoop takes nothing returns nothing
            local unit enumUnit
            call GroupEnumUnitsInRangeOfLoc(enumGroup, this.origin, RADIUS, null)
            for enumUnit in enumGroup 
                if not IsUnitAlly(enumUnit, GetOwningPlayer(this.caster)) and not IsUnitInGroup(enumUnit, this.boundEnemies) then
                    call GroupAddUnit(this.boundEnemies, enumUnit)
                endif
            endfor
        endmethod
        
        private static method buffDrain takes nothing returns nothing
            local thistype this = GetTimerData(GetExpiredTimer())
            local unit u
            local group g = CreateGroup()
            call GroupEnumUnitsInRect(g, bj_mapInitialPlayableArea, null)
            for u in g
                if GetUnitAbilityLevel(u, DUMM_SPELL) > 0 and getPointDistance(GetUnitLoc(u), GetUnitLoc(this.caster)) < 250 then
                    call this.giveMana((GetUnitState(u, UNIT_STATE_MAX_MANA)*.03), 250)
                endif
            endfor
            set this.buffLeft = this.buffLeft + 1
            if this.buffLeft == BUFFLASTS then
                call ReleaseTimer(this.buffLoop)
            endif
            if this.buffLoop == null then
                call this.destroy()
            endif
        endmethod
        
        private method giveBuff takes unit tar returns nothing
            call SetUnitAbilityLevel(tar, DUMM_SPELL, 1)
        endmethod
        
        private method giveMana takes real mana, real radius returns nothing
            local unit u
            local group g = CreateGroup()
            call GroupEnumUnitsInRange(g, GetUnitX(this.caster), GetUnitY(this.caster), radius, null)
            for u in g
                if IsUnitAlly(u, GetOwningPlayer(this.caster)) then
                    call SetUnitState(u, UNIT_STATE_MANA, GetUnitState(u, UNIT_STATE_MANA) + mana)
                endif
            endfor
            call DestroyGroup(g)
            set g = null
        endmethod
        
        private method unitLeaves takes nothing returns nothing
            local unit u
            local boolean rangeCheck
            local real drain
            for u in this.boundEnemies
                if getPointDistance(Location(GetUnitX(u), GetUnitY(u)), this.origin) > RADIUS then
                    call SetUnitPositionLoc(u, this.origin)
                endif
                call GroupAddUnit(enumGroupSafe, u)
                set drain = GetUnitState(u, UNIT_STATE_MAX_MANA) * DRAIN
                call SetUnitState(u, UNIT_STATE_MANA, GetUnitState(u, UNIT_STATE_MANA) - drain)
                call this.giveMana(drain, 350)
            endfor
            for u in enumGroupSafe
                call GroupAddUnit(this.boundEnemies, u)
            endfor
        endmethod       
       
        private static method periodic takes nothing returns nothing
            local thistype this = GetTimerData(GetExpiredTimer())
            local unit u
            if this.counter == 5 then
                set this.counter = 0
                call this.unitLeaves()
                set this.timeout = this.timeout + 1
                if this.timeout == TIMEOUT then 
                    call ReleaseTimer(this.looping)
                    call DestroyEffect(this.eyecandy)
                    for u in this.boundEnemies
                        call this.giveBuff(u)
                        call SetTimerData(this.buffLoop, this)
                        call TimerStart(this.buffLoop, 1., true, function thistype.buffDrain)
                    endfor
                endif
            endif
            call this.groupLoop()
            set this.counter = this.counter + 1

        endmethod
        
        private static method spell takes nothing returns nothing
            local thistype this = thistype.create()
            set this.caster = GetSpellAbilityUnit()
            set this.origin = GetSpellTargetLoc()
            set this.originX = GetLocationX(this.origin)
            set this.originY = GetLocationY(this.origin)
            set eyecandy = AddSpecialEffect(EYECANDY, this.originX, this.originY)
            call SetTimerData(this.looping, this)
            call TimerStart(this.looping, .2, true, function thistype.periodic)
        endmethod
    endstruct
endlibrary
 
Status
Not open for further replies.
Top