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

[vJASS] My periodic loop spell is not working

Status
Not open for further replies.
Level 2
Joined
Oct 15, 2008
Messages
17
Hi, after reading through few tutorials i've tried making a spell which should pick units in an AOE and make them move on the spot randomly for 3 seconds but the code is not working.

I have timerutils.

here is the code:

JASS:
scope DrunkenParty initializer Init
//===========================================================================
//=============================SETUP START===================================
//===========================================================================
    globals
        private constant integer SPELL_ID = 'A02G'  //the rawcode of the spell
        private constant real INTERVAL = 0.03
    endglobals
    
    private function Duration takes integer level returns real
        return 3.
    endfunction
    
    private function Range takes integer level returns real
        return 200.
    endfunction
    
    private function Targets takes unit target returns boolean
    //the units the spell will affect
        return (IsUnitType(target, UNIT_TYPE_STRUCTURE) == false) and (IsUnitType(target, UNIT_TYPE_MAGIC_IMMUNE) == false)
    endfunction
//===========================================================================
//=============================SETUP END=====================================
//===========================================================================
    globals
        private group all
        private group copy
        private boolexpr b
    endglobals
//===========================================================================
//Function made by Blade.dk; Search for [url=http://www.wc3campaigns.com]wc3campaigns.com[/url] for more info
    private function CopyGroup takes group g returns group
        set bj_groupAddGroupDest = CreateGroup()
        call ForGroup(g, function GroupAddGroupEnum)
        return bj_groupAddGroupDest
    endfunction
//===========================================================================
    private function Pick takes nothing returns boolean
        return Targets(GetFilterUnit())
    endfunction
//===========================================================================
    private function Conditions takes nothing returns boolean
        return GetSpellAbilityId() == SPELL_ID
    endfunction
    
    private struct Data
        unit caster
        unit target
        real spellX
        real spellY
        location effectLoc
        real duration
        real range
        integer level
    endstruct

    private function Loop takes nothing returns nothing
        local timer t = GetExpiredTimer()
        local Data data = Data(GetTimerData(t))
        call UnitDamageTarget(data.caster, data.caster, 15, false, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_UNIVERSAL, null)
        call GroupEnumUnitsInRange(all, data.spellX, data.spellY, data.range, b)
        set copy = CopyGroup(all)
        set data.target = FirstOfGroup(copy)
        loop
            exitwhen(data.target == null)
            set data.target = FirstOfGroup(copy)
            call GroupRemoveUnit(copy, data.target)
            if IsUnitEnemy(data.target, GetOwningPlayer(data.caster))==true then
                set data.effectLoc = GetUnitLoc(data.target)
                call SetUnitPositionLoc(data.target, PolarProjectionBJ(data.effectLoc, 4.00, GetRandomDirectionDeg()))      
            endif
        endloop             
        set data.duration = data.duration - INTERVAL
        if data.duration <= 0. then
            call ReleaseTimer(t)
            call data.destroy()
        endif
    endfunction
//===========================================================================
    private function Actions takes nothing returns nothing
        local location spellLoc = GetSpellTargetLoc()
        local location effectLoc
        local real spellX = GetLocationX(spellLoc)
        local real spellY = GetLocationY(spellLoc)
        local unit caster = GetTriggerUnit()
        local unit target
        local integer level = GetUnitAbilityLevel(caster, SPELL_ID)
        local timer t = NewTimer()
        local Data data = Data.create()
        set data.caster = caster
        set data.target = target
        set data.spellX = spellX
        set data.spellY = spellY
        set data.effectLoc = effectLoc
        set data.duration = Duration(level)
        set data.range = Range(level)
        set data.level = level
        
        call SetTimerData(t, integer(data))
        call TimerStart(t, INTERVAL, true, function Loop)
    
        call RemoveLocation(spellLoc)
        set effectLoc = null
        set spellLoc = null
        set target = null
        set caster = null
    endfunction    
//===========================================================================
    private function Init takes nothing returns nothing
        local trigger DrunkenPartyTrg = CreateTrigger()
        call TriggerRegisterAnyUnitEventBJ(DrunkenPartyTrg, EVENT_PLAYER_UNIT_SPELL_EFFECT )
        call TriggerAddCondition(DrunkenPartyTrg, Condition( function Conditions ) )
        call TriggerAddAction(DrunkenPartyTrg, function Actions )
        
        //setting globals
        set all = CreateGroup()
        set copy = CreateGroup()
        set b = Condition(function Pick)
        
    endfunction
endscope
 
Level 2
Joined
Oct 15, 2008
Messages
17
not sure what part of the code should be inside the struct and also not sure which functions to be changed into static method.

thx for your help :D
 
