Snippet MakeUnitSway

Vestras

Retired
Reaction score
249
Yeah, I solved it.
This is a pretty simple function(s), making the unit sway. The swaying isn't very smooth, I hope you don't mind.

JASS:
library MakeUnitSway

private keyword Data

globals
    private constant integer ENABLE_FLY='Amrf'
    // The Raven Form ability which enables flying
    private constant real INTERVAL=0.03
    // The timer interval. 0.03 is suggested, less can cause lag
    private constant real DIVIDE=100
    // d.z is divided with this
    private constant real RATE=5000
    // The "time" the unit is about getting from and to the ground/fly height
// Necessary globals
private Data array D
private integer N=0
private timer T=CreateTimer()
endglobals

//! WARNING WARNING WARNING WARNING WARNING WARNING WARNING
//! Real Snippet Code! 
//! Don't touch if you don't know what you are doing!
//! WARNING WARNING WARNING WARNING WARNING WARNING WARNING

private struct Data
    unit swayer
    real z
    real max
    real min
    real height
    boolean hasReachedMax
endstruct

private function Callback takes nothing returns nothing
    local Data d
    local integer i=N
    loop
        exitwhen i<=0
        set d=D<i>
            if (d.z&lt;d.min) then
                set d.z=(d.z+(d.z/DIVIDE))
                call SetUnitFlyHeight(d.swayer,d.z,0)
                set d.hasReachedMax=false
            elseif (d.z&gt;d.max) then
                set d.z=(d.z-(d.z/DIVIDE))
                call SetUnitFlyHeight(d.swayer,d.z,0)
                set d.hasReachedMax=true
            elseif (d.z&gt;d.min and d.hasReachedMax==false) then
                set d.z=(d.z+(d.z/DIVIDE))
                call SetUnitFlyHeight(d.swayer,d.z,0)
            elseif (d.z&gt;d.min) and (d.hasReachedMax==true) then
                set d.z=(d.z-(d.z/DIVIDE))
                call SetUnitFlyHeight(d.swayer,d.z,0)
            endif
        set i=i-1
    endloop
endfunction

function MakeUnitSway takes unit whichUnit, real max, real min returns nothing
    local Data d=Data.create()
    set d.swayer=whichUnit
    set d.height=GetUnitFlyHeight(whichUnit)
    call UnitAddAbility(whichUnit,ENABLE_FLY)
    call SetUnitFlyHeight(whichUnit,min,RATE)
    set d.z=min-1
    call UnitRemoveAbility(whichUnit,ENABLE_FLY)
    set d.max=max
    set d.min=min
    set d.hasReachedMax=false
    set N=N+1
    set D[N]=d
    if N==1 then
        call TimerStart(T,INTERVAL,true,function Callback)
    endif
endfunction

function StopUnitSway takes unit whichUnit returns nothing
    local Data d
    local integer i=N
    loop
        exitwhen i&lt;=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
endfunction

private function TimedCallback takes nothing returns nothing
    local Data d
    local integer i=N
    loop
        exitwhen i&lt;=0
        set d=D<i>
        call StopUnitSway(d.swayer)
        set D<i>=D[N]
        set N=N-1
        set i=i-1
    endloop
    call DestroyTimer(GetExpiredTimer())
endfunction

function MakeUnitSwayTimed takes unit whichUnit, real max, real min, real duration returns nothing
    local Data d=Data.create()
    set d.swayer=whichUnit
    set N=N+1
    set D[N]=d
        call MakeUnitSway(whichUnit,max,min)
        call TimerStart(CreateTimer(),duration,false,function TimedCallback)
endfunction

endlibrary</i></i></i></i></i>
 

saw792

Is known to say things. That is all.
Reaction score
280
Wouldn't mind seeing some screenies of this before I try it out myself.
 

Larcenist

REP: Respect, Envy, Prosperity?
Reaction score
211
Haven't tried it nor will do anytime soon, mostly because I'm lazy. A few things I
noticed by quickly going through the code:

1) Try to make it not require any specific attachment systems.

2) Make so that it uses a global timer instead of one for each instance.

3)

JASS:
    private constant real TIME=5000


How about making that into seconds instead? And what if someone would want a different one for different spells or anything?
 

Vestras

Retired
Reaction score
249
@ Saw:

Hmm, there isn't really anything to get screenies of.

@ Larcenist

1) How? Should I make it into a struct?
2) That would make it non-MUI.
3) Actually, it isn't time, it's the rate of the SetUnitFlyHeight(...) function.
 

saw792

Is known to say things. That is all.
Reaction score
280
2) Global timers allow spells to be MUI if used correctly. I'll let somebody else explain it since I'm not that great at it.

