question about call UnitDamageTarget

cleeezzz

The Undead Ranger.
Reaction score
268
lol, i dont think it is the filter, if it was the filter, the arrow would still move but not damage anything. thats a different story.

im not good at attatching either, ill compare it to another trigger.

it looks right =/
call SetCSData (timer, suffix of the struct)
(not sure if thats what its really called lol)
 

cleeezzz

The Undead Ranger.
Reaction score
268
no not yet, i dont have WE available, but i was just making a guess, changing the filter would only affect the damage part which wouldn't solve the moving, unless you could point out otherwise xd

oh and btw, function FilterIsUnitEnemyAlive was another custom function i based of your original (since i do want to damage Structures, but i still might need it later)
 

Kenny

Back for now.
Reaction score
202
My reasoning for it is pretty simple, when you create the arrow, the Move function immediately begins to check if units are close, so using bj_groupEnumOwningPlayer, instead of GetOwningPlayer(Caster) will cause the filter to not check for enemies since bj_groupEnumOwningPlayer hasn't been set for this spell, therefore when it is immediately created it will be immediately destroyed because there is a unit nearby.

Well that is what i think would/should happen.

*EDIT*

If that doesn't work, trying not using your polarprojection functions, see if that has something to do with anything.

Also your Move_dist is set to 44, but it is a real, so change it to 44.00 <-- I'd laugh if that was ur problem
 

cleeezzz

The Undead Ranger.
Reaction score
268
i dont follow you, the filter is only for the group action which then loops to damage units. i dont see how that affects the SetUnitX and SetUnitY, as far as i can see, the SetUnitX and Y should run before the group is created. which shouldn't matter anyway because the group doesn't affect the arrows movement

o_O

EDIT: 44.00, i would laugh too, although if that was an error, shouldn't pjass pick that up? =.=
 

Kenny

Back for now.
Reaction score
202
I don't think anyone really chose to make it static, it is just how software programming works, some one from the NewGen team probably saw that this makes things work on other programs so they implemented it into vJass.

Static is mainly used on create methods, and it isn't much of a hastle to put d. or data. infront of things because thats what you would be doing in the Actions function, but i guess it was done because it was the easiest way...

but im not a programmer so i have no idea.

*EDIT*

I don't think pjass would pick it up because a real is just a number, so it doesn't need decimal places, but i have heard ages ago that things using reals that do not have decimal places may cause the warcraft engine that it is an integer which could cause problems, once again i aint sure.
 

cleeezzz

The Undead Ranger.
Reaction score
268
you went off the current topic xd but thanks for the info.

EDIT; alright. we'll see tomorrow.

EDIT: how do i do GetOwningPlayer(Caster) ?

doesn't the function have to have an argument to do that?

function FilterIsEnemyAlive takes unit Caster returns boolean
 

Flare

Stops copies me!
Reaction score
662
how do i do GetOwningPlayer(Caster) ?

doesn't the function have to have an argument to do that?

function FilterIsEnemyAlive takes unit Caster returns boolean

Filter functions can't take arguments, so you have to assign your local unit to a global var before calling the GroupEnum or ForGroup

kenny! said:
Caster in that filter is a global unit that has been get to GetTriggerUnit() in the Actions function.
 

cleeezzz

The Undead Ranger.
Reaction score
268
JASS:
scope SA initializer InitTrig

globals
    // Configurables:
    private constant integer Abil_id = &#039;A011&#039;  // Your spells raw code
    private constant integer Unit_id = &#039;h00J&#039;  // Your dummy unit
    private constant real Period = 0.04        // Interval on the periodic timer
    private constant real Start_dist = 10.00   // Don&#039;t worry about this really, distance dummy unit starts away from the hero, i guess you would want this low
    private constant real Radius = 25.00       // Radius obviously
    private constant real Scale = 1            // Scale size of the arrow
    private constant real Fly_height = 60.00   // Fly height of the arrow
    private constant attacktype A_type = ATTACK_TYPE_CHAOS
    private constant damagetype D_type = DAMAGE_TYPE_UNIVERSAL
    private unit Caster
