• 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.

[JASS] structs have been officially ditched

Status
Not open for further replies.
JASS:
scope tide

globals
    private unit wave
    private integer speed
    private real direc
    private location offset
    private timer time
endglobals

private function tideTimeCall takes nothing returns nothing
    local location current = GetUnitLoc(wave)
    set offset = PolarProjectionBJ(GetUnitLoc(wave),speed,direc)
    call SetUnitPositionLoc(wave,offset)
    set speed = speed - 1
    if speed < -30 then
        call DestroyTimer(time)
    endif
endfunction

private function sTide takes nothing returns nothing
    set time = CreateTimer()
    set direc = GetUnitFacing(GetSpellAbilityUnit())
    set wave = CreateUnitAtLoc(GetOwningPlayer(GetSpellAbilityUnit()),'hfoo',GetUnitLoc(GetSpellAbilityUnit()),direc)
    set speed = 25
    call TimerStart(time,.03,true,function tideTimeCall)
endfunction

function callTide takes nothing returns nothing
    call sTide()
endfunction

endscope

function tideActions takes nothing returns nothing
    if GetSpellAbilityId()=='A001' then
        call callTide()
    endif
endfunction

function InitTrig_tide takes nothing returns nothing
    set gg_trg_tide = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(gg_trg_tide,EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddAction(gg_trg_tide,function tideActions)
endfunction

works but not MUI. if i have 2 units cast the ability at the same time the timer never ends (speed gets smaller and smaller (unit moves faster backwards))

any workaround?
 
Last edited:
Level 12
Joined
Apr 27, 2008
Messages
1,228
How would you expect it to be MUI...
These things don't just happen by themselves...
What is the problem with structs?

This is useless(just call sTide directly, but make it public(or nothing)):
JASS:
function callTide takes nothing returns nothing
    call sTide()
endfunction
 
Sorry about this comment... but that code is screwed...

a) You leak a TON of locations! Why do you even use locations??? Coords are MUCH better!
b) Of course it doesn't work MUI! It uses the same globals for each cast!!
c) It uses the same timer global for each cast... but sets it again and again! So you leak a timer, and keep the code running FOREVER every single time you cast the spell!
d) You put your condition IN the action? WTF?
e) You go through 3 function calls to get to the right one each time the spell is cast! It's like you're saying to the game:

"You just need to call this function to cast the spell..."
"HAHA tricked you cast ANOTHER function!"
"HEHE and again!"

So it makes the code run much more slowly... It could EASILY run off only 1 function call...

I will fix it for you and post it, but seriously... you need to practice your programming skills...

EDIT:

Done. I didn't test it but it should work. Tell me if it doesn't...
JASS:
scope tide

globals
    private location offset
    private location current
    private timer time = CreateTimer()
    private tide_data array dat
    private integer index = 0
endglobals

private function tideTimeCall takes nothing returns nothing
    local integer i = 0
    local real x
    local real y
    local tide_data this
    loop
        exitwhen i == index
        set this = dat[i]
        
        set x = GetUnitX(this.wave) + this.speed * Cos(this.direc*bj_DEGTORAD)
        set y = GetUnitY(this.wave) + this.speed * Sin(this.direc*bj_DEGTORAD)
        
        call SetUnitX(this.wave,x)
        call SetUnitY(this.wave,y)
        
        set this.speed = this.speed - 1.
        if this.speed < -30. then
            call this.destroy()
        endif
    
        set i = i + 1
    endloop
endfunction

struct tide_data
    unit wave
    real speed
    real direc
    
    integer ID
    
    static method create takes unit wave, real speed, real direc returns tide_data
        local tide_data this = tide_data.allocate()
        set this.wave = wave
        set this.speed = speed
        set this.direc = direc
        if index == 0 then
            call TimerStart(time,.03,true,function tideTimeCall)
        endif
        set dat[index] = this
        set this.ID = index
        set index = index + 1
        return this
    endmethod
    
    method onDestroy takes nothing returns nothing
        set index = index - 1
        set dat[this.ID] = dat[index]
        set dat[this.ID].ID = this.ID
        
        if index == 0 then
            call PauseTimer(time)
        endif
        
        call RemoveUnit(.wave)
    endmethod
