• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

[vJASS] [Snippet] KnockbackTools

Level 9
Joined
Jun 21, 2012
Messages
431
Well another knockback system, I hope can be useful for someone :ogre_rage:

JASS:
library KnockbackTools uses Optimizer32, Event, DestructableLib, AutoFly
/*****************************************************************************
*
*   KnockbackTools
*   _______________
*   v1.1.1.1
*   by Thelordmarshall
*   
*   Well another fucking Knockback system...
*
*   Pros:
*   _____
*   You can:
*       - Use slide speed or not.
*       - Use fly on launch targets.
*       - Create functions for loop/stop events.
*       - And more....
*
*   API:
*   ____
*   struct Knockback extends array:
*       - method launch takes real angle, real distance returns nothing
*           - Launch the target.
*   method operator:
*       - useSlideSpeed (boolean)
*       - speed (real)
*       - timerSpeed (real)
*       - arc (real)
*       - fx (string)
*       - pathing (boolean)
*       - pause (boolean)
*       - fly (boolean)
*       - hitTrees (boolean)
*   
*   Functions:
*   __________
*       - function Parabola takes real arc, real d, real x returns real
*       - function ParabolicMovement takes real h, real d, real x returns real
*
*   Credits:
*   ________
*       - Nestharus: Event.
*       - PitzerMike: DestructableLib.
*       - moyackx: Parabolic formulas.
*
*   Copyright © 2015.
*****************************************************************************/

    //CONFIGURATION
    globals
        private constant real ARC_LIMIT = 1.
        private constant real RATIO     = 200.
    endglobals
    //ENDCONFIGURATION
    
    function Parabola takes real arc, real d, real x returns real
        return (4*arc)*(d-x)*(x/d)
    endfunction

    function ParabolicMovement takes real h, real d, real x returns real
        local real a=-4*h/(d*d)
        local real b=4*h/d
        return a*x*x+b*x
    endfunction

    struct Knockback extends array
        readonly static Event EVENT_LOOP
        readonly static Event EVENT_STOP
        private static integer more=0
        private static integer array list
        static integer instanceData=0
        static unit lastStopedUnit=null
        static unit loopUnit=null
        private static rect treesRect=null
        private unit u
        private real d1
        private real d2
        private real sin
        private real cos
        private real x
        private real y
        private unit kb_targetUnit
        private real kb_distance
        private real kb_speed
        private real kb_timerSpeed
        private real kb_arc
        private integer kb_data
        private string kb_fx
        private boolean kb_collision
        private boolean kb_pause
        private boolean kb_slideSpeed
        private boolean kb_hitTrees
        private Timer32 t32
        
        private static method destroyDelay takes nothing returns nothing
            local thistype this=Timer32.getData()
            set list[this]=list[0]
            set list[0]=this
            if .u!=null then
            set lastStopedUnit=.u
            set instanceData=.kb_data
            call FireEvent(Knockback.EVENT_STOP)
            set lastStopedUnit=null
            if .kb_pause then
                call PauseUnit(.u,false)
            endif
            if not .kb_collision then
                call SetUnitPathing(.u,true)
            endif
            if .kb_arc>0. then
                call SetUnitFlyHeight(.u,GetUnitDefaultFlyHeight(.u),0.)
            endif
            set .u=null
            endif
            set .kb_targetUnit=null
        endmethod
        
        method manualDestroy takes nothing returns nothing
            call Timer32.start(this,.02,function thistype.destroyDelay)
        endmethod
        
        private static method killTrees takes nothing returns nothing
            local destructable d=GetEnumDestructable()
            if not IsDestructableDead(d) and IsDestructableTree(d) then
                call KillDestructable(d)
            endif
            set d=null
        endmethod
        
        private static method onLoop takes nothing returns nothing
            local thistype this=Timer32.getData()
            local real x=GetUnitX(.u)
            local real y=GetUnitY(.u)
            local real x2
            local real y2
            local real a
            local real d
            if GetUnitTypeId(.u)!=0 then
                set loopUnit=.u
                call FireEvent(Knockback.EVENT_LOOP)
                set loopUnit=null
                if .kb_pause and not IsUnitPaused(.u) then
                    call PauseUnit(.u,true)
                endif
                if .kb_targetUnit!=null then
                    set x2=GetUnitX(.kb_targetUnit)
                    set y2=GetUnitY(.kb_targetUnit)
                    set a=Atan2(y2-y,x2-x)
                    set .cos=Cos(a)
                    set .sin=Sin(a)
                    set .kb_distance=SquareRoot(Pow(x2-.x,2)+Pow(y2-.y,2))
                endif
                if .kb_slideSpeed then
                    set x=x+.d1*.cos
                    set y=y+.d1*.sin
                    set .d1=.d1-.d2
                else
                    set x=x+.kb_speed*.cos
                    set y=y+.kb_speed*.sin
                endif
                set d=SquareRoot(Pow(x-.x,2)+Pow(y-.y,2))
                if d<=.kb_distance then
                    call SetUnitPosition(.u,x,y)
                    if (.kb_fx!=null or .kb_fx!="") then
                        call DestroyEffect(AddSpecialEffect(.kb_fx,x,y))
                    endif
                    if .kb_arc>0. then
                        if .kb_arc>-ARC_LIMIT and .kb_arc<ARC_LIMIT then
                            call SetUnitFlyHeight(.u,Parabola(.kb_arc,.kb_distance,d),0.)
                        else
                            call SetUnitFlyHeight(.u,ParabolicMovement(.kb_arc,.kb_distance,d),0.)
                        endif
                    endif
                    if .kb_hitTrees then
                        call MoveRectTo(treesRect,x,y)
                        call EnumDestructablesInRect(treesRect,null,function thistype.killTrees)
                    endif
                endif
                if(.kb_slideSpeed and .d1<=0.)then
                    call .manualDestroy()
                    call .t32.stop()
                elseif(not .kb_slideSpeed and d>=.kb_distance)then
                    call .manualDestroy()
                    call .t32.stop()
                endif
            else
                call .manualDestroy()
                call .t32.stop()
            endif
        endmethod

        method launch takes real a, real d, real speed returns nothing
            local integer q=R2I(.kb_timerSpeed/Timer32.PERIOD)
            set .kb_distance=d
            set .kb_speed=speed
            set .x=GetUnitX(.u)
            set .y=GetUnitY(.u)
            set .cos=Cos(a)
            set .sin=Sin(a)
            if .kb_slideSpeed then
                set .d1=2*d/(q+1)
                set .d2=.d1/q
            endif
            call SetUnitPathing(.u,.kb_collision)
            set .t32=Timer32.start(this,0,function thistype.onLoop)
        endmethod
        
        static method create takes unit forWhichUnit returns Knockback
            local thistype this=list[0]
            if this==0 then
                set this=more+1
                set more=this
            else
                set list[0]=list[this]
            endif
            set .u=forWhichUnit
            return this
        endmethod
        
        //! textmacro kb_operator takes OPERATOR_NAME,VAR_TYPE,VAR_NAME
        method operator $OPERATOR_NAME$= takes $VAR_TYPE$ $VAR_NAME$ returns nothing
            set .kb_$OPERATOR_NAME$=$VAR_NAME$
        endmethod
        //! endtextmacro
        
        //! runtextmacro kb_operator("targetUnit","unit","u")
        //! runtextmacro kb_operator("data","integer","d")
        //! runtextmacro kb_operator("slideSpeed","boolean","b")
        ////! runtextmacro kb_operator("speed","real","s")
        //! runtextmacro kb_operator("timerSpeed","real","s")
        //! runtextmacro kb_operator("arc","real","a")
        //! runtextmacro kb_operator("fx","string","f")
        ///! runtextmacro kb_operator("stop","boolean","b")
        //! runtextmacro kb_operator("collision","boolean","b")
        //! runtextmacro kb_operator("pause","boolean","b")
        //! runtextmacro kb_operator("hitTrees","boolean","b")

        static method registerEvent takes boolexpr c, Event ev returns nothing
            call ev.register(c)
        endmethod
        
        private static method onInit takes nothing returns nothing
            set treesRect=Rect(-RATIO,-RATIO,RATIO,RATIO)
            set EVENT_LOOP=CreateEvent()
            set EVENT_STOP=CreateEvent()
        endmethod
    endstruct