Level 29
Joined
Mar 10, 2009
Messages
5,016
Im not using my WE, so something like this...take note that this is not tested...
JASS:
private struct Data
        unit caster
        unit target
        real spellX
        real spellY
        location effectLoc
        real duration
        real range
        integer level
    
    static method Loop takes nothing returns nothing
        local timer t = GetExpiredTimer()
        local thistype data = GetTimerData(t)
        call UnitDamageTarget(data.caster, data.caster, 15, false, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_UNIVERSAL, null)
        call GroupEnumUnitsInRange(all, data.spellX, data.spellY, data.range, b)
        set copy = CopyGroup(all)
        set data.target = FirstOfGroup(copy)
        loop
            exitwhen(data.target == null)
            set data.target = FirstOfGroup(copy)
            call GroupRemoveUnit(copy, data.target)
            if IsUnitEnemy(data.target, GetOwningPlayer(data.caster))==true then
                set data.effectLoc = GetUnitLoc(data.target)
                call SetUnitPositionLoc(data.target, PolarProjectionBJ(data.effectLoc, 4.00, GetRandomDirectionDeg()))      
            endif
        endloop             
        set data.duration = data.duration - INTERVAL
        if data.duration <= 0. then
            call ReleaseTimer(t)
            call data.destroy()
        endif
    endmethod
//===========================================================================
    static method Actions takes unit caster, unit target, real spellX, real spellY returns thistype
        local thistype data = thistype.create()
        local integer level = GetUnitAbilityLevel(caster, SPELL_ID)
        local timer t = NewTimer()
        set data.caster = caster
        set data.target = target
        set data.spellX = spellX
        set data.spellY = spellY
        set data.effectLoc = effectLoc
        set data.duration = Duration(level)
        set data.range = Range(level)
        set data.level = level
        
        call SetTimerData(t, data)
        call TimerStart(t, INTERVAL, true, function thistype.Loop)
    
        call RemoveLocation(spellLoc)
        set effectLoc = null
        set spellLoc = null
        set target = null
        set caster = null
        return data
    endmethod
endstruct

EDIT:
I've noticed that your using locations and BJ like PolarProjectionBJ >>> that's really bad...
 
Last edited:
Level 2
Joined
Oct 15, 2008
Messages
17
thanks for that now my problem is: (undefined action functions)

JASS:
    private function Init takes nothing returns nothing
        local trigger DrunkenPartyTrg = CreateTrigger()
        call TriggerRegisterAnyUnitEventBJ(DrunkenPartyTrg, EVENT_PLAYER_UNIT_SPELL_EFFECT )
        call TriggerAddCondition(DrunkenPartyTrg, Condition( function Conditions ) )
        call TriggerAddAction(DrunkenPartyTrg, [B]function Actions[/B] )

i tried thistype.Actions as well but that didn't work :(
 
Level 29
Joined
Mar 10, 2009
Messages
5,016
remove this...

JASS:
private function Conditions takes nothing returns boolean
        return GetSpellAbilityId() == SPELL_ID
endfunction

and put this...

JASS:
private function Conditions takes nothing returns boolean
    local unit caster
    local unit target
    local real x
    local real y  
    if GetSpellAbilityId() == SPELL_ID then
        set caster = GetTriggerUnit()
        set target = GetSpellTargetUnit()
        set x = GetSpellTargetX()
        set y = GetSpellTargetY()
        //actually you dont need effectloc
        call call Data.Actions(caster, target, x, y) 
    endif
    set caster = null
    set target = null
    return false
endfunction


private function Init takes nothing returns nothing
        local trigger DrunkenPartyTrg = CreateTrigger()
        call TriggerRegisterAnyUnitEventBJ(DrunkenPartyTrg, EVENT_PLAYER_UNIT_SPELL_EFFECT )
        call TriggerAddCondition(DrunkenPartyTrg, Condition( function Conditions ) )
        //setting globals
        set all = CreateGroup()
        set copy = CreateGroup()
        set b = Condition(function Pick)
endfunction

take note also that I've modified the code in post #4...
 
Level 2
Joined
Oct 15, 2008
Messages
17
nope, this spell basically splashes alcohol in an aoe and makes the enemies move randomly uncontrollably for x seconds.

i also tried call Data.Actions(caster, target, x, y)

and that had an error too.

originally this spell was GUI and was easy to make and worked properly
but once i tried making it vJass i just failed :(

thanks for all your help btw :)
 
Level 2
Joined
Oct 15, 2008
Messages
17
when caught in aoe moves to random positioon all the time

so it looks like they are going mental on the spot or dancing on the spot

here's the map which also might help.

you can turn the GUI on and see the proper spell

