• 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] keep getting expected; returns error

Status
Not open for further replies.
Level 8
Joined
Feb 3, 2013
Messages
277
Hi all, I've been trying to create a channeling spell that gives a hero to heal a friendly units mana/health at the expense of its mana;; i'm not sure if this is the best way to go about - but i wanted to give structs/methods a try

The main issue is that i keep getting an expected returns error on the line 'static method create .... returns data'

i have NO idea why, and it giving me bonkers

also if someone can help suggest other ways of doing this, or some tips on using structs/methods to make spells that would be great :)

thanks in advance
JASS:
scope Surge initializer init
    
    globals
        private constant hashtable HASH = InitHashtable()
    endglobals
    
    private struct data
        unit c
        unit t
        real r 
        integer i
        
        method hurt takes nothing returns nothing
            set this.r = I2R(GetUnitAbilityLevel(this.c, 'A00A')) * .33 * .2 * GetHeroInt(this.c, TRUE)
            if this.i < 25 then
                call SetUnitState(this.c, UNIT_STATE_MANA, GetUnitState(this.c, UNIT_STATE_MANA) - r)
                call SetUnitState(this.t, UNIT_STATE_MANA, GetUnitState(this.t, UNIT_STATE_MANA) + r)
                call SetUnitState(this.t, UNIT_STATE_LIFE, GetUnitState(this.t, UNIT_STATE_LIFE) + r)
            else
                call this.destroy()
            endif
            set this.i = this.i + 1
        endmethod
        
        static method create takes unit C takes unit T takes returns data
            local data this = data.allocate()
            set this.c = C
            set this.t = T
            call TimerStart(CreateTimer(), 0.2, TRUE, function this.hurt)
        endmethod
        
        method destroy takes nothing returns nothing
            set this.c = null
            set this.t = null
            call this.deallocate()
        endmethod
    endstruct
    
    private function S_Add takes nothing returns nothing
        local unit C = GetTriggerUnit()
        local unit T = GetSpellTargetUnit()
        local data d 
        if GetSpellAbilityId() == 'A00A' then
            set C = GetTriggerUnit()
            set T = GetSpellTargetUnit()
            set d = data.create(C, T)
            call SaveInteger(HASH, GetHandleId(C), 0, data.d)
            set C = null
            set T = null
        endif
    endfunction
    
    private function S_Remove takes nothing returns nothing
        local data d
        local unit C = GetTriggerUnit()
        if GetSpellAbilityId() == 'A00A' then
            set data.d = LoadInteger(HASH, GetHandleId(C), 0)
            call d.destroy
            set C = null
        endif
    endfunction
    
    private function init takes nothing returns nothing
        local trigger t = CreateTrigger()
        call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
        call TriggerAddAction(t, function S_Add)
        call TriggerRegisterAnyUnitEventBJ(t2, EVENT_PLAYER_UNIT_SPELL_ENDCAST)
        call TriggerAddAction(t2, function S_Remove)
    endfunction
    
endscope
 
Level 8
Joined
Feb 3, 2013
Messages
277
JASS:
static method create takes unit C, unit T returns data
            local data this = data.allocate()
            set this.c = C
            set this.t = T
            call TimerStart(CreateTimer(), 0.2, TRUE, function this.hurt)
            return this
        endmethod
wow such small mistakes ;s, how embarassing
i've tried this, but it gives me another error -_-

edit2: HOLY i just realized how many little errors i have in this trigger, let me fix and repost
 
u do know instead of data u can use the keyword
JASS:
thistype
If u use this and u change data to some other name it will still work.

ex
JASS:
static method create takes unit C, unit T returns thistype
            local thistype this = thistype.allocate()
            set this.c = C
            set this.t = T
            call TimerStart(CreateTimer(), 0.2, TRUE, function this.hurt)
            return this
        endmethod
 
