JASS dash spell Inifinite Loops?

wraithseeker

Tired.
Reaction score
122
What's wrong with my spell

JASS:
scope Warstomp initializer Init

globals
private constant integer SPELL = 'AOws'
private boolexpr b
endglobals

struct data
real x
real y
group g
unit caster
integer i
timer t
real duration

static method create takes nothing returns data
local data d = data.allocate()
set d.g = CreateGroup()
set d.caster = GetTriggerUnit()
set d.x = GetUnitX(d.caster)
set d.y = GetUnitY(d.caster)
set d.i = GetUnitAbilityLevel(d.caster,SPELL)
call GroupEnumUnitsInRange(d.g,d.x,d.y,100+50*d.i,b)
call BJDebugMsg("Creating Struct.....")
return d
endmethod

method OnDestroy takes nothing returns nothing
call ReleaseTimer(.t)
call DestroyGroup(.g)
set .g = null
endmethod

endstruct
private function Conditions takes nothing returns boolean
call BJDebugMsg("Conditions Worked!")
    return GetSpellAbilityId() == SPELL
endfunction

private function Check takes nothing returns boolean
call BJDebugMsg("Checking work")
return IsPlayerEnemy(GetOwningPlayer(GetTriggerUnit()), GetOwningPlayer(GetFilterUnit())) and GetWidgetLife(GetFilterUnit()) > 0.405 and not IsUnitType(GetFilterUnit(), UNIT_TYPE_FLYING)
endfunction

private function Loop takes nothing returns nothing
local data d = data(GetTimerData(GetExpiredTimer()))
local real ux
local real uy
local real a
local unit f
call BJDebugMsg("Time To Loop!")
set d.duration = d.i + 0.05
if d.duration < 1+0.5*d.i then
loop
call BJDebugMsg("looping")
set f = FirstOfGroup(d.g)
exitwhen f == null
set ux = GetUnitY(f)
set uy = GetUnitY(f)
set a = Atan2(uy-d.y,ux-d.x)
call SetUnitPosition(f,ux + 40*Cos(a),uy+40*Sin(a))
call GroupRemoveUnit(d.g,f)
endloop
else
call d.destroy()
endif
endfunction

private function Actions takes nothing returns nothing
local data d = data.create()
call SetTimerData(d.t,integer(d))
call TimerStart(d.t,0.05,true,function Loop)
call BJDebugMsg("actions worked")
endfunction

//===========================================================================
private function Init takes nothing returns nothing
    local trigger t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( t, Condition( function Conditions ) )
    call TriggerAddAction( t, function Actions )
    set b = Condition(function Check)
endfunction

endscope


This code isn't pushing enemys back..

Actions , Check , Create , Conditions work fine but the loop just never works.
 

T.s.e

Wish I was old and a little sentimental
Reaction score
133
I don't see you creating the timer anywhere.
 

Viikuna

No Marlo no game.
Reaction score
265
JASS:
set d.t=NewTimer() // goes to create method
 

Naga'sShadow

Ultra Cool Member
Reaction score
49
Does loop fire at all? Because the syntax seems odd. Maybe its just the attachment system but shouldn't this.

JASS:
local data d = data(GetTimerData(GetExpiredTimer()))


be this?

JASS:
local timer t = GetExpiredTimer()
local data d = GetTimerData(t)


I'm not familiar with the system your using so I may be wrong but this is how I've always done it.
 

RaiJin

New Member
Reaction score
40
Code:
call SetUnitPosition(f,ux + 40*Cos(a),uy+40*Sin(a))

why not just do

Code:
call SetUnitX
call SetUnitY
??????
 

Azlier

Old World Ghost
Reaction score
461
Jesus, wraith, ever heard of indenting?

Anyway, I see a problem with this line.
JASS:
set ux = GetUnitY(f)


Any reason as to why ux is equal to your unit's Y?

