Snippet Wispwheel

XeNiM666

I lurk for pizza
Reaction score
138
Wispwheel
by XeNiM666

First of all, what's a wispwheel?
A Wispwheel is a unit that's spinning on another unit / location. I created this snippet to make Wispwheel-ing easier. :)

Version: 1.1
MUI/MPI: Yes
Leakless: Yes
Lagless: When spammed, Yes.
Code: vJASS
Requires: TT

Documentation:
JASS:
//*******************************************************************************//
//                             WISPWHEEL BY XeNiM666                             //
//*******************************************************************************//
//                                    REQUIRES                                   //
//*******************************************************************************//
//                                                                               //
//   1. A vJASS preprocessor ( Jass NewGen Pack )                                //
//   2. The TT ( Timer Ticker System ) by Cohadar                                //
//                                                                               //
//*******************************************************************************//
//                                  HOW TO IMPORT                                //
//*******************************************************************************//
//                                                                               //
//   1. Create a trigger and name it Wispwheel or whatever.                      //
//   2. Copy the TT Trigger and the UsedFuncs Library.                           //
//   3. Select all the text in this trigger and copy it into your pre-created    //
//      trigger.                                                                 //
//                                                                               //
//*******************************************************************************//
//                                   HOW TO USE                                  //
//*******************************************************************************//
//                                                                               //
//   call WispwheelUnit( spinner, center, direction, duration, angle, distance, rate, effect )
//   call WispwheelPoint( spinner, center_x, center_y, direction, duration, angle, distance, rate, effect )
//                                                                               //
//   Spinner - the spinner is the unit being spinned. In other words, its the    //
//             unit being rotated around anothier unit.                          //
//   Center - is the center 'UNIT' where the "spinner" revolves around.          //
//   Center_X - is the center x-coordinate of a point.                           //
//   Center_Y - is the center y-coordinate of a point.                           //
//   Direction - is the direction where the spinner will be spinning.            //
//   Duration - its how long the spinner will be spinning.                       //
//   Angle - is the starting angle where the spinner will start spinning. 90.00  //
//           being north and 270.00 being south                                  //
//   Rate - its the speed of the spinner by Angle/Second. Meaning if you put     //
//          90.00 then it will spin 90.00 degrees per second.                    //
//   Effect - it is the effect created when the unit is spinning.                //
//                                                                               //
//*******************************************************************************//

How to use: ( Explained above. )
JASS:
call Wispwheel( spinner, center, direction, duration, angle, distance, rate, effect )
call WispwheelPoint( spinner, center_x, center_y, direction, duration, angle, distance, rate, effect )


Requires:
JASS:
//==============================================================================
//  TT -- TIMER TICKER SYSTEM BY COHADAR -- v3.4
//==============================================================================
//
//  PURPOUSE OF TT:
//       * Passing data to timers
//       * using only one timer for all actions
//
//  PROS:
//       * It is ridiculously easy to use.
//       * It is faster than ABC (and any other attaching system)
//
//  CONS:
//       * It can be used only for high-frequency timers
//         This method fails if PERIOD > 0.1 second
//
//  FUNCTIONS:
//       * TT_Start(userFunc, struct)
//         TT_GetData() -> struct
//
//       * userFunc is a user function that takes nothing and return boolean
//         it will be periodically called by the system until it returns true.
//
//       * TT_GetData() is a function that can be used inside userFunc
//         TT_GetData() will return struct passed to Start function
//
//  DETAILS:
//       * All user functions are stored in an array.
//         Timer will call all those functions each period.
//
//       * While user function returns false timer will continue to call it each period
//         Once user function returns true it will be removed from system
//
//  REQUIREMENTS:
//       * NewGen v4c and above (there might be some problems with older NewGen's)
//
//  THANKS TO:
//       * Vexorian - he was nagging me so much about how attaching to timers is bad
//         that I finally had to do something about it.
//
//  HOW TO IMPORT:
//       * Just create a trigger named TT
//       * convert it to text and replace the whole trigger text with this one
//
//==============================================================================
library TT initializer Init