Level 8
Joined
Feb 3, 2013
Messages
277
JASS:
scope Surge initializer init
    
    globals
        private constant hashtable HASH = InitHashtable()
    endglobals
    
    private struct data
        unit c
        unit t
        real r 
        integer i = 0
        effect e_c
        effect e_t
        string fx = "Abilities\\Spells\\Other\\Drain\\ManaDrainCaster.mdl"
        
        static method create takes unit C, unit T returns data
            local data this = data.allocate()
            set this.c = C
            set this.t = T
            return this
        endmethod
        
        method destroy takes nothing returns nothing
            set this.c = null
            set this.t = null
            call DestroyEffect(this.e_c)
            call DestroyEffect(this.e_t)
            set this.e_t = null
            set this.e_c = null
            call this.deallocate()
        endmethod
    endstruct
    
    private function S_Channel takes nothing returns boolean
            local data d = TT_GetData()
            set d.r = I2R(GetUnitAbilityLevel(d.c, 'A00A')) * 1/3 * GetHeroInt(d.c, TRUE) * .4
            if d.i < 25 then 
                if GetUnitState(d.c, UNIT_STATE_MANA) >= d.r then
                    call BJDebugMsg(R2S(d.r))
                    call SetUnitState(d.c, UNIT_STATE_MANA, GetUnitState(d.c, UNIT_STATE_MANA) - d.r)
                    call SetUnitState(d.t, UNIT_STATE_MANA, GetUnitState(d.t, UNIT_STATE_MANA) + d.r)
                    call SetUnitState(d.t, UNIT_STATE_LIFE, GetUnitState(d.t, UNIT_STATE_LIFE) + d.r)
                else
                    call BJDebugMsg("stop!")
                    call IssueImmediateOrder(d.c, "stop")
                    set d.i = 25
                    call FlushChildHashtable(HASH, GetHandleId(d.c))
                endif
            else
                call d.destroy()
                return TRUE
            endif
            set d.i = d.i + 1
            return FALSE
    endfunction
    
    private function S_Add takes nothing returns nothing
        local unit lv_caster = GetTriggerUnit()
        local unit lv_target = GetSpellTargetUnit()
        local data d 
        if GetSpellAbilityId() == 'A00A' then
            set d = data.create(lv_caster, lv_target)
            set d.e_c = AddSpecialEffectTarget(d.fx, d.c, "overhead")
            set d.e_t = AddSpecialEffectTarget(d.fx, d.t, "overhead")
            call TT_StartEx(function S_Channel, d, .2)
            call SaveInteger(HASH, GetHandleId(lv_caster), 0, d)
            call BJDebugMsg("RAWR")
        endif
        set lv_caster = null
        set lv_target = null
    endfunction
    
    private function S_Remove takes nothing returns nothing
        local data d
        local unit C = GetTriggerUnit()
        if GetSpellAbilityId() == 'A00A' then
            set d = LoadInteger(HASH, GetHandleId(C), 0)
            set d.i = 25
            call BJDebugMsg("DONE")
            call FlushChildHashtable(HASH, GetHandleId(C))
        endif
        set C = null
    endfunction
    
    private function init takes nothing returns nothing
        local trigger t = CreateTrigger()
        local trigger t2 = CreateTrigger()
        call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
        call TriggerAddAction(t, function S_Add)
        call TriggerRegisterAnyUnitEventBJ(t2, EVENT_PLAYER_UNIT_SPELL_ENDCAST)
        call TriggerAddAction(t2, function S_Remove)
    endfunction
    
endscope
puhahahahahaha, sorry if anyone posted after my second post;; I redid it again - i always find my self trying even harder after i post something zzzz

@ death : that only works if its written inside the struct rite?
 
JASS:
scope Surge initializer init
    
    globals
        private constant hashtable HASH = InitHashtable()
    endglobals
    
    private struct data
        unit c
        unit t
        real r 
        integer i = 0
        effect e_c
        effect e_t
        string fx = "Abilities\\Spells\\Other\\Drain\\ManaDrainCaster.mdl"
        
        static method create takes unit C, unit T returns data
            local data this = data.allocate()
            set this.c = C
            set this.t = T
            return this
        endmethod
        
        method destroy takes nothing returns nothing
            set this.c = null
            set this.t = null
            call DestroyEffect(this.e_c)
            call DestroyEffect(this.e_t)
            set this.e_t = null
            set this.e_c = null
            call this.deallocate()
        endmethod
    endstruct
    
    private function S_Channel takes nothing returns boolean
            local data d = TT_GetData()
            set d.r = I2R(GetUnitAbilityLevel(d.c, 'A00A')) * 1/3 * GetHeroInt(d.c, TRUE) * .4
            if d.i < 25 then 
                if GetUnitState(d.c, UNIT_STATE_MANA) >= d.r then
                    call BJDebugMsg(R2S(d.r))
                    call SetUnitState(d.c, UNIT_STATE_MANA, GetUnitState(d.c, UNIT_STATE_MANA) - d.r)
                    call SetUnitState(d.t, UNIT_STATE_MANA, GetUnitState(d.t, UNIT_STATE_MANA) + d.r)
                    call SetUnitState(d.t, UNIT_STATE_LIFE, GetUnitState(d.t, UNIT_STATE_LIFE) + d.r)
                else
                    call BJDebugMsg("stop!")
                    call IssueImmediateOrder(d.c, "stop")
                    set d.i = 25
                    call FlushChildHashtable(HASH, GetHandleId(d.c))
                endif
            else
                call d.destroy()
                return TRUE
            endif
            set d.i = d.i + 1
            return FALSE
    endfunction
    
    private function S_Add takes nothing returns nothing
        local unit lv_caster = GetTriggerUnit()
        local unit lv_target = GetSpellTargetUnit()
        local data d 
        if GetSpellAbilityId() == 'A00A' then
            set d = data.create(lv_caster, lv_target)
            set d.e_c = AddSpecialEffectTarget(d.fx, d.c, "overhead")
            set d.e_t = AddSpecialEffectTarget(d.fx, d.t, "overhead")
            call TT_StartEx(function S_Channel, d, .2)
            call SaveInteger(HASH, GetHandleId(lv_caster), 0, d)
            call BJDebugMsg("RAWR")
        endif
        set lv_caster = null
        set lv_target = null
    endfunction
    
    private function S_Remove takes nothing returns nothing
        local data d
        local unit C = GetTriggerUnit()
        if GetSpellAbilityId() == 'A00A' then
            set d = LoadInteger(HASH, GetHandleId(C), 0)
            set d.i = 25
            call BJDebugMsg("DONE")
            call FlushChildHashtable(HASH, GetHandleId(C))
        endif
        set C = null
    endfunction
    
    private function init takes nothing returns nothing
        local trigger t = CreateTrigger()
        local trigger t2 = CreateTrigger()
        call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
        call TriggerAddAction(t, function S_Add)
        call TriggerRegisterAnyUnitEventBJ(t2, EVENT_PLAYER_UNIT_SPELL_ENDCAST)
        call TriggerAddAction(t2, function S_Remove)
    endfunction
    