Second, I see you use a FirstOfGroup loop that removes the units, and yet I do not see you adding them back in so that they can resume sliding.
 

RaiJin

New Member
Reaction score
40
Lol Aizler finds the problem again !!! lol yeah no indenting just raped my eyes
 

wraithseeker

Tired.
Reaction score
122
JASS:
scope Warstomp initializer Init

globals
private constant integer SPELL = 'AOws'
private constant real SPEED = 700
private constant real TIME = 0.03
private boolexpr b
endglobals

struct data
real x
real y
group g
unit caster
integer i
timer t
real duration
real distance

static method create takes nothing returns data
local data d = data.allocate()
set d.g = CreateGroup()
set d.t = NewTimer()
set d.caster = GetTriggerUnit()
set d.x = GetUnitX(d.caster)
set d.y = GetUnitY(d.caster)
set d.i = GetUnitAbilityLevel(d.caster,SPELL)
call GroupEnumUnitsInRange(d.g,d.x,d.y,100+50*d.i,b)
call BJDebugMsg("Creating Struct.....")
return d
endmethod

method OnDestroy takes nothing returns nothing
call ReleaseTimer(.t)
call DestroyGroup(.g)
set .g = null
endmethod
endstruct

private function DISTANCE takes integer level returns integer
return level * 150
endfunction

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

private function Check takes nothing returns boolean
return IsPlayerEnemy(GetOwningPlayer(GetTriggerUnit()), GetOwningPlayer(GetFilterUnit())) and GetWidgetLife(GetFilterUnit()) > 0.405 and not IsUnitType(GetFilterUnit(), UNIT_TYPE_FLYING)
endfunction

private function Loop takes nothing returns nothing
local data d = data(GetTimerData(GetExpiredTimer()))
local real ux
local real uy
local real angle
local unit t
local real cos
local real sin
local group g = d.g
loop
set t = FirstOfGroup(g)
exitwhen t == null
set ux = GetUnitX(t)
set uy = GetUnitY(t)
set angle = Atan2(uy-d.y,ux-d.x)
set cos = Cos(angle)
set sin = Sin(angle)
set ux = ux + cos * TIME * SPEED
set uy = uy + sin * TIME * SPEED
call SetUnitPosition(t,ux,uy)
call GroupRemoveUnit(g,t)
endloop
set d.distance = d.distance - TIME * SPEED
if d.distance <= 0 then
call d.destroy()
endif
endfunction

private function Actions takes nothing returns nothing
local data d = data.create()
local unit caster = GetTriggerUnit()
set d.distance = DISTANCE(GetUnitAbilityLevel(d.caster,SPELL))
call SetTimerData(d.t,integer(d))
call TimerStart(d.t,TIME,true,function Loop)
endfunction

//===========================================================================
private function Init takes nothing returns nothing
    local trigger t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( t, Condition( function Conditions ) )
    call TriggerAddAction( t, function Actions )
    set b = Condition(function Check)
endfunction

endscope


Alright, a revised verison , now why does this push the unit ... alittle bit instead of the distance which i wanted
 

saw792

Is known to say things. That is all.
Reaction score
280
azlier said:
Second, I see you use a FirstOfGroup loop that removes the units, and yet I do not see you adding them back in so that they can resume sliding.

You need another group to store them in while you loop through them so that your sliding group isn't empty next interval.
 

Artificial