endglobals

//=======================================================================
private function Damage takes integer lvl returns real
    return 133.33+(66.66*lvl)
endfunction

private function Max_dist takes integer lvl returns real
    return 333.33+(666.66*lvl) 
endfunction

//=======================================================================
private struct SAD
    timer t
    unit cast
    unit dummy
    real castx
    real casty
    real targx
    real targy
    real Move_dist
    real dist = Start_dist
    real angle
    integer level
    group Group1 = CreateGroup()
    group Group2 = CreateGroup()
   
    static method create takes nothing returns SAD
        local SAD data = SAD.allocate()
        local location targ = GetSpellTargetLoc()
        set data.cast = GetTriggerUnit()
        set data.castx = GetUnitX(data.cast)
        set data.casty = GetUnitY(data.cast)
        set data.targx = GetLocationX(targ)
        set data.targy = GetLocationY(targ)
        set data.angle = AngleXY(data.castx,data.casty,data.targx,data.targy)
        set data.Move_dist = 44.00
        set data.level = GetUnitAbilityLevel(data.cast,Abil_id)
        set Caster = data.cast
       
        set data.dummy = CreateUnit(GetOwningPlayer(data.cast),Unit_id, PolarProjectionX (data.castx, Start_dist, data.angle), PolarProjectionY (data.casty, Start_dist, data.angle) , 0.00)
        call SetUnitFacing(data.dummy,data.angle)
        call SetUnitPathing(data.dummy,false)
        call SetUnitScale(data.dummy,Scale,Scale,Scale)
        call SetUnitFlyHeight(data.dummy,Fly_height,0.00)
       
        call RemoveLocation(targ)
        set targ = null
        return data
    endmethod
   
    private method onDestroy takes nothing returns nothing
        call KillUnit(.dummy)
        call GroupClear(.Group1)
        call DestroyGroup(.Group1)
        call ReleaseTimer(.t)
    endmethod
endstruct

//=======================================================================
private function Move takes nothing returns nothing
    local SAD data = GetCSData(GetExpiredTimer())
    local unit u
    local real x = GetUnitX(data.dummy)
    local real y = GetUnitY(data.dummy)
   
    set data.dist = data.dist + data.Move_dist
    if data.dist &gt;= Max_dist(data.level) then
        call data.destroy()
        return
    endif
   
    set x = PolarProjectionX(x, data.Move_dist, data.angle)
    set y = PolarProjectionY(y, data.Move_dist, data.angle)
   
    call SetUnitX(data.dummy,SafeX(x))
    call SetUnitY(data.dummy,SafeY(y))
    call GroupClear(data.Group2)
    call GroupEnumUnitsInRange(data.Group2,SafeX(x),SafeY(y),Radius,Condition(function FilterIsEnemyAlive))
        loop
            set u = FirstOfGroup(data.Group2)
            exitwhen u == null
            if not(IsUnitInGroup(u,data.Group1)) then
                call GroupAddUnit(data.Group1,u)
                call UnitDamageTarget(data.cast,u,Damage(data.level),false,false,A_type,D_type,null)
                call GroupRemoveUnit(data.Group2,u)
            endif
                call GroupRemoveUnit(data.Group2,u)
        endloop
endfunction
   
//=======================================================================
private function Actions takes nothing returns nothing
    local SAD data = SAD.create()
   
    set data.t = NewTimer()
    call TimerStart(data.t,Period,true,function Move)
    call SetCSData(data.t,data)
endfunction

//=======================================================================
private function Conditions takes nothing returns boolean
    return GetSpellAbilityId()== Abil_id
endfunction


