• 🏆 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] 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
 
Level 29
Joined
Oct 24, 2012
Messages
6,543
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?
 
Level 29
Joined
Oct 24, 2012
Messages
6,543
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
 
Level 29
Joined
Oct 24, 2012
Messages
6,543
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
 
Level 29
Joined
Oct 24, 2012
Messages
6,543
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