vJASS Problem

RaiJin

New Member
Reaction score
40
Okay was making a quick spell and was going to sumbit it :S heres the code

JASS:
scope WaveForm initializer WaveFormInit

globals
    private constant string  EFFECT        =                        "Objects\\Spawnmodels\\Naga\\NagaDeath\\NagaDeath.mdl" //Water effect used when dashing
    private constant real    DISTANCE      =                         30.00 //Distance used
    private constant real    TIMERINTERVAL =                         0.03 //Perodic Timer interval
    private constant real    DMGCOUNT      =                         100.00 // DAMAGE PER LEVEL
    private constant real    MAXDISTANCE   =                         1100.00 //MAXDISTANCE TRAVELED
    private constant real    AOE           =                         200.00// MAX AOE OF THE SPELL
    private constant integer WAVEFORMID    =                         'WAV3' //SpellID NAM
endglobals

private struct data
    unit u
    location ul
    location sl
    integer lvl
    real DAMAGE
    real dis
    real x
    real y
    real x2
    real y2
    timer time
    group ug
    method CleanUp takes nothing returns nothing
        call DestroyGroup(.ug)
        call RemoveLocation(.ul)
        call RemoveLocation(.sl)
        set .u=null
        set .ul=null
        set .sl=null
    endmethod
endstruct

private function GroupDMGCheck takes nothing returns boolean
    local data d
    return IsUnitType(GetFilterUnit(), UNIT_TYPE_STRUCTURE) == false and IsUnitEnemy(GetFilterUnit(), GetOwningPlayer(d.u))
endfunction

private function WConditions takes nothing returns boolean
    return GetSpellAbilityId() == WAVEFORMID
endfunction

private function GroupDAMAGE takes nothing returns nothing
    local data d
    call UnitDamageTargetBJ(d.u, GetEnumUnit(), d.DAMAGE, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL)
endfunction

private function Movement takes nothing returns nothing
    local data d
    local effect e
    local real xx
    local real yy
    local location wl=GetUnitLoc(d.u)
    set d.x=GetUnitX(d.u) + DISTANCE
    set d.y=GetUnitY(d.u) + DISTANCE
    set xx=d.x - d.x2
    set yy=d.y - d.y2
    set d.dis=SquareRoot( xx * xx + yy * yy)
    if d.dis < MAXDISTANCE then
        call SetUnitX(d.u, d.x)
        call SetUnitY(d.u, d.y)
        set d.ug=GetUnitsInRangeOfLocMatching(AOE, wl, Condition(function GroupDMGCheck))
        set e=AddSpecialEffect(EFFECT, d.x, d.y)
        call DestroyEffect(e)
        call ForGroup(d.ug, function GroupDAMAGE)
    else
        call d.CleanUp()
        call SetUnitInvulnerable(d.u, false)
        call SetUnitVertexColorBJ(d.u, 100.00, 100.00, 100.00, 100.00)
        call PauseTimer(GetExpiredTimer())
        call SetUnitPathing(d.u, true)
        call d.destroy()
    endif
endfunction

private function WActions takes nothing returns nothing
    local data d = data.create()
    set d.u=GetTriggerUnit()
    set d.ul=GetUnitLoc(d.u)
    set d.sl=GetSpellTargetLoc()
    set d.lvl=GetUnitAbilityLevel(d.u, WAVEFORMID)
    set d.DAMAGE=I2R(d.lvl)*DMGCOUNT
    set d.time=CreateTimer()
    set d.dis=0.00
    set d.x2=GetLocationX(d.sl)
    set d.y2=GetLocationY(d.sl)
    call RemoveLocation(d.ul)
    call RemoveLocation(d.sl)
    set d.ul=null
    set d.sl=null
    call SetUnitInvulnerable(d.u, true)
    call SetUnitPathing(d.u, false)
    call SetUnitVertexColorBJ(d.u, 100.00, 100, 100, 0.00)
    call TimerStart(d.time, TIMERINTERVAL, true, function Movement)
endfunction

