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

[JASS] Problem with a spell

Status
Not open for further replies.
Level 16
Joined
May 1, 2008
Messages
1,605
Moin moin =)

i have a little problem with my spell. I rewrote the trigger now 4 times but always I get another error. Now in this code I have 2 new problems.

1: The loop part runs only one time. For testing I displayed the "war.t" and it stops by 0.04. Why that =O

2: As you see, I set the TimedLife of an orc in "private function FelOrcDur". Normally the duration should be 20/30/40 seconds, but when I test it ingame and the orc spawns, the TimedLife is at all levels only about 2 seconds (It's so fast so I think it's 2 seconds, maybe it's just 1 or 3) Why that =O

=== Warcry ===
When the ability is used, an fel orc spawn instantly. Now every 2 seconds another fel orc is spawned, until the "FelOrcAmount" is reached.

JASS:
library Warcry initializer Init requires TimerUtils

    globals
        private constant integer SPELL_ID = 'A004'
        
        private constant string WAR_EFFECT = "Abilities\\Spells\\NightElf\\BattleRoar\\RoarCaster.mdl"
        private constant real SPAWN_RELEASE = 2.
    endglobals
    
    globals // store the unit
        private integer array FEL_ORC
    endglobals
    
    private function WarcrySetup takes nothing returns nothing
        set FEL_ORC[1] = 'uni0'
        set FEL_ORC[2] = 'uni1'
        set FEL_ORC[3] = 'uni2'
    endfunction
    
    private function FelOrcDur takes nothing returns real
        return (10. * GetUnitAbilityLevel(GetTriggerUnit(),SPELL_ID)) + 10.
    endfunction
    
    private function FelOrcAmount takes nothing returns integer
        return (2 + GetUnitAbilityLevel(GetTriggerUnit(),SPELL_ID))
    endfunction
    
    // Configuration ends here \\
    
    globals
        private constant real LOOP_TIME = 0.04
        private integer TEMP
    endglobals
    
    private struct Warcry
        unit    caster  = null
        real    t       = 0.
        integer c       = 0
        
       private static method WarcryLoop takes nothing returns nothing
            local timer t = GetExpiredTimer()
            local Warcry war = GetTimerData(t)
            local real x
            local real y
            local unit u
            
            set war.t = war.t + LOOP_TIME
            if war.c < FelOrcAmount then
                if war.t >= SPAWN_RELEASE then
                    set war.t = 0
                    set x = GetUnitX(war.caster)
                    set y = GetUnitY(war.caster)
                    set u = CreateUnit(GetOwningPlayer(war.caster),FEL_ORC[GetUnitAbilityLevel(war.caster,SPELL_ID)],x,y,GetUnitFacing(war.caster))
                    call DestroyEffect(AddSpecialEffect(WAR_EFFECT,x,y))
                    call UnitApplyTimedLife(u,'BTFL',FelOrcDur)
                    set war.c = war.c + 1
                endif
            elseif war.c == FelOrcAmount then
                call ReleaseTimer(t)
                call war.destroy()
            endif
            set u = null
        endmethod
       
       static method WarcryCreate takes unit caster returns Warcry
            local thistype war = thistype.allocate()
            local timer t = NewTimer()
            local real x
            local real y
            local unit u
            
            set war.caster = caster
            set x = GetUnitX(war.caster)
            set y = GetUnitY(war.caster)
            set u = CreateUnit(GetOwningPlayer(war.caster),FEL_ORC[GetUnitAbilityLevel(war.caster,SPELL_ID)],x,y,GetUnitFacing(war.caster))
            call UnitApplyTimedLife(u,'BTFL',FelOrcDur)
            call DestroyEffect(AddSpecialEffect(WAR_EFFECT,x,y))
            set war.c = war.c + 1
            set u = null
            call SetTimerData(t,war)
            call TimerStart(t,LOOP_TIME,true,function Warcry.WarcryLoop)            
            return war
        endmethod
    endstruct
            
    private function WarcryCast takes nothing returns boolean
        if GetSpellAbilityId() == SPELL_ID then
            call Warcry.WarcryCreate(GetTriggerUnit())
        endif
        return false
    endfunction  
    
    private function Init takes nothing returns nothing
        local trigger t = CreateTrigger()
        local integer i = 0
        
        loop
            exitwhen i == 15
            call TriggerRegisterPlayerUnitEvent(t,Player(i),EVENT_PLAYER_UNIT_SPELL_EFFECT,null)
            set i = i + 1
        endloop
        call TriggerAddCondition(t,Condition(function WarcryCast)) 
        call Preload(WAR_EFFECT)
        call WarcrySetup()

        set t = null
    endfunction
endlibrary

It's not my first vJass spell at all, but it's the first time, that the loop only runs one time and stop then. Also I don't understand this with the TImedLife, for me it seems to be correct =O

Hope someone can help me with this.

Greetings - Thanks - Peace
Dr. Boom
 
Level 22
Joined
Nov 14, 2008
Messages
3,256
call UnitApplyTimedLife(u,'BTFL',FelOrcDur)

Does this even work? Doesn't it give you a syntax error?

call UnitApplyTimedLife(u,'BTFL',FelOrcDur())

Should be like that.

Also GetTriggerUnit() does only work for EventResponding triggers/functions, you cannot use it in the loop. Dunno if it even works in the create method (should be a function taking a unit as an argument).

Same with Amount.

And because of this, I think the function returns 0 or 1.
 
Level 16
Joined
May 1, 2008
Messages
1,605
No, I didn't get any error, when I try to save it up, but the TimedLife does work now.
But anyway, can you say me how to implement those functions then, that it will work. I try to chance the native into .. takes <something> returns <something> but then I get an error from jass helper "Unexpected returns".
Also I tried to add those functions into the struct with (private) static methods but then I get another error " Relational comparison between special type and native type"

It's the first time, I make this with function. Normally I do this with arrays, but all say "use function use function" .. now I use and see what I got -_-

Edit: Also I try to add both returns into struct members
JASS:
            set war.d = FelOrcDur()
            set war.a = FelOrcAmount()
but the loop still runs just once -_-

So how to make this work? =S
 
Last edited:
Level 16
Joined
May 1, 2008
Messages
1,605
JASS:
    private function FelOrcDur takes nothing returns real
        return (10. * GetUnitAbilityLevel(GetTriggerUnit(),SPELL_ID)) + 10.
    endfunction
    
    private function FelOrcAmount takes nothing returns integer
        return (2 + GetUnitAbilityLevel(GetTriggerUnit(),SPELL_ID))
    endfunction

This functions gives me an error and when I add something instead of "nothing" after takes, what ever it is, I get an syntax error "Unexpected: returns"

Edit: Now I use private function FellorcAmount takes unit caster returns real. But when I use the FelOrcAmount in the struct now, jass helper says "FelOrcAmout must not take any arguments when used as code" and "Comparing two different primitive types are not allowed"
 
Level 22
Joined
Nov 14, 2008
Messages
3,256
Then it's something else that gives you the syntax error. Try to comment those functions out and those calls that calls these functions because this:

JASS:
scope test

private function FelOrcDur takes nothing returns real
    return (10. * GetUnitAbilityLevel(GetTriggerUnit(),'a001')) + 10.
endfunction

private function FelOrcAmount takes nothing returns integer
    return (2 + GetUnitAbilityLevel(GetTriggerUnit(),'test'))
endfunction

endscope

Doesn't give me an error.
 
Level 16
Joined
May 1, 2008
Messages
1,605
Moin moin =)

