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.
  • Ghan Ghan:
    Howdy
  • Ghan Ghan:
    Still lurking
    +3
  • The Helper The Helper:
    I am great and it is fantastic to see you my friend!
    +1
  • The Helper The Helper:
    If you are new to the site please check out the Recipe and Food Forum https://www.thehelper.net/forums/recipes-and-food.220/
  • Monovertex Monovertex:
    How come you're so into recipes lately? Never saw this much interest in this topic in the old days of TH.net
  • Monovertex Monovertex:
    Hmm, how do I change my signature?
  • tom_mai78101 tom_mai78101:
    Signatures can be edit in your account profile. As for the old stuffs, I'm thinking it's because Blizzard is now under Microsoft, and because of Microsoft Xbox going the way it is, it's dreadful.
  • The Helper The Helper:
    I am not big on the recipes I am just promoting them - I use the site as a practice place promoting stuff
    +2
  • Monovertex Monovertex:
    @tom_mai78101 I must be blind. If I go on my profile I don't see any area to edit the signature; If I go to account details (settings) I don't see any signature area either.
  • The Helper The Helper:
    You can get there if you click the bell icon (alerts) and choose preferences from the bottom, signature will be in the menu on the left there https://www.thehelper.net/account/preferences
  • The Helper The Helper:
    I think I need to split the Sci/Tech news forum into 2 one for Science and one for Tech but I am hating all the moving of posts I would have to do
  • The Helper The Helper:
    What is up Old Mountain Shadow?
  • The Helper The Helper:
    Happy Thursday!
    +1
  • Varine Varine:
    Crazy how much 3d printing has come in the last few years. Sad that it's not as easily modifiable though
  • Varine Varine:
    I bought an Ender 3 during the pandemic and tinkered with it all the time. Just bought a Sovol, not as easy. I'm trying to make it use a different nozzle because I have a fuck ton of Volcanos, and they use what is basically a modified volcano that is just a smidge longer, and almost every part on this thing needs to be redone to make it work
  • Varine Varine:
    Luckily I have a 3d printer for that, I guess. But it's ridiculous. The regular volcanos are 21mm, these Sovol versions are about 23.5mm
  • Varine Varine:
    So, 2.5mm longer. But the thing that measures the bed is about 1.5mm above the nozzle, so if I swap it with a volcano then I'm 1mm behind it. So cool, new bracket to swap that, but THEN the fan shroud to direct air at the part is ALSO going to be .5mm to low, and so I need to redo that, but by doing that it is a little bit off where it should be blowing and it's throwing it at the heating block instead of the part, and fuck man
  • Varine Varine:
    I didn't realize they designed this entire thing to NOT be modded. I would have just got a fucking Bambu if I knew that, the whole point was I could fuck with this. And no one else makes shit for Sovol so I have to go through them, and they have... interesting pricing models. So I have a new extruder altogether that I'm taking apart and going to just design a whole new one to use my nozzles. Dumb design.
  • Varine Varine:
    Can't just buy a new heatblock, you need to get a whole hotend - so block, heater cartridge, thermistor, heatbreak, and nozzle. And they put this fucking paste in there so I can't take the thermistor or cartridge out with any ease, that's 30 dollars. Or you can get the whole extrudor with the direct driver AND that heatblock for like 50, but you still can't get any of it to come apart
  • Varine Varine:
    Partsbuilt has individual parts I found but they're expensive. I think I can get bits swapped around and make this work with generic shit though
  • Ghan Ghan:
    Heard Houston got hit pretty bad by storms last night. Hope all is well with TH.
  • The Helper The Helper:
    Power back on finally - all is good here no damage
    +1
  • V-SNES V-SNES:
    Happy Friday!
    +1

      The Helper Discord

      Members online

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top