EDIT: sry uploadede wrong map. this one is the working one.
 

Attachments

  • Drunken Party.w3x
    59.6 KB · Views: 51
Level 29
Joined
Mar 10, 2009
Messages
5,016
Check this out...

"so it looks like they are going mental on the spot or dancing on the spot"

JASS:
scope DrunkenParty initializer Init
//===========================================================================
//=============================SETUP START===================================
//===========================================================================
    globals
        private constant integer SPELL_ID = 'A000'  //the rawcode of the spell
        private constant real INTERVAL = 0.03
    endglobals
    
    private function Duration takes integer level returns real
        return 3.
    endfunction
    
    private function Range takes integer level returns real
        return 200.
    endfunction
    
    private function Targets takes unit target returns boolean
    //the units the spell will affect
        return not IsUnitType(target, UNIT_TYPE_STRUCTURE) and not IsUnitType(target, UNIT_TYPE_MAGIC_IMMUNE)
    endfunction
//===========================================================================
//=============================SETUP END=====================================
//===========================================================================
    globals
        private group all
        private group copy
        private boolexpr b
    endglobals
//===========================================================================
//Function made by Blade.dk; Search for [url=http://www.wc3campaigns.com]wc3campaigns.com[/url] for more info
    private function CopyGroup takes group g returns group
        set bj_groupAddGroupDest = CreateGroup()
        call ForGroup(g, function GroupAddGroupEnum)
        return bj_groupAddGroupDest
    endfunction
//===========================================================================
    private function Pick takes nothing returns boolean
        return Targets(GetFilterUnit())
    endfunction
//===========================================================================
    
    private struct Data
        unit caster
        real spellX
        real spellY
        //location effectLoc
        real duration
        real range
        integer level
    
        static method Loop takes nothing returns nothing
            local timer t = GetExpiredTimer()
            local thistype data = GetTimerData(t)
            local unit target
            local real x
            local real y
            //call UnitDamageTarget(data.caster, data.caster, 15, false, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_UNIVERSAL, null)
            call GroupEnumUnitsInRange(all, data.spellX, data.spellY, data.range, b)
            set copy = CopyGroup(all)
            set target = FirstOfGroup(copy)
            loop
                exitwhen(target == null)
                set target = FirstOfGroup(copy)
                call GroupRemoveUnit(copy, target)
                if IsUnitEnemy(target, GetOwningPlayer(data.caster)) then
                    set x = GetUnitX(target)
                    set y = GetUnitY(target)
                    call SetUnitX(target, x+4*Cos(GetRandomReal(0, 360)))
                    call SetUnitY(target, y+4*Sin(GetRandomReal(0, 360)))
                endif
            endloop             
            set data.duration = data.duration - INTERVAL
            if data.duration <= 0. then
                call ReleaseTimer(t)
                call data.destroy()
            endif
        endmethod
//===========================================================================
        static method Actions takes unit caster, real spellX, real spellY, integer level returns thistype
            local location spellLoc = GetSpellTargetLoc()
            local thistype data = thistype.create()
            local timer t = NewTimer()
            set data.caster = caster
            set data.spellX = spellX
            set data.spellY = spellY
            set data.duration = Duration(level)
            set data.range = Range(level)
            set data.level = level
            call SetTimerData(t, data)
            call TimerStart(t, INTERVAL, true, function thistype.Loop)
            return data
        endmethod
endstruct 

private function Conditions takes nothing returns boolean
    local unit caster
    local real x
    local real y 
    local integer level
    if GetSpellAbilityId() == SPELL_ID then
        set caster = GetTriggerUnit()
        set x = GetSpellTargetX()
        set y = GetSpellTargetY()
        set level = GetUnitAbilityLevel(caster, SPELL_ID)
        call Data.Actions(caster, x, y, level) 
    endif
    set caster = null
    return false
endfunction

private function Init takes nothing returns nothing
        local trigger DrunkenPartyTrg = CreateTrigger()
        call TriggerRegisterAnyUnitEventBJ(DrunkenPartyTrg, EVENT_PLAYER_UNIT_SPELL_EFFECT )
        call TriggerAddCondition(DrunkenPartyTrg, Condition( function Conditions ) )
        //setting globals
        set all = CreateGroup()
        set copy = CreateGroup()
        set b = Condition(function Pick)
endfunction

endscope
 
Level 2
Joined
Oct 15, 2008
Messages
17
NICE it worked!

i found out why mine never worked because i had the wrong ability code...

but with urs just now it looks smooth and nice and i dont need to call BJ or randomDEG

its now vJASS and MUI YAY

THANKS LOTS!!!!!!!!!
 
Status
Not open for further replies.
Top