Without Intelligence
Reaction score
326
> Doesn't that do the trick?
No. All handle variables contain just pointers to the real handles. So when you do that, you just make group g point to the same group as d.g points to. So when you do something to group g, the exact same thing is done to d.g (as it is the exact same group). I think using a ForGroup would be easiest (as it doesn't require you to copy the group).
 

wraithseeker

Tired.
Reaction score
122
JASS:
scope Warstomp initializer Init

globals
private constant integer SPELL = 'AOws'
private constant real SPEED = 700
private constant real TIME = 0.03
private boolexpr b
endglobals

struct data
real x
real y
group g
unit caster
integer i
timer t
real duration
real distance

static method create takes nothing returns data
local data d = data.allocate()
set d.g = CreateGroup()
set d.t = NewTimer()
set d.caster = GetTriggerUnit()
set d.x = GetUnitX(d.caster)
set d.y = GetUnitY(d.caster)
set d.i = GetUnitAbilityLevel(d.caster,SPELL)
call GroupEnumUnitsInRange(d.g,d.x,d.y,100+50*d.i,b)
call BJDebugMsg("Creating Struct.....")
return d
endmethod

method OnDestroy takes nothing returns nothing
call ReleaseTimer(.t)
call DestroyGroup(.g)
set .g = null
endmethod
endstruct

private function DISTANCE takes integer level returns integer
return level * 150
endfunction

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

private function Check takes nothing returns boolean
return IsPlayerEnemy(GetOwningPlayer(GetTriggerUnit()), GetOwningPlayer(GetFilterUnit())) and GetWidgetLife(GetFilterUnit()) > 0.405 and not IsUnitType(GetFilterUnit(), UNIT_TYPE_FLYING)
endfunction

private function Move takes nothing returns nothing
local data d = data(GetTimerData(GetExpiredTimer()))
local unit t = GetEnumUnit()
local real ux = GetUnitX(t)
local real uy = GetUnitY(t)
local real angle = Atan2(uy-d.y,ux-d.x)
local real cos = Cos(angle)
local real sin = Sin(angle)
set ux = ux + cos * TIME * SPEED
set uy = uy + sin * TIME * SPEED
call SetUnitPosition(t,ux,uy)
endfunction

private function Loop takes nothing returns nothing
local data d = data(GetTimerData(GetExpiredTimer()))
call ForGroup(d.g,function Move)
set d.distance = d.distance - TIME * SPEED
if d.distance <= 0 then
call d.destroy()
endif
endfunction

private function Actions takes nothing returns nothing
local data d = data.create()
local unit caster = GetTriggerUnit()
set d.distance = DISTANCE(GetUnitAbilityLevel(d.caster,SPELL))
call SetTimerData(d.t,integer(d))
call TimerStart(d.t,TIME,true,function Loop)
endfunction

//===========================================================================
private function Init takes nothing returns nothing
    local trigger t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( t, Condition( function Conditions ) )
    call TriggerAddAction( t, function Actions )
    set b = Condition(function Check)
endfunction

endscope


Works good now but now the units never ever stop moving?
 

Artificial

Without Intelligence
Reaction score
326
JASS:
//     v
method OnDestroy takes nothing returns nothing
//     ^

Use a lower-case O in case you want that method to actually run when an instance is destroyed. If it doesn't run, the timer is never stopped.
 

Azlier

Old World Ghost
Reaction score
461
Hmm... Well, I can't quite place my finger on why they don't stop moving. Probably some of that funky math you're doing with distance. But, I can point out problems.

1. The group filter. I don't think boolexprs work like that...

2. Please, don't null the group in your onDestroy method. Struct members don't work like that.

3. You don't null t in the Move function.

4. data(GetTimerData(GetExpiredTimer()))? I didn't know data was a function. Structs can be passed around just like integers. No need for the fancy data(...).

5. In actions, you use GetUnitAbilityLevel when it's already in your struct as d.i.

Edit: Good catch, Artificial.
 

saw792

Is known to say things. That is all.
Reaction score
280
IIRC, you can't refer to an expired timer outside of the callback function as well. In that case you would store the struct in a global integer variable and use that in the group callback (eg: 'local data d = D') since no time expires during the ForGroup.
 

Azlier

Old World Ghost
Reaction score
461
Where is he trying GetExpiredTimer() outside of the callback :confused:
 

Flare

Stops copies me!
Reaction score
662
1. The group filter. I don't think boolexprs work like that...
Work like what? I can't see why anything would be wrong with it (he's just setting it to a variable, then using the variable instead of Condition (function ...) from what I can see)