globals
    // List of recommended periods:
    // 0.04    = 25 calls per second
    // 0.03125 = 32 calls per second
    // 0.025   = 40 calls per second
    // 0.02    = 50 calls per second
    public constant real PERIOD = 0.02
    
    // One Timer to rule them all, One Timer to find them,
    // One Timer to call them all and in the jass bind them
    // In the land of warcraft where the desyncs lie.
    private timer   Timer = CreateTimer()
    
    private integer Data
    private integer Counter = 0
    private trigger array Triggz
    private integer array Dataz
endglobals

//==============================================================================
private function Handler takes nothing returns nothing
    local trigger swap
    local integer i = Counter
    loop
        exitwhen i<=0
        set Data = Dataz<i>
        if TriggerEvaluate(Triggz<i>) then
            set swap = Triggz<i>
            call TriggerClearConditions(swap)
            set Triggz<i> = Triggz[Counter]
            set Triggz[Counter] = swap
            set Dataz<i> = Dataz[Counter]
            set Counter = Counter - 1
        endif
        set i = i - 1
    endloop
    // who can guess why am I not nulling swap here?
endfunction

//==============================================================================
public function Start takes code userFunc, integer data returns nothing
    debug if userFunc == null then
    debug    call BJDebugMsg(&quot;ERROR: TT_Start - null userFunc&quot;)
    debug    return
    debug endif

    set Counter = Counter + 1    
    
    if Triggz[Counter] == null then
        set Triggz[Counter] = CreateTrigger()
    endif
    
    call TriggerAddCondition(Triggz[Counter], Condition(userFunc))
    set Dataz[Counter] = data
endfunction

//==============================================================================
//  Call this function only inside the userFunc you passed to Start
//==============================================================================
public function GetData takes nothing returns integer
    return Data
endfunction

//==============================================================================
private function Init takes nothing returns nothing
    call TimerStart(Timer, PERIOD, true, function Handler)  
endfunction

endlibrary

//==============================================================================
//  END OF TIMER TICKER SYSTEM
//==============================================================================


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


Changelog: Version 1.1

- Fixed the * 0.02 thing.
- Removed UsedFuncs as a requirement and copied the needed functions inside the Wispwheel library.
- Fixed when duration is not a multiple of 0.02
- Created a point version of the Wispwheel.
- Optimized a very little bit.