endscope
puhahahahahaha, sorry if anyone posted after my second post;; I redid it again - i always find my self trying even harder after i post something zzzz

@ death : that only works if its written inside the struct rite?

yes thats right. umm u cant initialize the hashtable in the globals block.
instead of making functions just make everything methods. It will be better and u can change everything from data to thistype.

Also this is inside the struct and shouold be changed to the keywords.
JASS:
static method create takes unit C, unit T returns data
            local data this = data.allocate()
            set this.c = C
            set this.t = T
            return this
        endmethod

is something still wrong ? besides the hashtable lol.
 
Level 23
Joined
Apr 16, 2012
Messages
4,041
FALSE to false, FALSE is constant global variable, which is set to false, so false is a bit faster(you dont need to read a variable)
in function S_Add you never deallocate data struct, which means that after enough times it will bug(cant get another index, because you are already using all 8192 indexes

deathismyfriend said:
yes thats right. umm u cant initialize the hashtable in the globals block.

That is not true, I do that and hashtables works as expected
and no you are trying to convince him in using thistype keyword, that is not necessary
 
he probably missed the d.destroy() call.
u should make this completely rely on structs tho. Take a look at my spell in my sig. That may be able to help u see what the difference will be. Its a lot better looking when u use methods rather than call functions IMO. plus u can replace data with this and use the thistype for everything. so its easier to edit also.
 
Level 8
Joined
Feb 3, 2013
Messages
277
he probably missed the d.destroy() call.
u should make this completely rely on structs tho. Take a look at my spell in my sig. That may be able to help u see what the difference will be. Its a lot better looking when u use methods rather than call functions IMO. plus u can replace data with this and use the thistype for everything. so its easier to edit also.

kkk i will thanks mengs :)
i realized that they do make stuff a lot cleaner
 
theres a few different ways. u can index structs based on the time they expire. Which is good if its a long wait. umm the way i like to do it is use an integer array and a maxindex just like normal jass.
then u increase the maxindex everytime u create a new struct and de-index it like normal when u destroy a struct.
i basically do
JASS:
set structIndex[ maxIndex] = this
to index it. now i have a periodic timer that goes off every 0.031250000 and it loads the struct like this
JASS:
method periodic takes nothing returns nothing
    local thistype this
    local integer L = 1
    loop
        exitwhen L > maxIndex
        set this = structIndex[ L]
        // do stuff here normally i use a counter and when that counter hits a number i do my actions.
        // to de-index do this
        if this.counter > 50 then
            set structIndex[ L] = structIndex[ maxIndex]
            set maxIndex = maxIndex - 1
            set L = L - 1
            call this.destroy()
        endif
    endloop
endmethod
 
Level 4
Joined
Apr 7, 2012
Messages
63
By the way, as far as I'm concerned you can not set a unit's life/mana by SetUnitState, you are going to have to use SetWidgetLife or use item abilities.
 
Status
Not open for further replies.
Top