endstruct

function tideConditions takes nothing returns boolean
    return GetSpellAbilityId()=='A001'
endfunction

function tideActions takes nothing returns nothing
    local real x = GetUnitX(GetSpellAbilityUnit())
    local real y = GetUnitY(GetSpellAbilityUnit())
    local real direc = GetUnitFacing(GetSpellAbilityUnit())
    local unit wave = CreateUnit(GetOwningPlayer(GetSpellAbilityUnit()),'hfoo',x,y,direc)
    local real speed = 25.
    call tide_data.create(wave, speed, direc)
    set wave = null
endfunction

function InitTrig_tide takes nothing returns nothing
    set gg_trg_tide = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(gg_trg_tide,EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddCondition(gg_trg_tide,Condition(function tideConditions))
    call TriggerAddAction(gg_trg_tide,function tideConditions)
endfunction

endscope
 
the 2 threads were different questions with different scripts -.-

Sorry about this comment... but that code is screwed...

a) You leak a TON of locations! Why do you even use locations??? Coords are MUCH better!
b) Of course it doesn't work MUI! It uses the same globals for each cast!!
c) It uses the same timer global for each cast... but sets it again and again! So you leak a timer, and keep the code running FOREVER every single time you cast the spell!
d) You put your condition IN the action? WTF?
e) You go through 3 function calls to get to the right one each time the spell is cast! It's like you're saying to the game:

"You just need to call this function to cast the spell..."
"HAHA tricked you cast ANOTHER function!"
"HEHE and again!"

So it makes the code run much more slowly... It could EASILY run off only 1 function call...

I will fix it for you and post it, but seriously... you need to practice your programming skills...

EDIT:

Done. I didn't test it but it should work. Tell me if it doesn't...
JASS:
scope tide

globals
    private location offset
    private location current
    private timer time = CreateTimer()
    private tide_data array dat
    private integer index = 0
endglobals

private function tideTimeCall takes nothing returns nothing
    local integer i = 0
    local real x
    local real y
    local tide_data this
    loop
        exitwhen i == index
        set this = dat[i]
        
        set x = GetUnitX(this.wave) + this.speed * Cos(this.direc*bj_DEGTORAD)
        set y = GetUnitY(this.wave) + this.speed * Sin(this.direc*bj_DEGTORAD)
        
        call SetUnitX(this.wave,x)
        call SetUnitY(this.wave,y)
        
        set this.speed = this.speed - 1.
        if this.speed < -30. then
            call this.destroy()
        endif
    
        set i = i + 1
    endloop
endfunction

struct tide_data
    unit wave
    real speed
    real direc
    
    integer ID
    
    static method create takes unit wave, real speed, real direc returns tide_data
        local tide_data this = tide_data.allocate()
        set this.wave = wave
        set this.speed = speed
        set this.direc = direc
        if index == 0 then
            call TimerStart(time,.03,true,function tideTimeCall)
        endif
        set dat[index] = this
        set this.ID = index
        set index = index + 1
        return this
    endmethod
    
    method onDestroy takes nothing returns nothing
        set index = index - 1
        set dat[this.ID] = dat[index]
        set dat[this.ID].ID = this.ID
        
        if index == 0 then
            call PauseTimer(time)
        endif
        
        call RemoveUnit(.wave)
    endmethod
endstruct

function tideConditions takes nothing returns boolean
    return GetSpellAbilityId()=='A001'
endfunction

function tideActions takes nothing returns nothing
    local real x = GetUnitX(GetSpellAbilityUnit())
    local real y = GetUnitY(GetSpellAbilityUnit())
    local real direc = GetUnitFacing(GetSpellAbilityUnit())
    local unit wave = CreateUnit(GetOwningPlayer(GetSpellAbilityUnit()),'hfoo',x,y,direc)
    local real speed = 25.
    call tide_data.create(wave, speed, direc)
    set wave = null