Anyway, I think I misunderstood what this is supposed to do. Define 'swaying'.
 

Vestras

Retired
Reaction score
249
Hmm... I mean that it goes from one point in the air to another, like increase height, decrease, increase, decrease and so on...
 

Larcenist

REP: Respect, Envy, Prosperity?
Reaction score
211
2) Global timers allow spells to be MUI if used correctly. I'll let somebody else explain it since I'm not that great at it.

Anyway, I think I misunderstood what this is supposed to do. Define 'swaying'.

JASS:
private keyword Data

globals
    private timer T = CreateTimer()
    private integer N = 0
    private Data array D
endglobals

...
...

private function StopUnitSway takes ...
    local integer i = N
    local Data d
    ...
    ...
    loop
        exitwhen i &lt;= 0
            set d = Data<i>
            //Do stuff
            if (Whatever you use to destroy) == true then
                call SetUnitFlyHeight(d.swayer,d.height,TIME)
                call d.destroy()
                set D<i> = D[N]
                set N = N - 1
                if N == 0 then
                    call PauseTimer(T)
                endif
            endif
        set i = i - 1
    endloop
endfunction

function MakeUnitSway takes ...
    local Data d = ...
    ....
    set N = N + 1
    if N == 1 then
        call TimerStart(T, ...)
        set D[N] = d
    endif
endfunction</i></i>


You get the idea. Might be errors since it rapidly freehanded.

3) Actually, it isn't time, it's the rate of the SetUnitFlyHeight(...) function.

I'm not stupid... What I said is that you should make it so that the user can declare this in seconds, rather than rate.
 

Vestras

Retired
Reaction score
249
Okay... I thought I got it, but no...
It doesn't get the data, it doesn't do anything.

JASS:
library MakeUnitSway

private keyword Data

globals
    private constant integer ENABLE_FLY=&#039;Amrf&#039;
    // The Raven Form ability which enables flying
    private constant real INTERVAL=0.03
    // The timer interval. 0.03 is suggested, less can cause lag
    private constant real DIVIDE=100
    // d.z is divided with this
    private constant real TIME=5000
    // The &quot;time&quot; the unit is about getting from and to the ground/fly height
// Necessary globals
private Data array D
private integer N
private timer T=CreateTimer()
endglobals

//! WARNING WARNING WARNING WARNING WARNING WARNING WARNING
//! Real Snippet Code! 
//! Don&#039;t touch if you don&#039;t know what you are doing!
//! WARNING WARNING WARNING WARNING WARNING WARNING WARNING

private struct Data
    unit swayer
    real z
    real max
    real min
    real height
    boolean hasReachedMax
endstruct

private function Callback takes nothing returns nothing
    local Data d
    local integer i=N
    loop
        exitwhen i&lt;=0
        set d=D<i>
        call UnitAddAbility(d.swayer,ENABLE_FLY)
            if (d.z&lt;d.min) then
                set d.z=(d.z+(d.z/DIVIDE))
                call SetUnitFlyHeight(d.swayer,d.z,0)
                set d.hasReachedMax=false
            elseif (d.z&gt;d.max) then
                set d.z=(d.z-(d.z/DIVIDE))
                call SetUnitFlyHeight(d.swayer,d.z,0)
                set d.hasReachedMax=true
            elseif (d.z&gt;d.min and d.hasReachedMax==false) then
                set d.z=(d.z+(d.z/DIVIDE))
                call SetUnitFlyHeight(d.swayer,d.z,0)
            elseif (d.z&gt;d.min) and (d.hasReachedMax==true) then
                set d.z=(d.z-(d.z/DIVIDE))
                call SetUnitFlyHeight(d.swayer,d.z,0)
            endif
        set D<i>=D[N]
        set N=N-1
        call UnitRemoveAbility(d.swayer,ENABLE_FLY)
        set i=i-1
    endloop
endfunction

function MakeUnitSway takes unit whichUnit, real max, real min returns nothing
    local Data d=Data.create()
    set d.swayer=whichUnit
    set d.height=GetUnitFlyHeight(whichUnit)
    call UnitAddAbility(whichUnit,ENABLE_FLY)
    call SetUnitFlyHeight(whichUnit,min,TIME)
    set d.z=min-1
    call UnitRemoveAbility(whichUnit,ENABLE_FLY)
    set d.max=max
    set d.min=min
    set d.hasReachedMax=false
    set N=N+1
    if N==1 then
        set D[N]=d
        call TimerStart(T,INTERVAL,true,function Callback)
    endif
endfunction