Ok here we go this is solved now! Was a good discussion with my friend ap0calypse and we (at all he) get it.

I made another struct member for "FelOrcAmount". Seems to be, that he had problems, with directly use " if war.c == FelOrcAmount. Instead I set war.x = FelOrcAmount and use now "if war.c == war.x.

Also, and for some reason, I had to chance the native from:
private function FelOrcAmount takes integer level returns real

into

private function FelOrcAmount takes integer level returns integer

and then, everything works now. Anyway thanks to you baassee, for helping me, you are really a mighty coder - thanks!

JASS:
library Warcry initializer Init requires TimerUtils

    globals
        private constant integer SPELL_ID = 'A004' //Spell Id
        
        private constant string WAR_EFFECT = "Abilities\\Spells\\NightElf\\BattleRoar\\RoarCaster.mdl" // Effect
        private constant real SPAWN_RELEASE = 2. // When an fel orc should be spawn
    endglobals
    
    globals // store the unit
        private integer array FEL_ORC
    endglobals
    
    private function WarcrySetup takes nothing returns nothing
        set FEL_ORC[1] = 'uni0'
        set FEL_ORC[2] = 'uni1'
        set FEL_ORC[3] = 'uni2'
    endfunction
    
    private function FelOrcDur takes integer level returns real // For UnitApplyTimedLife to the fel orc
        return 10. + 10. * level
    endfunction
    
    private function FelOrcAmount takes integer level returns integer // The amount of maximal orcs
        return 2 + 1 * level
    endfunction
    
    // Configuration ends here \\
    
    globals
        private constant real LOOP_TIME = 0.04
        private integer TEMP
    endglobals
    
    private struct Warcry
        unit    caster  = null //caster
        real    t       = 0. // counts until it reach SPAWN_RELEASE, then it's set to 0
        integer c       = 0 // Counts, how many orcs are spawned until FelOrcAmount
        integer x       = 0
    
       private static method WarcryLoop takes nothing returns nothing
            local timer t = GetExpiredTimer()
            local Warcry war = GetTimerData(t)
            local real x
            local real y
            local unit u
            
            set war.t = war.t + LOOP_TIME
            if war.c < war.x then
                if war.t >= SPAWN_RELEASE then
                    set war.t = 0
                    set x = GetUnitX(war.caster)
                    set y = GetUnitY(war.caster)
                    set u = CreateUnit(GetOwningPlayer(war.caster),FEL_ORC[GetUnitAbilityLevel(war.caster,SPELL_ID)],x,y,GetUnitFacing(war.caster))
                    call DestroyEffect(AddSpecialEffect(WAR_EFFECT,x,y))
                    call UnitApplyTimedLife(u,'BTFL',FelOrcDur(GetUnitAbilityLevel(war.caster,SPELL_ID)))
                    set war.c = war.c + 1
                endif
            elseif war.c == war.x then
                call ReleaseTimer(t)
                call war.destroy()
            endif
            set u = null
        endmethod
       
       static method WarcryCreate takes unit caster returns Warcry
            local thistype war = thistype.allocate()
            local timer t = NewTimer()
            local real x
            local real y
            local unit u
            
            set war.caster = caster
            set war.x = FelOrcAmount(GetUnitAbilityLevel(war.caster,SPELL_ID))
            set x = GetUnitX(war.caster)
            set y = GetUnitY(war.caster)
            set u = CreateUnit(GetOwningPlayer(war.caster),FEL_ORC[GetUnitAbilityLevel(war.caster,SPELL_ID)],x,y,GetUnitFacing(war.caster))
            call UnitApplyTimedLife(u,'BTFL',FelOrcDur(GetUnitAbilityLevel(war.caster,SPELL_ID)))
            call DestroyEffect(AddSpecialEffect(WAR_EFFECT,x,y))
            set war.c = war.c + 1
            set u = null
            call SetTimerData(t,war)
            call TimerStart(t,LOOP_TIME,true,function Warcry.WarcryLoop)            
            return war
        endmethod
    endstruct
            
    private function WarcryCast takes nothing returns boolean
        if GetSpellAbilityId() == SPELL_ID then
            call Warcry.WarcryCreate(GetTriggerUnit())
        endif
        return false
    endfunction  
    
    private function Init takes nothing returns nothing
        local trigger t = CreateTrigger()
        local integer i = 0
        
        loop
            exitwhen i == 15
            call TriggerRegisterPlayerUnitEvent(t,Player(i),EVENT_PLAYER_UNIT_SPELL_EFFECT,null)
            set i = i + 1
        endloop
        call TriggerAddCondition(t,Condition(function WarcryCast)) 
        call Preload(WAR_EFFECT)
        call WarcrySetup()

        set t = null
    endfunction
endlibrary

Greetings and Peace
Dr. Boom
 
Status
Not open for further replies.
Top