Snippet MakeUnitSway

Flare

Stops copies me!
Reaction score
662
The reason why I used a timer, and not Blizz' native, was that I actually wanted a bit of help making it smoother, and I knew that Blizz' native couldn't do that... So, anybody got an alternative?
??? What?

Also, your StopUnitSway is still messed up, and you could handle MakeUnitSway and MakeUnitSwayTimed in the same callback, so you'd still be able to say "uses a single timer" :p

And remove the "requires DAS" from first post
 

Vestras

Retired
Reaction score
248
> What?

What's there not to understand?

> Also, your StopUnitSway is still messed up, and you could handle MakeUnitSway and MakeUnitSwayTimed in the same callback, so you'd still be able to say "uses a single timer" :p

How "messed up"? And how would I do that?

> And remove the "requires DAS" from first post

Done
 

Larcenist

REP: Respect, Envy, Prosperity?
Reaction score
211
How "messed up"? And how would I do that?

Remove the whole function and deal with it in the callback. The way it is now it's not working as planned at all.

This is the idea:

You have 5 instances A, B, C, D and E. E would be D[N] since it's the last instance.

Say instance C ends, then you loop backwards from instance E -> A checking if they're done. When reaching instance C you destroy that struct, and uses set D = D[N] (replaces C with E).

Now your instances should look like this:

A, B, E, D (Since you decrease N with 1 when an instance is removed, instance D would now be D[N]).

What you're doing is decreasing N for each instance, whether it is done or not. Same example with your way of doing it.

Starts with instance E (which is D[N]), you then destroy E, replaces E with D[N] (which is E). Now instance D is D[N], and next step is checking instance D. This will do the same as it did for instance E, destroy and replace D with D, starting to see the problem?

In the end you'll end up with no instances just because one ended.
 

Flare

Stops copies me!
Reaction score
662
What's there not to understand?
Blizz natives vs timer?
What native(s) are you talking about? The SetUnitFlyHeight one?

Also, if you want a smooth increment, find a parabola function, then do
JASS:
//BEWARE: I can't guarantee this even works, but I think it should

set zInc = RAbsBJ (ParabolaFunc (currentTime, totalTime, swayHeight) - GetUnitFlyHeight (whichUnit))
//currentTime is the time elapsed from lowest point in the way
//(currentTime will be cyclic in nature i.e. will go from 0 towards X, then back to 0 when it reaches X
//totalTime is the total time to get from lowest point of sway, to highest point of sway
//swayHeight is lowest value for height for the sway, subtracted from the highest value for height of the sway (based on height above ground, not with respect to the unit)
//and subtract GetUnitFlyHeight for the increment required
if data.hasReachedMax then
  call SetUnitFlyHeight (whichUnit, GetUnitFlyHeight (whichUnit) - zInc, 0)
else
  call SetUnitFlyHeight (whichUnit, GetUnitFlyHeight (whichUnit) + zInc, 0)
endif

//Also, you can calculate currentTime as
set currentTime = RAbsBJ (((maxSwayHeight - minSwayHeight) + 1)/(maxSwayHeight + 1)) //1 is required to prevent Divide by Zero errors to, hopefully, avoid Divide by Zero situations
set totalTime = 1


And how would I do that?
An additional boolean struct member, and a real counter (again, a struct member) - start the counter at intendedDuration, then
JASS:
if data.isInstanceTimed then
  set data.duration = data.duration - TIMER_INT
endif

if data.duration <= 0 then
  call EndThisInstance (...)
endif


How "messed up"?
Very - it's pretty much rendered the system non-MUI.

Read through the code, and say to yourself "What is this line doing?" - you're doing 2 things wrong (if you can't find them for yourself, I'll point them out)
JASS:
function StopUnitSway takes unit whichUnit returns nothing
    local Data d
    local integer i=N
    loop
        exitwhen i<=0
        set d=D<i>
        if d.swayer==null then
            call BJDebugMsg(&quot;|cffff0000MakeUnitSway|r: invalid unit.&quot;)
            return
        endif
        set D<i>=D[N]
        set N=N-1
        if N==0 then
            call PauseTimer(T)
        endif
        call SetUnitFlyHeight(d.swayer,d.height,RATE)
        call d.destroy()
        set i=i-1
    endloop</i></i>
 

Vestras

Retired
Reaction score
248
> Read through the code, and say to yourself "What is this line doing?" - you're doing 2 things wrong (if you can't find them for yourself, I'll point them out)

I'm not entirely sure, but isn't it the part where I set D=D[N]?

> Also, if you want a smooth increment, find a parabola function, then do

Is all the variables (currentTime, totalTime, swayHeight) struct data? And should they just be initialized as 0?

> Blizz natives vs timer?
What native(s) are you talking about? The SetUnitFlyHeight one?

Yeah.

> An additional boolean struct member, and a real counter (again, a struct member) - start the counter at intendedDuration, then

I'll at that.
 

Darius34

New Member
Reaction score
30
That'd give you a syntax error :p - syntax checker does point out the lack of a return IIRC (unless I'm dreaming about random errors >_<)
I thought that might happen, but then I heard about this from people in WC3C in a thread I created recently (link), so I didn't test.
 

Flare

Stops copies me!
Reaction score
662
I'm not entirely sure, but isn't it the part where I set D=D[N]?

No, that's one of the good lines :)

1) You're looping through all the units, and modifying their fly height without any check (you don't check if d.swayer == whichUnit) therefore, all instances will be messed up

2) You're decreasing N, for every iteration of the loop. N is only meant to decrease when an instance ends, never anytime else (because this is your instance counter)

3) You're destroying the struct regardless of whether it's the right one or not

4) As it is, the function is inefficient since you are looping through X units, and you're only ever going to do actions for one of those units. You could index the system i.e. return the struct's value (as an integer, not as the struct's type), then you can do
JASS:
function StopUnitSway takes integer index returns nothing
  local SwayData d = SwayData (index) //Not sure if the cast to &lt;struct type&gt; is required, but I recall seeing Vexorian say something about it
if d != 0 then //Not sure if this will work to prevent people from passing non-existant indexes and breaking the system, but it&#039;s worth a shot
  call SetUnitFlyHeight (d.swayer, height, 0)
  set N = N - 1
  if N == 0 then
    call PauseTimer (T)
  endif
  call d.destroy ()
endif
//I may have forgotten some stuff <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" class="smilie smilie--sprite smilie--sprite7" alt=":p" title="Stick Out Tongue    :p" loading="lazy" data-shortname=":p" />
endfunction


Is all the variables (currentTime, totalTime, swayHeight) struct data? And should they just be initialized as 0?
currentTime? No, it shouldn't need to be
totalTime? No, it's constant (1)
swayHeight? Depends - do you have the max/min height stored within the struct? If so, then you can calculate swayHeight each time the timer executes. Otherwise, pre-calculate swayHeight and store it in the struct
 

AceHart

Your Friendly Neighborhood Admin
Reaction score
1,495
> That'd give you a syntax error

Or, maybe not.


> Hover.

Hover?
A 200+ lines script that makes a unit hover?
With two threads on the same subject, and the thing is most likely still not working?

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