function StopUnitSway takes unit whichUnit returns nothing
    local Data d
    local integer i=N
    loop
        exitwhen i&lt;=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,TIME)
        call d.destroy()
        set i=i-1
    endloop
endfunction

private function TimedCallback takes nothing returns nothing
    local Data d
    local integer i=N
    loop
        exitwhen i&lt;=0
        set d=D<i>
        call StopUnitSway(d.swayer)
        set D<i>=D[N]
        set N=N-1
        set i=i-1
    endloop
    call DestroyTimer(GetExpiredTimer())
endfunction

function MakeUnitSwayTimed takes unit whichUnit, real max, real min, real duration returns nothing
    local Data d=Data.create()
    set d.swayer=whichUnit
    set N=N+1
    set D[N]=d
        call MakeUnitSway(whichUnit,max,min)
        call TimerStart(CreateTimer(),duration,false,function TimedCallback)
endfunction

endlibrary</i></i></i></i></i></i>
 

Flare

Stops copies me!
Reaction score
662
JASS:
    if N==1 then
        set D[N]=d

Set D[N] outside of the if (otherwise the data will only be set when an instance occurs when no other instance is running) - shame on Larcenist for having made that mistake :p

And you haven't initialized N (sadly you can't increment an uninitialized variable)

JASS:
private function Callback takes nothing returns nothing
    local Data d
    local integer i=N
    loop
        exitwhen i&lt;=0
        set d=D<i>
        call UnitAddAbility(d.swayer,ENABLE_FLY)
            if (d.z&lt;d.min) then
                set d.z=(d.z+(d.z/DIVIDE))
                call SetUnitFlyHeight(d.swayer,d.z,0)
                set d.hasReachedMax=false
            elseif (d.z&gt;d.max) then
                set d.z=(d.z-(d.z/DIVIDE))
                call SetUnitFlyHeight(d.swayer,d.z,0)
                set d.hasReachedMax=true
            elseif (d.z&gt;d.min and d.hasReachedMax==false) then
                set d.z=(d.z+(d.z/DIVIDE))
                call SetUnitFlyHeight(d.swayer,d.z,0)
            elseif (d.z&gt;d.min) and (d.hasReachedMax==true) then
                set d.z=(d.z-(d.z/DIVIDE))
                call SetUnitFlyHeight(d.swayer,d.z,0)
            endif
        set D<i>=D[N]
        set N=N-1
        call UnitRemoveAbility(d.swayer,ENABLE_FLY)
        set i=i-1
    endloop
endfunction</i></i>

Read through the callback function from Larcenist's code - you're not supposed to decrease N, unless you are removing an instance (whereas you're decreasing it as if it were a loop counter)

[del]And, when you decrease N by 1, i should be increased by 1 (otherwise you are skipping the top-most instance which was moved down to the empty slot for that timer execution)[/del]
Oops, forgot that you were counted down (the single decrease to i is only needed when counting up)

JASS:
function StopUnitSway takes unit whichUnit returns nothing
    local Data d
    local integer i=N
    loop
        exitwhen i&lt;=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,TIME)
        call d.destroy()
        set i=i-1
    endloop</i></i>

Do you even realise what you're doing there? It's far from what's intended, just by looking at it :rolleyes:

And there's no real need for 'Amrf' to be a constant, since every map should have that (if it doesn't...), and there wouldn't be any need for people to choose Amrf over Arav (since they're both gonna do the same thing)
 

Larcenist

REP: Respect, Envy, Prosperity?
Reaction score
211
And, when you decrease N by 1, i should be increased by 1 (otherwise you are skipping the top-most instance which was moved down to the empty slot for that timer execution)

Lies, not when running i backwards.

@Vestras: Check through my code (except my noob-mistake with the D[N] declaring ^^), you didn't even do half of what I really did.
 

Flare

Stops copies me!
Reaction score
662
Lies, not when running i backwards.

@Vestras: Check through my code (except my noob-mistake with the D[N] declaring ^^), you didn't even do half of what I really did.
Ye, I [noparse][del][/del][/noparse]'ed it there :p

JASS:
    if d.swayer==null then
        call BJDebugMsg(&quot;|cffff0000MakeUnitSway|r: invalid unit.&quot;)
// !!!
        return
    endif

From what I know, an empty return (not sure what exactly to call it) can cause desyncs on a Mac - make the function return an integer or something, and return 0 at all times, which would solve that problem
 

Joker(Div)

Always Here..
Reaction score
86
From what I know, an empty return (not sure what exactly to call it) can cause desyncs on a Mac - make the function return an integer or something, and return 0 at all times, which would solve that problem
Where you hear this?
 

Darthfett