endfunction

function InitTrig_tide takes nothing returns nothing
    set gg_trg_tide = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(gg_trg_tide,EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddCondition(gg_trg_tide,Condition(function tideConditions))
    call TriggerAddAction(gg_trg_tide,function tideConditions)
endfunction

endscope

-I fix leaks and change to co-ords last. I'm new to jass so it's easier for me to think linearly with locations
-I just learned what private globals were and misunderstood their use (thought they could be used to be MUI)
-Once again I thought private timer meant MUI
-Whats wrong with putting the condition in the action? It just reduces ur function count as far as I see...
-I once again misunderstood the use of privates and didn't know a private function could be called outside a scope. I also didn't know a function could have an event within a scope.

-your script doesn't work (footman never gets created)
 
-I fix leaks and change to co-ords last. I'm new to jass so it's easier for me to think linearly with locations
-I just learned what private globals were and misunderstood their use (thought they could be used to be MUI)
-Once again I thought private timer meant MUI
Good that you're learning from your mistakes.
-Whats wrong with putting the condition in the action? It just reduces ur function count as far as I see...
I don't know why, but conditions are faster than actions. If you put your conditions in the action, it runs the (slow) action every time you cast any spell. If the condition is seperate, only the faster condition will be run every time you cast a spell. If you want to reduce the function count, put the actions in the condition rather than the condition in the actions.
-I once again misunderstood the use of privates and didn't know a private function could be called outside a scope.
I don't mean to say you can call the private function from outside the struct. I just mean you should either do what Spiwn said, or you should make the actions inside the scope...
I also didn't know a function could have an event within a scope.
Why not?
-your script doesn't work (footman never gets created)
I hate the way I can't ever a code to work first time without testing... seems I'll have to debug it... will post again soon...

EDIT:

OMG I can't believe how thick I can be... the only error I made was making the action I added the condition function. Anyways, new code...
JASS:
scope tide

globals
    private location offset
    private location current
    private timer time = CreateTimer()
    private tide_data array dat
    private integer index = 0
endglobals

private function tideTimeCall takes nothing returns nothing
    local integer i = 0
    local real x
    local real y
    local tide_data this
    loop
        exitwhen i == index
        set this = dat[i]
        
        if this != 0 then

        set x = GetUnitX(this.wave) + this.speed * Cos(this.direc*bj_DEGTORAD)
        set y = GetUnitY(this.wave) + this.speed * Sin(this.direc*bj_DEGTORAD)

        call SetUnitX(this.wave,x)
        call SetUnitY(this.wave,y)

        set this.speed = this.speed - 1.
        if this.speed < -30. then
            call dat[i].destroy()
        endif
        
        endif

        set i = i + 1
    endloop
endfunction

struct tide_data
    unit wave
    real speed
    real direc

    integer ID

    static method create takes unit wave, real speed, real direc returns tide_data
        local tide_data this = tide_data.allocate()
        set this.wave = wave
        set this.speed = speed
        set this.direc = direc
        if index == 0 then
            call TimerStart(time,.03,true,function tideTimeCall)
        endif
        set this.ID = index
        set dat[index] = this
        set index = index + 1
        return this
    endmethod

    method onDestroy takes nothing returns nothing
        set index = index - 1
        set dat[this.ID] = dat[index]
        set dat[this.ID].ID = this.ID

        if index == 0 then
            call PauseTimer(time)
        endif

        call RemoveUnit(.wave)
    endmethod
endstruct

function Trig_tide_Conditions takes nothing returns boolean
    return GetSpellAbilityId() == 'A001'
endfunction

function Trig_tide_Actions takes nothing returns nothing
    local real x = GetUnitX(GetSpellAbilityUnit())
    local real y = GetUnitY(GetSpellAbilityUnit())
    local real direc = GetUnitFacing(GetSpellAbilityUnit())
    local unit wave = CreateUnit(GetOwningPlayer(GetSpellAbilityUnit()),'hfoo',x,y,direc)
    local real speed = 25.
    call tide_data.create(wave, speed, direc)
    set wave = null
endfunction

function InitTrig_tide takes nothing returns nothing
    set gg_trg_tide = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(gg_trg_tide, EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddAction(gg_trg_tide, function Trig_tide_Actions)
    call TriggerAddCondition(gg_trg_tide, Condition(function Trig_tide_Conditions))
endfunction

endscope
 
Last edited:
Level 12
Joined
Apr 27, 2008
Messages
1,228

JASS:
scope tide initializer InitTrig_tide

globals
    private location offset
    private location current
    private timer time = CreateTimer()
    private tide_data array dat
    private integer index = 0
endglobals

private function tideTimeCall takes nothing returns nothing
    local integer i = 0
    local real x
    local real y
    local tide_data this
    loop
        exitwhen i == index
        set this = dat[i]

        set x = GetUnitX(this.wave) + this.speed * Cos(this.direc*bj_DEGTORAD)
        set y = GetUnitY(this.wave) + this.speed * Sin(this.direc*bj_DEGTORAD)

        call SetUnitPosition(this.wave, x,y)
        
        set this.speed = this.speed - 1.
        if this.speed < -30. then
            call this.destroy()
        endif

        set i = i + 1
    endloop
endfunction

struct tide_data
    unit wave
    real speed
    real direc

    integer ID

    static method create takes unit wave, real speed, real direc returns tide_data
        local tide_data this = tide_data.allocate()
        set this.wave = wave
        set this.speed = speed
        set this.direc = direc
        if index == 0 then
            call TimerStart(time,.03,true,function tideTimeCall)
        endif
        set dat[index] = this
        set this.ID = index
        set index = index + 1
        return this
    endmethod

    method onDestroy takes nothing returns nothing
set index = index - 1
        set dat[this.ID] = dat[index]
        set dat[this.ID].ID = this.ID

if index == 0 then
            call PauseTimer(time)
        endif

        call RemoveUnit(.wave)
    endmethod
endstruct

function tideConditions takes nothing returns boolean
    return GetSpellAbilityId()=='A001'
endfunction

function tideActions takes nothing returns nothing
    local real x = GetUnitX(GetSpellAbilityUnit())
    local real y = GetUnitY(GetSpellAbilityUnit())
    local real direc = GetUnitFacing(GetSpellAbilityUnit())
    local unit wave = CreateUnit(GetOwningPlayer(GetSpellAbilityUnit()),'hfoo',x,y,direc)
    local real speed = 25.
    call tide_data.create(wave, speed, direc)
    set wave = null
endfunction

function InitTrig_tide takes nothing returns nothing
    set gg_trg_Tide = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(gg_trg_Tide,EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddCondition(gg_trg_Tide,Condition(function tideConditions))
    call TriggerAddAction(gg_trg_Tide,function  tideActions)
endfunction

endscope


Missing initializer at scope declaration.
Function name in actions registering messed up.

I also changed the setunitx and setunity to setunitposition, cause that has some advantages(like moving effects).
 
hehe I fixed it before you!

Missing initializer at scope declaration.
Don't need that at all... it registers it as InitTrig_tide anyway... In fact, if you do declare that as the initializer, it will be called twice!
Function name in actions registering messed up.
I know how thick can I get... :(
I also changed the setunitx and setunity to setunitposition, cause that has some advantages(like moving effects).
But in this case he uses no effects, so it has no advantages (in fact it has disadvantages, such as positioning the unit wrongly if the place you want it to move to shouldn't be pathable...)
 
Last edited:
Level 12
Joined
Apr 27, 2008
Messages
1,228
7:31 and 7:32 :p
You do need to put the initializer. Did you test it with out it. It sure did not run without it.
 
Sorry for double post

I changed the trigger because it was giving me a compile error for some reason, and now it doesn't work.

I tried to duplicate what your trigger was doing in a different way because pJass wouldn't compile the way it was set up.

JASS:
scope tide initializer InitTrig_tide

globals
    private location offset
    private location current
    private timer time = CreateTimer()
    private tide_data array tideDataArray
    private integer index = 0
    private unit waveTemp
    private real speedTemp
endglobals

private function damage takes nothing returns nothing
    local real x = GetUnitX(GetEnumUnit())
    local real y = GetUnitY(GetEnumUnit())
    local location tempLoc = PolarProjectionBJ(Location(x,y),3*(speedTemp/8),GetUnitFacing(waveTemp))
    if GetUnitTypeId(GetEnumUnit())!='h001' and IsPlayerAlly(GetOwningPlayer(GetEnumUnit()),GetOwningPlayer(waveTemp))==false and IsUnitAliveBJ(GetEnumUnit())==true then
        call SetUnitLifeBJ(GetEnumUnit(),GetUnitState(GetEnumUnit(),UNIT_STATE_LIFE)-5)
        call SetUnitX(GetEnumUnit(),GetLocationX(tempLoc))
        call SetUnitY(GetEnumUnit(),GetLocationY(tempLoc))
    endif
endfunction

private function tideTimeCall takes nothing returns nothing
    local integer i = 0
    local real x
    local real y
    local tide_data localTideDat
    loop
        exitwhen i == index
        set localTideDat = tideDataArray[i]
        set x = GetUnitX(localTideDat.wave)+localTideDat.speed/2*Cos(localTideDat.direc*bj_DEGTORAD)
        set y = GetUnitY(localTideDat.wave)+localTideDat.speed/2*Sin(localTideDat.direc*bj_DEGTORAD)
        call SetUnitPosition(localTideDat.wave,x,y)
        set waveTemp = localTideDat.wave
        set speedTemp = localTideDat.speed
        call ForGroup(GetUnitsInRangeOfLocAll(150,Location(x,y)),function damage)
        set localTideDat.speed = localTideDat.speed - 1.
        if localTideDat.speed < -60 then
            call tide_data.remove(localTideDat.wave)
            call localTideDat.destroy()
        endif
        set i = i + 1
    endloop
endfunction

struct tide_data
    unit wave
    real speed
    real direc
    integer ID
    static method create takes unit wave, real speed, real direc returns tide_data
        local tide_data localTideDat = tide_data.allocate()
        set localTideDat.wave = wave
        set localTideDat.speed = speed
        set localTideDat.direc = direc
        if index == 0 then
            call TimerStart(time,.03,true,function tideTimeCall)
        endif
        set tideDataArray[index] = localTideDat
        set localTideDat.ID = index
        set index = index + 1
        return localTideDat
    endmethod
    
    static method remove takes unit wave returns nothing
        local tide_data localDat = tide_data.allocate()
        set localDat.wave = wave
        call RemoveUnit(localDat.wave)
        set index = index - 1
        set localDat = tideDataArray[index]
        set tideDataArray[index].ID = index
        if index == 0 then
            call PauseTimer(time)
            call BJDebugMsg("global timer paused")
        endif
    endmethod
endstruct

function tideConditions takes nothing returns boolean
    return GetSpellAbilityId()=='A001'
endfunction

function tideActions takes nothing returns nothing
    local real x = GetUnitX(GetSpellAbilityUnit())
    local real y = GetUnitY(GetSpellAbilityUnit())
    local real direc = GetUnitFacing(GetSpellAbilityUnit())
    local unit wave = CreateUnit(GetOwningPlayer(GetSpellAbilityUnit()),'h001',x,y,direc)
    local real speed = 60
    call tide_data.create(wave,speed,direc)
endfunction

function InitTrig_tide takes nothing returns nothing
    set gg_trg_tide2 = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(gg_trg_tide2,EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddCondition(gg_trg_tide2,Condition(function tideConditions))
    call TriggerAddAction(gg_trg_tide2,function tideActions)
endfunction

endscope

Thanks for any help...
 
Status
Not open for further replies.
Top