public function WaveFormInit takes nothing returns nothing
    local trigger WaveForm = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( WaveForm, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( WaveForm, Condition( function WConditions ) )
    call TriggerAddAction( WaveForm, function WActions )
endfunction

endscope


hes not dashing T_T help? pl0x
 

Azlier

Old World Ghost
Reaction score
461
I fail to see where you are attaching/retrieving the struct from a timer. And, don't null struct members. Please, just don't.
 

Tom Jones

N/A
Reaction score
437
Get a struct passing system, or use an array to store the struct and then loop trough all of the assigned structs in the timer function.
 

RaiJin

New Member
Reaction score
40
Get a struct passing system, or use an array to store the struct and then loop trough all of the assigned structs in the timer function.

how would i be able to loop through all of them? can u show me please. and thanks for your time really. :thup::)
 

Azlier

Old World Ghost
Reaction score
461
I reccomend TimerUtils (It's incredibly easy to use.)

JASS:
library_once TimerUtils
//*********************************************************************
//* TimerUtils (Blue flavor)
//* ----------
//*
//*  To implement it , create a custom text trigger called TimerUtils
//* and paste the contents of this script there.
//*
//*  To copy from a map to another, copy the trigger holding this
//* library to your map.
//*
//* (requires vJass)   More scripts: htt://www.wc3campaigns.net
//*
//* For your timer needs:
//*  * Attaching
//*  * Recycling (with double-free protection)
//*
//* set t=NewTimer()      : Get a timer (alternative to CreateTimer)
//* ReleaseTimer(t)       : Relese a timer (alt to DestroyTimer)
//* SetTimerData(t,2)     : Attach value 2 to timer
//* GetTimerData(t)       : Get the timer's value.
//*                         You can assume a timer's value is 0
//*                         after NewTimer.
//*
//* Blue Flavor: Slower than the red flavor, it got a 408000 handle id
//*             limit, which means that if more than 408000 handle ids
//*             are used in your map, TimerUtils might fail, this
//*             value is quite big and it is much bigger than the 
//*             timer limit in Red flavor.
//*
//********************************************************************

//================================================================
    globals
        private constant integer MAX_HANDLE_ID_COUNT = 408000
        // values lower than 8191: very fast, but very unsafe.
        // values bigger than 8191: not that fast, the bigger the number is the slower the function gets
        // Most maps don't really need a value bigger than 50000 here, but if you are unsure, leave it
        // as the rather inflated value of 408000
    endglobals

    //=================================================================================================
    private function H2I takes handle h returns integer
        return h
        return 0
    endfunction

    //==================================================================================================
    globals
        private integer array data[MAX_HANDLE_ID_COUNT]
        private constant integer MIN_HANDLE_ID=0x100000
    endglobals

    //It is dependent on jasshelper's recent inlining optimization in order to perform correctly.
    function SetTimerData takes timer t, integer value returns nothing
        debug if(H2I(t)-MIN_HANDLE_ID>=MAX_HANDLE_ID_COUNT) then
        debug     call BJDebugMsg("SetTimerData: Handle id too big, increase the max handle id count or use gamecache instead")
        debug endif
        set data[H2I(t)-MIN_HANDLE_ID]=value
    endfunction

    function GetTimerData takes timer t returns integer
        debug if(H2I(t)-MIN_HANDLE_ID>=MAX_HANDLE_ID_COUNT) then
        debug     call BJDebugMsg("GetTimerData: Handle id too big, increase the max handle id count or use gamecache instead")
        debug endif
        return data[H2I(t)-MIN_HANDLE_ID]
    endfunction

    //==========================================================================================
    globals
        private timer array tT
        private integer tN = 0
        private constant integer HELD=0x28829022
        //use a totally random number here, the more improbable someone uses it, the better.
    endglobals

    //==========================================================================================
    function NewTimer takes nothing returns timer
        if (tN==0) then
            set tT[0]=CreateTimer()
        else
            set tN=tN-1
        endif
        call SetTimerData(tT[tN],0)
     return tT[tN]
    endfunction

    //==========================================================================================
    function ReleaseTimer takes timer t returns nothing
        if(t==null) then
            debug call BJDebugMsg("Warning: attempt to release a null timer")
            return
        endif
        if (tN==8191) then
            debug call BJDebugMsg("Warning: Timer stack is full, destroying timer!!")

            //stack is full, the map already has much more troubles than the chance of bug
            call DestroyTimer(t)
        else
            call PauseTimer(t)
            if(GetTimerData(t)==HELD) then
                debug call BJDebugMsg("Warning: ReleaseTimer: Double free!")
                return
            endif
            call SetTimerData(t,HELD)
            set tT[tN]=t
            set tN=tN+1
        endif    
    endfunction

endlibrary


No, I cannot put it in a spoiler tag. To use:

JASS:


private struct Data
    integer ExecCount = 0
    //Stuffs.
endstruct

private function Callback takes nothing returns nothing
    local Data d = GetTimerData(GetExpiredTimer())
    //Blah blah do stuff.
    set d.ExecCount = d.ExecCount + 1
    //Now, we can end the timer execution.
    if ExecCount > 100 then //Approximately one second.
        call ReleaseTimer(GetExpiredTimer())
        call d.destroy()
    endif
endfunction

private function Actions takes nothing returns nothing
    local Data d = Data.create()
    local timer t = NewTimer()
    call SetTimerData(t, d)
    call TimerStart(t, 0.01, true, function Callback)
    set t = null
endfunction
 

RaiJin

New Member
Reaction score
40
aw cool system's awesome :D

JASS:
scope WaveForm initializer WaveFormInit

globals
    private constant string  EFFECT        =                        "Objects\\Spawnmodels\\Naga\\NagaDeath\\NagaDeath.mdl" //Water effect used when dashing
    private constant real    DISTANCE      =                         30.00 //Distance used
    private constant real    TIMERINTERVAL =                         0.03 //Perodic Timer interval
    private constant real    DMGCOUNT      =                         100.00 // DAMAGE PER LEVEL
    private constant real    MAXDISTANCE   =                         1100.00 //MAXDISTANCE TRAVELED
    private constant real    AOE           =                         200.00// MAX AOE OF THE SPELL
    private constant integer WAVEFORMID    =                         'WAV3' //SpellID NAM
endglobals

private struct data
    unit u
    location sl
    integer lvl
    real DAMAGE
    real dis
    real x
    real y
    real x2
    real y2
    timer time
    group ug
    method CleanUp takes nothing returns nothing
        call DestroyGroup(.ug)
        call RemoveLocation(.sl)
    endmethod
endstruct

private function GroupDMGCheck takes nothing returns boolean
    local data d
    return IsUnitType(GetFilterUnit(), UNIT_TYPE_STRUCTURE) == false and IsUnitEnemy(GetFilterUnit(), GetOwningPlayer(d.u))
endfunction

private function WConditions takes nothing returns boolean
    return GetSpellAbilityId() == WAVEFORMID
endfunction

private function GroupDAMAGE takes nothing returns nothing
    local data d
    call UnitDamageTargetBJ(d.u, GetEnumUnit(), d.DAMAGE, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL)
endfunction

private function Movement takes nothing returns nothing
    local data d = GetTimerData(GetExpiredTimer())
    local effect e
    local real xx
    local real yy
    local location wl=GetUnitLoc(d.u)
    set d.x=GetUnitX(d.u) + DISTANCE
    set d.y=GetUnitY(d.u) + DISTANCE
    set xx=d.x - d.x2
    set yy=d.y - d.y2
    set d.dis=SquareRoot( xx * xx + yy * yy)
    if d.dis < MAXDISTANCE then
        call SetUnitX(d.u, d.x)
        call SetUnitY(d.u, d.y)
        set d.ug=CreateGroup()
        call GroupEnumUnitsInRange(d.ug, d.x, d.y, AOE, Condition(function GroupDMGCheck))
        set e=AddSpecialEffect(EFFECT, d.x, d.y)
        call DestroyEffect(e)
        call ForGroup(d.ug, function GroupDAMAGE)
    else
        call d.CleanUp()
        call SetUnitInvulnerable(d.u, false)
        call ReleaseTimer(GetExpiredTimer())
        call SetUnitPathing(d.u, true)
        call d.destroy()
    endif
endfunction

private function WActions takes nothing returns nothing
    local data d = data.create()
    local timer t = NewTimer()
    set d.u=GetTriggerUnit()
    set d.sl=GetSpellTargetLoc()
    set d.lvl=GetUnitAbilityLevel(d.u, WAVEFORMID)
    set d.DAMAGE=I2R(d.lvl)*DMGCOUNT
    set d.time=CreateTimer()
    set d.dis=0.00
    set d.x2=GetLocationX(d.sl)
    set d.y2=GetLocationY(d.sl)
    call RemoveLocation(d.sl)
    call SetUnitInvulnerable(d.u, true)
    call SetUnitPathing(d.u, false)
    call ShowUnitHide(d.u)
    call SetTimerData(t, d)
    call TimerStart(t, TIMERINTERVAL, true, function Movement)
endfunction

public function WaveFormInit takes nothing returns nothing
    local trigger WaveForm = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( WaveForm, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( WaveForm, Condition( function WConditions ) )
    call TriggerAddAction( WaveForm, function WActions )
endfunction

endscope


anyways.. Hes moving in the wrong direction.. How would i do AngleBetweenpoints xD god dam im so noob
 

RaiJin

New Member
Reaction score
40
ah cool thanks :S just one last thing

is there a system so i can use structs from function to function??
 

Viikuna

No Marlo no game.
Reaction score
265
JASS:


private struct Data

//...

endstruct

globals
     private Data tempData
endglobals

private function SpellFilterFunc takes nothing returns boolean
      local unit u=GetFilterUnit()
      local Data d=tempData
      if u:isAlive then
           // something with d´s members
      endif
      set u=null
      return false
endfunction


private function PewPew takes nothing returns nothing
    local Data d=Data.create() 
    //...
     set TempData=d
    call GroupEnumUnitsInRange(TempGroup,x,y,AREA_OF_EFFECT,SpellFilter)
endfunction


You can use global struct to pass your Data to another function.
With timers you cant do this, because time passes between actions and it would not be MUI.
Use TimerUtils or some other system for timers.
 

RaiJin

New Member
Reaction score
40
JASS:
scope WaveForm initializer WaveFormInit

globals
    private constant string  EFFECT        =                        "Objects\\Spawnmodels\\Naga\\NagaDeath\\NagaDeath.mdl" //Water effect used when dashing
    private constant real    DISTANCE      =                         30.00 //Distance used
    private constant real    TIMERINTERVAL =                         0.03 //Perodic Timer interval
    private constant real    DMGCOUNT      =                         100.00 // DAMAGE PER LEVEL
    private constant real    MAXDISTANCE   =                         1100.00 //MAXDISTANCE TRAVELED
    private constant real    AOE           =                         200.00// MAX AOE OF THE SPELL
    private constant integer WAVEFORMID    =                         'WAV3' //SpellID NAM
    private struct tempdata
endglobals

private struct data
    unit u
    location sl
    integer lvl
    real DAMAGE
    real dis
    real x
    real y
    real x2
    real y2
    real angle
    timer time
    group ug
    method CleanUp takes nothing returns nothing
        call DestroyGroup(.ug)
        call RemoveLocation(.sl)
    endmethod
endstruct

private function GroupDMGCheck takes unit uu returns boolean
    local data d=tempdata
    return IsUnitType(GetFilterUnit(), UNIT_TYPE_STRUCTURE) == false and IsUnitEnemy(GetFilterUnit(), GetOwningPlayer(uu))
endfunction

private function WConditions takes nothing returns boolean
    return GetSpellAbilityId() == WAVEFORMID
endfunction

private function GroupDAMAGE takes nothing returns nothing
    local data d=tempdata
    call UnitDamageTargetBJ(d.u, GetEnumUnit(), d.DAMAGE, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL)
endfunction

private function Movement takes nothing returns nothing
    local data d = GetTimerData(GetExpiredTimer())
    local effect e
    local real xx
    local real yy
    local real newx
    local real newy
    local real nangle
    local location wl=GetUnitLoc(d.u)
    set d.x=GetUnitX(d.u)
    set d.y=GetUnitY(d.u)
    set xx=d.x - d.x2
    set yy=d.y - d.y2
    set d.dis=SquareRoot( xx * xx + yy * yy)
    set newx=d.x + DISTANCE * Cos(d.angle * bj_DEGTORAD)
    set newy=d.y + DISTANCE * Cos(d.angle * bj_DEGTORAD)
    if d.dis < MAXDISTANCE then
        call SetUnitX(d.u, newx)
        call SetUnitY(d.u, newy)
        set d.ug=CreateGroup()
        call GroupEnumUnitsInRange(d.ug, d.x, d.y, AOE, Condition(function GroupDMGCheck))
        set e=AddSpecialEffect(EFFECT, d.x, d.y)
        call DestroyEffect(e)
        call ForGroup(d.ug, function GroupDAMAGE)
    else
        call ShowUnit(d.u, true)
        call d.CleanUp()
        call SetUnitInvulnerable(d.u, false)
        call ReleaseTimer(GetExpiredTimer())
        call SetUnitPathing(d.u, true)
        call d.destroy()
    endif
endfunction

private function WActions takes nothing returns nothing
    local data d = data.create()
    local timer t = NewTimer()
    local unit uu=GetTriggerUnit()
    set tempdata=d
    set d.u=GetTriggerUnit()
    set d.sl=GetSpellTargetLoc()
    set d.lvl=GetUnitAbilityLevel(d.u, WAVEFORMID)
    set d.DAMAGE=I2R(d.lvl)*DMGCOUNT
    set d.time=CreateTimer()
    set d.dis=0.00
    set d.x=GetUnitX(d.u)
    set d.y=GetUnitY(d.u)
    set d.x2=GetLocationX(d.sl)
    set d.y2=GetLocationY(d.sl)
    set d.angle=bj_RADTODEG * Atan2(d.y - d.y2, d.x - d.x2)
    call RemoveLocation(d.sl)
    call SetUnitInvulnerable(d.u, true)
    call SetUnitPathing(d.u, false)
    call ShowUnit(d.u, false)
    call SetTimerData(t, d)
    call TimerStart(t, TIMERINTERVAL, true, function Movement)
    set uu=null
endfunction

public function WaveFormInit takes nothing returns nothing
    local trigger WaveForm = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( WaveForm, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( WaveForm, Condition( function WConditions ) )
    call TriggerAddAction( WaveForm, function WActions )
endfunction

endscope


theres what i got.. the angle doesn't work :S i probably did it wrong .. and it gives me a syntax error (when i save) for
JASS:
private function GroupDAMAGE takes nothing returns nothing
    local data d=tempdata
    call UnitDamageTargetBJ(d.u, GetEnumUnit(), d.DAMAGE, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL)
endfunction


and
JASS:
private function GroupDMGCheck takes unit uu returns boolean
    local data d=tempdata
    return IsUnitType(GetFilterUnit(), UNIT_TYPE_STRUCTURE) == false and IsUnitEnemy(GetFilterUnit(), GetOwningPlayer(uu))
endfunction


it says d is not a type that allows . syntax
 

Viikuna

No Marlo no game.
Reaction score
265
private struct tempdata should be private data tempdata

Anyways, your global block is above your struct, so you cant have a private data there.

Try static struct member, it is a member which is same for all struct instances. It works like global.

JASS:
private struct data
    unit u
    location sl
    integer lvl
    real DAMAGE
    real dis
    real x
    real y
    real x2
    real y2
    real angle
    timer time
    group ug

    static data temp // here   

    method CleanUp takes nothing returns nothing
        call DestroyGroup(.ug)
        call RemoveLocation(.sl)
    endmethod
endstruct


To use this temp member do this:
JASS:
 set data.temp=d
          // and
local data d=data.temp


And uu is not member of data, so you cant use it GroupDAMAGE.

edit I edited this post a lot after I first posted it , luls.
 

RaiJin

New Member
Reaction score
40
awesome it worked :D now all i need is the angle to work :S because the angle is effed up
 

T.s.e

Wish I was old and a little sentimental
Reaction score
133
> And, don't null struct members. Please, just don't.
Why not? Say you have a struct that's allocated one hundred times. Then say you won't reach that level anymore. Then those values leak...
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Staff online

      Members online

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top