Also,
2. Please, don't null the group in your onDestroy method. Struct members don't work like that.
4. data(GetTimerData(GetExpiredTimer()))? I didn't know data was a function. Structs can be passed around just like integers. No need for the fancy data(...).
Those aren't problems. There isn't anything specifically wrong with doing either. Nulling a global shouldn't cause any problems, and struct cast won't either (I think that's a safety to prevent people using structs that haven't been instanciated, not 100% sure though)
 

Azlier

Old World Ghost
Reaction score
461
When I say 'problems', I mean "I wouldn't have done that."

And, a boolexpr can be saved in a variable like that and still work correctly as a group enum? Oh noes! I used Filter(function whatever) all the time! Must... optimize... script...
 

wraithseeker

Tired.
Reaction score
122
JASS:
scope Warstomp initializer Init

globals
private constant integer SPELL = 'AOws'
private constant real TIME = 0.03
private constant string EFFECT = "Objects\\Spawnmodels\\Undead\\ImpaleTargetDust\\ImpaleTargetDust.mdl"
private boolexpr b
endglobals

struct data
real x
real y
group g
unit caster
integer i
timer t
real duration
real distance
real fx
real speed

static method create takes nothing returns data
local data d = data.allocate()
set d.g = CreateGroup()
set d.t = NewTimer()
set d.caster = GetTriggerUnit()
set d.x = GetUnitX(d.caster)
set d.y = GetUnitY(d.caster)
set d.i = GetUnitAbilityLevel(d.caster,SPELL)
set d.speed = 600
call GroupEnumUnitsInRange(d.g,d.x,d.y,100+50*d.i,b)
call BJDebugMsg("Creating Struct.....")
return d
endmethod

method onDestroy takes nothing returns nothing
call ReleaseTimer(.t)
endmethod
endstruct

private function DISTANCE takes integer level returns integer
return level * 250
endfunction

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

private function Check takes nothing returns boolean
    return IsPlayerEnemy(GetOwningPlayer(GetTriggerUnit()), GetOwningPlayer(GetFilterUnit())) and GetWidgetLife(GetFilterUnit()) > 0.405 and not IsUnitType(GetFilterUnit(), UNIT_TYPE_FLYING)
endfunction

private function Move takes nothing returns nothing
local data d = data(GetTimerData(GetExpiredTimer()))
local unit t = GetEnumUnit()
local real ux = GetUnitX(t)
local real uy = GetUnitY(t)
local real angle = Atan2(uy-d.y,ux-d.x)
local real cos = Cos(angle)
local real sin = Sin(angle)
set ux = ux + cos * TIME * d.speed
set uy = uy + sin * TIME * d.speed
call SetUnitPosition(t,ux,uy)
call DestroyEffect(AddSpecialEffect(EFFECT,ux,uy))
endfunction

private function Loop takes nothing returns nothing
local data d = data(GetTimerData(GetExpiredTimer()))
set d.speed = d.speed + 30
set d.distance = d.distance - TIME * d.speed
if d.distance <= 0 then
call d.destroy()
endif
call ForGroup(d.g,function Move)
endfunction

private function Actions takes nothing returns nothing
local data d = data.create()
local unit caster = GetTriggerUnit()
set d.distance = DISTANCE(GetUnitAbilityLevel(d.caster,SPELL))
call SetTimerData(d.t,integer(d))
call TimerStart(d.t,TIME,true,function Loop)
set caster = null
endfunction

//===========================================================================
private function Init takes nothing returns nothing
    local trigger t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( t, Condition( function Conditions ) )
    call TriggerAddAction( t, function Actions )
    set b = Condition(function Check)
endfunction

endscope


I finally got all the effects and knockback done * cough *

Now I have some problems, I want to limit the SFX to 8, how do i do that?

With my current speed code, will the speed get increased?
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Members online

      No members online now.

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top