Code:
JASS:
library Wispwheel initializer Init

    globals
        public real MaxX
        public real MaxY
        public real MinX
        public real MinY

        // Timer interval / PERIOD value of the TT_System //
        private constant real INTERVAL = 0.02
        
        // Ghost Raw Id for anti collision //
        private constant integer GHOST_ID = &#039;Aeth&#039;
    endglobals
    
    // Functions by Used Funcs //
    
    private function SetSafeX takes unit which, real x returns nothing
        if x &lt; MaxX then
            if x &gt; MinX then
                call SetUnitX(which, x)
            else
                call SetUnitX(which,MinX)
            endif
        else
            call SetUnitX(which, MaxX)
        endif
    endfunction
    

    private function SetSafeY takes unit which, real y returns nothing
        if y &lt; MaxY then
            if y &gt; MinY then
                call SetUnitY(which,y)
            else
                call SetUnitY(which,MinY)
            endif
        else
            call SetUnitY(which, MaxY)
        endif
    endfunction
            
    private struct WheelUnit
        unit u
        unit c
        real cx
        real cy
        string dir
        real dur
        real dis
        real rate
        string fx
        
        real r
        real d
        
        // Wispwheeling on a unit //
        
        method SpinUnit takes unit spinner, unit center, string direction, real duration, real angle, real distance, real rate, string fx returns nothing
            set .u = spinner
            set .c = center
            set .cx = GetUnitX( .c )
            set .cy = GetUnitY( .c )
            set .dir = direction
            set .dur = duration
            set .r = angle
            set .dis = distance
            set .rate = rate
            set .fx = fx
            call UnitAddAbility( .u, GHOST_ID )
            call TT_Start( function WheelUnit.UnitMove, this )
        endmethod
        
        static method UnitMove takes nothing returns boolean
            local WheelUnit wheel = TT_GetData()
            
            local real nx
            local real ny
            
            local real r = wheel.rate * INTERVAL
            
            local effect e = null
            local boolean flag = false
            
            local real a
            
            if wheel.dir == &quot;left&quot; then
                set a = 1.00
            elseif wheel.dir == &quot;right&quot; then
                set a = -1.00
            else
                set a = 1.00
            endif
            
            set wheel.cx = GetUnitX( wheel.c )
            set wheel.cy = GetUnitY( wheel.c )
            
            // Moving the spinner
            
            set wheel.d = wheel.d + INTERVAL
            set wheel.r = wheel.r + ( r * a )
            
            set nx = wheel.cx + wheel.dis * Cos( wheel.r * bj_DEGTORAD )
            set ny = wheel.cy + wheel.dis * Sin( wheel.r * bj_DEGTORAD )
                
            call SetSafeX( wheel.u, nx )
            call SetSafeY( wheel.u, ny )
            
            call SetUnitFacing( wheel.u, wheel.r + ( 90.00 * a ) )
            
            set e = AddSpecialEffect( wheel.fx, nx, ny )
            call DestroyEffect( e )
            
            set e = null
            
            if wheel.d &gt; wheel.dur then
                set flag = true
                call wheel.destroy()
            endif
            
            return flag
        endmethod
        
        method onDestroy takes nothing returns nothing
            call UnitRemoveAbility( .u, GHOST_ID )
            set .u = null
            set .c = null
        endmethod

    endstruct
    
    private struct WheelPoint
        unit u
        real cx
        real cy
        string dir
        real dur
        real dis
        real rate
        string fx
        
        real r
        real d
        
        // Wispwheeling on a point //
        
        method SpinPoint takes unit spinner, real center_x, real center_y, string direction, real duration, real angle, real distance, real rate, string fx returns nothing
            set .u = spinner
            set .cx = center_x
            set .cy = center_y
            set .dir = direction
            set .dur = duration
            set .r = angle
            set .dis = distance
            set .rate = rate
            set .fx = fx
            call UnitAddAbility( .u, GHOST_ID )
            call TT_Start( function WheelPoint.PointMove, this )
        endmethod
        
        static method PointMove takes nothing returns boolean
            local WheelPoint wheel = TT_GetData()
            
            local real nx
            local real ny
            
            local real r = wheel.rate * INTERVAL
            
            local effect e = null
            local boolean flag = false
            
            local real a
            
            if wheel.dir == &quot;left&quot; then
                set a = 1.00
            elseif wheel.dir == &quot;right&quot; then
                set a = -1.00
            else
                set a = 1.00
            endif
            
            // Moving the spinner
            
            set wheel.d = wheel.d + INTERVAL
            set wheel.r = wheel.r + ( r * a )
            
            set nx = wheel.cx + wheel.dis * Cos( wheel.r * bj_DEGTORAD )
            set ny = wheel.cy + wheel.dis * Sin( wheel.r * bj_DEGTORAD )
                
            call SetSafeX( wheel.u, nx )
            call SetSafeY( wheel.u, ny )
            
            call SetUnitFacing( wheel.u, wheel.r + ( 90.00 * a ) )
            
            set e = AddSpecialEffect( wheel.fx, nx, ny )
            call DestroyEffect( e )
            
            set e = null
            
            if wheel.d &gt; wheel.dur then
                set flag = true
                call wheel.destroy()
            endif
            
            return flag
        endmethod
        
        method onDestroy takes nothing returns nothing
            call UnitRemoveAbility( .u, GHOST_ID )
            set .u = null
        endmethod

    endstruct

    function WispwheelUnit takes unit spinner, unit center, string direction, real duration, real angle, real distance, real rate, string fx returns nothing
        call WheelUnit.create().SpinUnit( spinner, center, direction, duration, angle, distance, rate, fx )
    endfunction
        
    function WispwheelPoint takes unit spinner, real center_x, real center_y, string direction, real duration, real angle, real distance, real rate, string fx returns nothing
        call WheelPoint.create().SpinPoint( spinner, center_x, center_y, direction, duration, angle, distance, rate, fx )
    endfunction
    
    private function Init takes nothing returns nothing
        set MaxX = GetRectMaxX(bj_mapInitialPlayableArea)
        set MaxY = GetRectMaxY(bj_mapInitialPlayableArea)
        set MinX = GetRectMinX(bj_mapInitialPlayableArea)
        set MinY = GetRectMinY(bj_mapInitialPlayableArea)
    endfunction
            