//=======================================================================
private function InitTrig takes nothing returns nothing
    local trigger trig = CreateTrigger()   
    call TriggerRegisterAnyUnitEventBJ(trig,EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddCondition(trig,Condition(function Conditions))
    call TriggerAddAction(trig,function Actions)
endfunction

endscope


JASS:
function FilterIsEnemyAlive takes nothing returns boolean
    return IsUnitEnemy(GetFilterUnit(), GetOwningPlayer(Caster)) and GetWidgetLife(GetFilterUnit())&gt;0.405
endfunction


same results =/
either timer isn't working correctly, or my PolarProjections dont work. but if they dont work, whats wrong with them?
JASS:
function PolarProjectionX takes real x, real distance, real angle returns real
    return x + distance * Cos(angle)
endfunction

function PolarProjectionY takes real y, real distance, real angle returns real
    return y + distance * Sin(angle)
endfunction


edit: im 100% sure my polar projections work, my spread shot skill uses them and it works fine.

edit: timer works because the arrow dies, yet why isn't it moving..

EDIT: so if timer is working..that means its something wrong in the polar projection area or set x,y area.
 

Kenny

Back for now.
Reaction score
202
Trying using a custom filter:

JASS:
function FilterIsEnemyAlive takes nothing returns boolean
    return IsUnitEnemy(GetFilterUnit(), GetOwningPlayer(Caster)) and GetWidgetLife(GetFilterUnit())&gt;0.405
endfunction



That won't work because the function is not within the scope, therefore the private global Caster will not register in that function, just make a filter within the scope that is identical to the one you have, and put it up near damage and max dist functions. Oh yeah and make it private.
 

cleeezzz

The Undead Ranger.
Reaction score
268
alright but i still don't see how that affects the offset and movement of the arrow XD (dont have WE, never at night)

and i changed it to SAD data, for some reason, Data d was really confusing.

and every time the Move trigger is called by the timer, it calls for Max_dist(d.level)
would it be better to set that into a struct so it only runs the function once?

(if i remember right, unnecessary function calls are bad cuz it slows it down?)
 

Kenny

Back for now.
Reaction score
202
alright but i still don't see how that affects the offset and movement of the arrow XD

Maybe because it cannot check for enemies properly, but if this doesn't work then at least it will narrow it down, im going to put the spell into my map to check it out.

and i changed it to SAD data, for some reason, Data d was really confusing.

Whatever your comfortable with.

and every time the Move trigger is called by the timer, it calls for Max_dist(d.level)
would it be better to set that into a struct so it only runs the function once?


Um i guess you could, but honestly i don't think it makes a difference, like the time factor would be incredibly minimal.

(if i remember right, unnecessary function calls are bad because it slows it down?)

That is true.

*EDIT*

Did you remove the SafeX and SafeY functions from the spell and put them into the library or just remove them completely?

Also what did you do with the AngleXY function?

*EDIT 2*

Wait! um... in your polar projections functions, where it says Sin(angle) and Cos(angle), try Sin(angle*bj_DEGTORAD) and Cos(angle*bj_DEGTORAD), cause thats how i do my angles.
 

cleeezzz

The Undead Ranger.
Reaction score
268
the library you gave me came with SafeX and SafeY so i deleted the ones in the main trigger and used the library functions.

what did i do with AngleXY?
i took out * 57.4234 or w.e
cuz tahts just converting it to degrees right?
>(Angle * bj_DEGTORAD)
i dont think thats necessary since my angle is already in radians

i dont think the angle matters does it? even if it had an error and returned 0 radians, the worst would be the arrow flying off in the wrong direction O_O
 

Kenny

Back for now.
Reaction score
202
Ahhhh, ok then fair enough, well im guessing its gotta be ur filter then...

I just implemented the spell it changed it a bit, like using ABC now, and it works fine...

Read through this and see if there is any major differences:

JASS:
scope ShootArrow initializer InitTrig

globals
    // Configurables:
    private constant integer Abil_id = &#039;A00C&#039;  // Your spells raw code
    private constant integer Unit_id = &#039;h001&#039;  // Your dummy unit
    private constant real Period = 0.04        // Interval on the periodic timer
    private constant real Start_dist = 5.00   // Don&#039;t worry about this really, distance dummy unit starts away from the hero, i guess you would want this low
    private constant real Radius = 25.00       // Radius obviously
    private constant real Move_dist = 40.00    // Distance moved per interval &lt;-- i think this would be better kept as a global not struct member
    private constant real Scale = 1            // Scale size of the arrow
    private constant real Fly_height = 60.00   // Fly height of the arrow
    private constant attacktype A_type = ATTACK_TYPE_CHAOS
    private constant damagetype D_type = DAMAGE_TYPE_UNIVERSAL
    private unit Caster
    private real Game_MaxX                              // Needed to keep things in map
    private real Game_MinX                              // Needed to keep things in map
    private real Game_MaxY                              // Needed to keep things in map
    private real Game_MinY                              // Needed to keep things in map
endglobals

//=======================================================================
private function Damage takes integer lvl returns real
    return 0.00+(100.00*lvl)
endfunction

private function Max_dist takes integer lvl returns real
    return 2000.00+(0.00*lvl)
endfunction

private function FilterEnemies takes nothing returns boolean
	return IsUnitEnemy(GetFilterUnit(),GetOwningPlayer(Caster)) and GetWidgetLife(GetFilterUnit())&gt;0.405 and (IsUnitType(GetFilterUnit(),UNIT_TYPE_STRUCTURE)==false) and GetUnitFlyHeight(GetFilterUnit())&lt;150.00
endfunction

//=======================================================================
private function AngleXY takes real x, real y, real xx, real yy returns real
    return Atan2((yy-y),(xx-x))*57.29583
endfunction

private function SafeX takes real x returns real
    if x&lt;Game_MinX then
        return Game_MinX
    elseif x&gt;Game_MaxX then   
        return Game_MaxX
    endif
    return x
endfunction

private function SafeY takes real y returns real
    if y&lt;Game_MinY then
        return Game_MinY
    elseif y&gt;Game_MaxY then 
        return Game_MaxY
    endif
    return y
endfunction

//=======================================================================
private struct Data
    timer t
    unit cast
    unit dummy
    real castx
    real casty
    real targx
    real targy
    real dist = Start_dist
    real sin
    real cos
    integer level
    group Group1 = CreateGroup()
    group Group2 = CreateGroup()
   
    static method create takes nothing returns Data
        local Data d = Data.allocate()
        local location targ = GetSpellTargetLoc()
        local real angle
        
        set d.cast = GetTriggerUnit()
        set d.castx = GetUnitX(d.cast)
        set d.casty = GetUnitY(d.cast)
        set d.targx = GetLocationX(targ)
        set d.targy = GetLocationY(targ)
        set angle = AngleXY(d.castx,d.casty,d.targx,d.targy)
        set d.sin = Sin(angle*bj_DEGTORAD)
        set d.cos = Cos(angle*bj_DEGTORAD)
        set d.level = GetUnitAbilityLevel(d.cast,Abil_id)
        set Caster = d.cast
       
        set d.dummy = CreateUnit(GetOwningPlayer(d.cast),Unit_id,d.castx+Start_dist*d.cos,d.casty+Start_dist*d.sin,angle)
        call SetUnitPathing(d.dummy,false)
        call SetUnitScale(d.dummy,Scale,Scale,Scale)
        call SetUnitFlyHeight(d.dummy,Fly_height,0.00)
       
        call RemoveLocation(targ)
        set targ = null
        return d
    endmethod
   
    private method onDestroy takes nothing returns nothing
        call KillUnit(.dummy)
        call GroupClear(.Group1)
        call DestroyGroup(.Group1)
        call GroupClear(.Group2) // Clear this group too
        call DestroyGroup(.Group2) // Destroy this group too
        call ClearTimerStructA(.t)
        call ReleaseTimer(.t)
    endmethod
endstruct

//=======================================================================
private function Move takes nothing returns nothing
    local Data d = GetTimerStructA(GetExpiredTimer())
    local unit u
    local real dumx = GetUnitX(d.dummy)
    local real dumy = GetUnitY(d.dummy)
   
    set d.dist = d.dist + Move_dist // once again move_dist isn&#039;t needed in the struct, it is better as a constant global
    if d.dist &gt;= Max_dist(d.level) then
        call d.destroy()
        return
    endif
   
    set dumx = dumx+Move_dist*d.cos // You would obviously have all your angles and stuff
    set dumy = dumy+Move_dist*d.sin
   
    call SetUnitX(d.dummy,SafeX(dumx))
    call SetUnitY(d.dummy,SafeY(dumy))
    call GroupClear(d.Group2)
    call GroupEnumUnitsInRange(d.Group2,SafeX(dumx),SafeY(dumy),Radius,Condition(function FilterEnemies))
        loop
            set u = FirstOfGroup(d.Group2)
            exitwhen u == null
            if not(IsUnitInGroup(u,d.Group1)) then
                call GroupAddUnit(d.Group1,u)
                call UnitDamageTarget(d.cast,u,Damage(d.level),false,false,A_type,D_type,null)
                call GroupRemoveUnit(d.Group2,u)
            endif
                call GroupRemoveUnit(d.Group2,u)
        endloop
endfunction
   
//=======================================================================
private function Actions takes nothing returns nothing
    local Data d = Data.create()
   
    set d.t = NewTimer()
    call SetTimerStructA(d.t,d)
    call TimerStart(d.t,Period,true,function Move)
endfunction

//=======================================================================
private function Conditions takes nothing returns boolean
    return GetSpellAbilityId()== Abil_id
endfunction

//=======================================================================
private function InitTrig takes nothing returns nothing
    local trigger trig = CreateTrigger()  
    set Game_MaxX = GetRectMaxX(bj_mapInitialPlayableArea)-50.00
    set Game_MinX = GetRectMinX(bj_mapInitialPlayableArea)+50.00
    set Game_MaxY = GetRectMaxY(bj_mapInitialPlayableArea)-50.00
    set Game_MinY = GetRectMinY(bj_mapInitialPlayableArea)+50.00
    call TriggerRegisterAnyUnitEvent(trig,EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddCondition(trig,Condition(function Conditions))
    call TriggerAddAction(trig,function Actions)
endfunction

endscope


I obviously dont have my library in the map i do my coding in, so thats why i always put those SafeX, SafeY and angle functions back in.
 

cleeezzz

The Undead Ranger.
Reaction score
268
oh noez, ABC!

hmm CSData or ABC
it looks the same =.=
except of course the angle function. mine doesn't convert to deg. other than that, its the same.

oh and i wanted Move_dist to be a struct member cuz i wanted to have a speed boost ability or something.

JASS:
scope SA initializer InitTrig

globals
    // Configurables:
    private constant integer Abil_id = &#039;A011&#039;  // Your spells raw code
    private constant integer Unit_id = &#039;h00J&#039;  // Your dummy unit
    private constant real Period = 0.04        // Interval on the periodic timer
    private constant real Start_dist = 10.00   // Don&#039;t worry about this really, distance dummy unit starts away from the hero, i guess you would want this low
    private constant real Radius = 25.00       // Radius obviously
    private constant real Scale = 1            // Scale size of the arrow
    private constant real Fly_height = 60.00   // Fly height of the arrow
    private constant attacktype A_type = ATTACK_TYPE_CHAOS
    private constant damagetype D_type = DAMAGE_TYPE_UNIVERSAL
    private unit Caster
endglobals

//=======================================================================
private function Damage takes integer lvl returns real
    return 133.33+(66.66*lvl)
endfunction

private function Max_dist takes integer lvl returns real
    return 333.33+(666.66*lvl) 
endfunction

function CustomFilter takes nothing returns boolean
    return IsUnitEnemy(GetFilterUnit(), GetOwningPlayer(Caster)) and GetWidgetLife(GetFilterUnit())&gt;0.405
endfunction



//=======================================================================
private struct SAD
    timer t
    unit cast
    unit dummy
    real castx
    real casty
    real targx
    real targy
    real Move_dist
    real dist = Start_dist
    real angle
    integer level
    group Group1 = CreateGroup()
    group Group2 = CreateGroup()
   
    static method create takes nothing returns SAD
        local SAD data = SAD.allocate()
        local location targ = GetSpellTargetLoc()
        set data.cast = GetTriggerUnit()
        set data.castx = GetUnitX(data.cast)
        set data.casty = GetUnitY(data.cast)
        set data.targx = GetLocationX(targ)
        set data.targy = GetLocationY(targ)
        set data.angle = AngleXY(data.castx,data.casty,data.targx,data.targy)
        set data.Move_dist = 44.00
        set data.level = GetUnitAbilityLevel(data.cast,Abil_id)
        set Caster = data.cast
       
        set data.dummy = CreateUnit(GetOwningPlayer(data.cast),Unit_id, PolarProjectionX (data.castx, Start_dist, data.angle), PolarProjectionY (data.casty, Start_dist, data.angle) , data.angle)
        call SetUnitPathing(data.dummy,false)
        call SetUnitScale(data.dummy,Scale,Scale,Scale)
        call SetUnitFlyHeight(data.dummy,Fly_height,0.00)
       
        call RemoveLocation(targ)
        set targ = null
        return data
    endmethod
   
    private method onDestroy takes nothing returns nothing
        call KillUnit(.dummy)
        call GroupClear(.Group1)
        call DestroyGroup(.Group1)
        call ReleaseTimer(.t)
    endmethod
endstruct

//=======================================================================
private function Move takes nothing returns nothing
    local SAD data = GetCSData(GetExpiredTimer())
    local unit u
    local real x = GetUnitX(data.dummy)
    local real y = GetUnitY(data.dummy)
   
    set data.dist = data.dist + data.Move_dist
    if data.dist &gt;= Max_dist(data.level) then
        call data.destroy()
        return
    endif
   
    set x = PolarProjectionX(x, data.Move_dist, data.angle)
    set y = PolarProjectionY(y, data.Move_dist, data.angle)
   
    call SetUnitX(data.dummy,SafeX(x))
    call SetUnitY(data.dummy,SafeY(y))
    call GroupClear(data.Group2)
    call GroupEnumUnitsInRange(data.Group2,SafeX(x),SafeY(y),Radius,Condition(function CustomFilter))
        loop
            set u = FirstOfGroup(data.Group2)
            exitwhen u == null
            if not(IsUnitInGroup(u,data.Group1)) then
                call GroupAddUnit(data.Group1,u)
                call UnitDamageTarget(data.cast,u,Damage(data.level),false,false,A_type,D_type,null)
                call GroupRemoveUnit(data.Group2,u)
            endif
                call GroupRemoveUnit(data.Group2,u)
        endloop
endfunction
   
//=======================================================================
private function Actions takes nothing returns nothing
    local SAD data = SAD.create()
   
    set data.t = NewTimer()
    call TimerStart(data.t,Period,true,function Move)
    call SetCSData(data.t,data)
endfunction

//=======================================================================
private function Conditions takes nothing returns boolean
    return GetSpellAbilityId()== Abil_id
endfunction


//=======================================================================
private function InitTrig takes nothing returns nothing
    local trigger trig = CreateTrigger()   
    call TriggerRegisterAnyUnitEventBJ(trig,EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddCondition(trig,Condition(function Conditions))
    call TriggerAddAction(trig,function Actions)
endfunction

endscope


there, custom filter, still doesn't move
 

cleeezzz

The Undead Ranger.
Reaction score
268
im not sure if i want to switch to using ABC, can anyone see the problem? (why the dummy unit isn't sliding)
 

Kenny

Back for now.
Reaction score
202
I honestly can't see the problem really, so its time to resort to changing things that probably eon't matter :p lol.

Clear and destroy Group2 in the onDestroy method, just like Group1.

Try putting SetCSData above the timer call.

Try another attachment system.

Im almost 100% sure these wont do anything, except for changing system (not to sure about that), but when i am completely out of ideas i fiddle around with the code until i can get it to work. Just try making sure all raw codes are the rights ones, make new skills if you need to (in object editor), make a new dummy unit, that kind of stuff.

Ill keep looking through it when i got time, but i gotta to some work.

*EDIT*

I suggest putting in some BJDebugMsg()'s to find out whether certain functions are actually being run.

Put one where the unit is being created, one when the timer starts, one when the unit is moved in interval and one in the onDestroy method. If one doesn't run, then we will know where the problem is.
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Members online

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top