Aerospace/Cybersecurity Software Engineer
Reaction score
615
Flare said:
From what I know, an empty return (not sure what exactly to call it) can cause desyncs on a Mac - make the function return an integer or something, and return 0 at all times, which would solve that problem

Considering Skip Remaining Actions does exactly this, I really doubt this.

Isn't this what your function is doing, Vestras?

systemkj6.jpg


You do realize this can be done by using the SetUnitFlyHeight using the Min/Max values, and a given time, right?

This system isn't much use without making the edges more rounded. It is already set up to do so, just needs a little bit of math.
 

Darius34

New Member
Reaction score
30
It's not an empty return that causes desyncs - it's a non-existent one.

JASS:
function foo takes nothing returns boolean
    call BJDebugMsg(&quot;Blah&quot;)
endfunction

Something like this.

You do realize this can be done by using the SetUnitFlyHeight using the Min/Max values, and a given time, right?
QFT.

The arguments: switch min and max? Somehow seems more intuitive that way.
 

AceHart

Your Friendly Neighborhood Admin
Reaction score
1,495
> Where you hear this?

Returning nothing in a condition function can do bad things. A Mac exclusive.


Anyone care to explain what "swaying units" actually is?
 

quraji

zap
Reaction score
144
If Darthfett's diagram represents your snippet, I think this is a better alternative:

JASS:
library unitbob

globals
    constant integer FlyID = &#039;Amrf&#039;
    private gamecache gc = InitGameCache(&quot;unitbob&quot;)
endglobals

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

struct unitbob
    unit u
    real offset
    real rate
    real origz
    timer t
    
    static method callback takes nothing returns nothing
        local timer t = GetExpiredTimer()
        local unitbob ub = unitbob(GetStoredInteger(gc, I2S(H2I(t)), &quot;ub&quot;))
        
        call SetUnitFlyHeight(ub.u, GetUnitFlyHeight(ub.u) + ub.offset, ub.rate)
        set ub.offset = -ub.offset
    endmethod

    static method create takes unit u returns unitbob
        local unitbob ub = unitbob.allocate()
        
        set ub.u = u
        set ub.origz = GetUnitFlyHeight(u)
        set ub.t = CreateTimer()
        call UnitAddAbility(u, FlyID)
        call UnitRemoveAbility(u, FlyID)
      
        return ub
    endmethod
    
    method stop takes nothing returns nothing
        call PauseTimer(.t)
        call SetUnitFlyHeight(.u, .origz, 0.)
    endmethod
    
    method start takes real offset, real rate returns nothing
        set .offset = offset
        set .rate = rate
        
        call StoreInteger(gc, I2S(H2I(.t)), &quot;ub&quot;, this)
        call PauseTimer(.t)
        call TimerStart(.t, .offset/.rate, true, function unitbob.callback) 
        call SetUnitFlyHeight(.u, GetUnitFlyHeight(.u) + .offset, .rate)
        set .offset = -.offset 
    endmethod 
endstruct

endlibrary


I just wrote it here then made sure it compiled and bobbed the unit, I didn't test it much. Just bobs the unit up and down without "sliding" it (periodically changing FlyHeight - it lets the native do that), and requires no attachment system. The struct can easily be made a member of a data struct for PUI or whatever.

If you like this alternative better, feel free to take it and add/change what you like. I just thought it was a shame to make this more complicated than it is, seeing as Blizz has a native for it ;)
 

Flare

Stops copies me!
Reaction score
662
Where you hear this?

Considering Skip Remaining Actions does exactly this, I really doubt this.
Can't remember where exactly I saw it, but I definitely remember seeing someone saying it (I think it was emjlr3, not 100% sure though)

It's not an empty return that causes desyncs - it's a non-existent one.

JASS:
function foo takes nothing returns boolean
    call BJDebugMsg(&quot;Blah&quot;)
endfunction
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 >_<)
 

Vestras

Retired
Reaction score
249
Updated.
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?

The snippet doesn't use any systems!
 
General chit-chat
Help Users
  • No one is chatting at the moment.
  • 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
    +2
  • V-SNES V-SNES:
    Happy Friday!
    +1
  • The Helper The Helper:
    New recipe is another summer dessert Berry and Peach Cheesecake - https://www.thehelper.net/threads/recipe-berry-and-peach-cheesecake.194169/
  • The Helper The Helper:
    I think we need to add something to the bottom of the front page that shows the Headline News forum that has a link to go to the News Forum Index so people can see there is more news. Do you guys see what I am saying, lets say you read all the articles on the front page and you get to the end and it just ends, no kind of link for MOAR!
  • The Helper The Helper:
    Happy Wednesday!
    +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