endlibrary

Enjoy!
 

Trollvottel

never aging title
Reaction score
262
JASS:
local real r = wheel.rate * 0.02

why 0.02?

please use more destriptive variable names then dur, dir or dis. it makes your code easier to understand.

and i see you only using SetSafeX/Y in your code so i think it isnt really necessary to import a whole library (i think the only other library that uses the UsedFuncs library is my PudgeWars meathook). Just import the 2 functions into your library and make them private.

JASS:
call Wispwheel( spinner, center, direction, duration, angle, distance, rate, effect )


you dont really get to know which of types the arguments are.

direction for example is a string, i would have guessed it would be and int 1 or -1.


and this is not really configurable. what if i want it to deal damage to units which come to close or if i want it to kill them.


JASS:
if wheel.d == wheel.dur then
                set flag = true
                call wheel.destroy()
            endif


so if the duration is not a multiple of 0.02 the function will never stop?
 

Romek

Super Moderator
Reaction score
963
You could make this system independent. So it doesn't rely on UselessFuncs and TT.
Useless Funcs is a useless library with some really basic functions. I think you should just put the needed ones into your script. Same applies to all your systems.

And you could make this run on a single timer instead of it requiring TT.

Also, what if I want the wheel to do damage? I can't do that with this.
And what if I don't want a unit to be at the center?
I think you should make an X/Y coordinates version. It should be quite easy anyway.
 

Trollvottel

never aging title
Reaction score
262
Very much maps use TT and if you use 1 timer instead of TT, you will have 1 timer each system. also UsedFuncs isnt useless if you have a big code with many sequences which repeat. it makes them easier to overlook and better organized. For this system it is useless.
 

XeNiM666

I lurk for pizza
Reaction score
138
UPDATED: Version 1.1

why 0.02?
because its the Period variable in the TT system. <-- Fixed
so i think it isnt really necessary to import a whole library
Fixed
what if i want it to deal damage to units which come to close or if i want it to kill them.
this snippet is only used to make wispwheels. to do that you can do Trigger - Add Event/Condition/Action.
so if the duration is not a multiple of 0.02 the function will never stop?
thanks for that!! :D <-- Fixed
And what if I don't want a unit to be at the center?
I think you should make an X/Y coordinates version. It should be quite easy anyway.
Finished!

P.S.
Is it ok if i use 2 structs?
 

XeNiM666

I lurk for pizza
Reaction score
138
I hope you realize that TT's Period is public.
Yes. but for some reason when i put the global PERIOD into the snippet it keeps saying: Undeclared variable PERIOD
 

Romek

Super Moderator
Reaction score
963
The "How to use" isn't really helpful at the moment.
Maybe instead of just this:
JASS:
call Wispwheel( spinner, center, direction, duration, angle, distance, rate, effect )
call WispwheelPoint( spinner, center_x, center_y, direction, duration, angle, distance, rate, effect )


You could put the type of the arguments.
JASS:
function WispwheelUnit takes unit spinner, unit center, string direction, real duration, real angle, real distance, real rate, string fx returns nothing
// And the other function


"direction" could also be made a bit more clear.
I had to look into the code to see what it did.

You could explain that you need "left" or "right". Or you could change those to "clockwise" and "anticlockwise", as left and right is a bit confusing.
Or, you could remove that altogether, and simply make it spin clockwise by default, and anticlockwise if [whichever varabale controls the increment] is negative.
 
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