endlibrary
 

Kazeon

Hosted Project: EC
Level 34
Joined
Oct 12, 2011
Messages
3,449
JASS:
//Well another fucking Knockback system...
You wrote the reason why this is not acceptable by yourself. Good.

These kind of things can be approved at spell section, but not here. So please don't waste your time, for your own good. I'm glad someone trying to improve but you are doing it at (maybe) the wrong place. Jass section is not where you gamble your luck.
 
Level 9
Joined
Jun 21, 2012
Messages
431
JASS:
//Well another fucking Knockback system...
You wrote the reason why this is not acceptable by yourself. Good.

These kind of things can be approved at spell section, but not here. So please don't waste your time, for your own good. I'm glad someone trying to improve but you are doing it at (maybe) the wrong place. Jass section is not where you gamble your luck.

Sure mate :ogre_datass:. I'm working on the next version ...'ll fix it, don't worry.
 
Level 19
Joined
Mar 18, 2012
Messages
1,716
Event is deprecated and DestructableLib is graveyarded ( both are requirements )

Pro contra of your knockback system towards Knockback3D written by Cokemonkey?
--> Tell me why we need a second knockback resource
  • Better API?
  • Other, more features?
  • Cleaner code?
  • Easy implementation and usage?
  • lightweight?
  • etc ....

Unnecessary operator overloading, as they do not include extra safety. You just generate not useful code here.
Why not manipulate the variables directly?

Lacking description in the configuration block. RATIO, ACR_LINIT???

The whole code could require some description aswell.

Destructable enumeration should always be optional and in best case covered in static ifs.

Also:

Knockback does not stop when hitting unpathable terrain.
SetUnitPosition saves you from out of map bounds issues, but
may look fishy ingame. Also it has a much greater computation time then SetUnitX/Y

Stick to the JPAG, when submitting code.

The way it is now, it's going directly to the graveyard.
 
Level 23
Joined
Apr 16, 2012
Messages
4,041
why sending everything to graveyard("The way it is now, it's going directly to the graveyard."), thats like anything that is Need's fix should be rejected straight up.

Of course if it doesnt receive update/fix, then yea, but leave some time to people to update thier resource(Yes it has been submitted 3 months ago, but your review appeared today, not 3 months ago)
 
Level 19
Joined
Mar 18, 2012
Messages
1,716
I'm not moving the thread to the garveyard now. The phrase just points out that
it's not in a state for approval. I will see how the thread develops and then make a descion.

Worst user case is that imported code from a second person is not working or not easy to implement.
So what we need is
  • A minimum of debug safety, with proper output format. ( Library, function , object, instance, description, [game time?])
  • A minimum of basic features, so we really get what we import and not more. ( no pack )
  • A maximum of optional extension for a full range API ( optional, but really nice to have )
  • Understandable and well documented API
  • Finally, clean and acceptable optimized code ( not talking about micro optimizing )
 
Top