• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • ✅ The POLL for Hive's Texturing Contest #33 is OPEN! Vote for the TOP 3 SKINS! 🔗Click here to cast your vote!

KB3D - Knock back 3D

Status
Not open for further replies.
Level 18
Joined
Sep 14, 2012
Messages
3,413
Dude this will get complex ince you will have negative value ^^^
Except if Accel xor Range are negatives.

Anyway you forgot to indent a loop in the code ^^'
Here is with the indented loop and the TriggerAddCondition :

JASS:
/////////////////////////////////////////////////////////////////////////////
//                                                                         //
//           Knock-Back 3D  v. 1.0.0.0   [JASS - GUI]                      //
//                                                by JAD aka DotCa         //
//                                                                         //
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//                                                                         //
//           System Requirements:   (NONE)                                 //
//                                                                         //
//  The System uses implemented CheckWalkability System by PurgeandFire    //
//  You "can" remove the initialization trigger of PnF's System since      //
//  it is directly implemented in the System, all will work fine with or   //
//  without removing your Initializer trigger                              //
//                                                                         //
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//                                                                         //
//           Credits:                                                      //
//                                                                         //
//    *Chobibo for helping in Script Fixes                                 //
//    *Malhorne for helping in Script Fixes                                //
//    *PurgeandFire for his CheckWalkability System                        //
//                                                                         //
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//                                                                         //
//           How to Import?                                                //
//                                                                         //
//  1. Check that Create Unkown Variables is ticked in your WE Settings    //
//  2. Copy the Paste this Trigger                                         //
//  3. Congratulations, the System is now implemented in your map          //
//                                                                         //
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//                                                                         //
//           How to Use?                                                   //
//                                                                         //
//  1. There are 3 Examples of use in the KB3D Example Folder              //
//  2. Documentations are there in each of the 3 examples to help you      //
//  3. The KB3D System is an Ultra-Purpose System where you can use it for://
//     -Projectiles, the system supports homming so a projectile is easy   //
//     -Jump, the System's smoothness in the fly is useful for a jump spell//
//     -And of course, a 2D Knock-Back                                     //
//                                                                         //
/////////////////////////////////////////////////////////////////////////////

function KB3D_Registration_Actions takes nothing returns boolean
    local real R
    set udg_KB3D_Counter = udg_KB3D_Counter + 1
    set udg_KB3D_Instances = udg_KB3D_Instances + 1
    set udg_KB3D_Zoffset = 2 * udg_KB3D_Zoffset
    call SaveUnitHandle( udg_KB3D_HA, 0, udg_KB3D_Counter, udg_KB3D_Unit )
    call SaveReal( udg_KB3D_HA, 1, udg_KB3D_Counter, udg_KB3D_Range )
    call SaveReal( udg_KB3D_HA, 2, udg_KB3D_Counter, udg_KB3D_Speed )
    call SaveReal( udg_KB3D_HA, 3, udg_KB3D_Counter, udg_KB3D_Zoffset )
    call SaveReal( udg_KB3D_HA, 4, udg_KB3D_Counter, udg_KB3D_Accel )
    if ( udg_KB3D_Targeted_Unit == null ) then
        call SaveReal( udg_KB3D_HA, 5, udg_KB3D_Counter, udg_KB3D_Angle * 3.14159 / 180 )
    else
        call SaveUnitHandle( udg_KB3D_HA, 5, udg_KB3D_Counter, udg_KB3D_Targeted_Unit )
    endif
    call SaveBoolean( udg_KB3D_HA, 6, udg_KB3D_Counter, udg_KB3D_DisableUnit )
    call SaveBoolean( udg_KB3D_HA, 7, udg_KB3D_Counter, udg_KB3D_UnpathableStop )
    call SaveBoolean( udg_KB3D_HA, 8, udg_KB3D_Counter, udg_KB3D_DestroyTree )
    call SaveStr( udg_KB3D_HA, 9, udg_KB3D_Counter, udg_KB3D_Fx )
    call SaveStr( udg_KB3D_HA, 10, udg_KB3D_Counter, udg_KB3D_Fx_Attach )
    if ( udg_KB3D_Accel == 0.00 ) then
        set R = udg_KB3D_Range / udg_KB3D_Speed
    else
        set R = ( 4 * udg_KB3D_Accel * udg_KB3D_Range + ( udg_KB3D_Speed * udg_KB3D_Speed ) )
    endif
    call SaveReal( udg_KB3D_HA, 11, udg_KB3D_Counter, R )
    call SaveReal( udg_KB3D_HA, 12, udg_KB3D_Counter, udg_KB3D_Zoffset / (-1 * udg_KB3D_Speed / udg_KB3D_Accel / 2) )
    call SaveReal( udg_KB3D_HA, 13, udg_KB3D_Counter, ( -1 * udg_KB3D_Zoffset / (-1 * udg_KB3D_Speed / udg_KB3D_Accel / 2) ) / (-1 * udg_KB3D_Speed / udg_KB3D_Accel / 2) )
    call SaveBoolean( udg_KB3D_HA, 15, udg_KB3D_Counter, true )
    if UnitAddAbility(udg_KB3D_Unit, 'Amrf') then
        call UnitRemoveAbility(udg_KB3D_Unit, 'Amrf')
    endif
    if ( udg_KB3D_Counter == 1 ) then
        call EnableTrigger(udg_KB3D_Loop)
    endif
    //Nulling
    set udg_KB3D_Accel = 0.00
    set udg_KB3D_Angle = 0.00
    set udg_KB3D_DestroyTree = false
    set udg_KB3D_DisableUnit = false
    set udg_KB3D_Fx = ""
    set udg_KB3D_Fx_Attach = ""
    set udg_KB3D_Range = 0.00
    set udg_KB3D_Speed = 0.00
    set udg_KB3D_Targeted_Unit = null
    set udg_KB3D_Unit = null
    set udg_KB3D_UnpathableStop = false
    set udg_KB3D_Zoffset = 0.00
    return false
endfunction

function KB3D_Tree_Check takes destructable D returns boolean
    local boolean B = false
    call IssueTargetOrder( udg_KB3D_Harvester, "harvest", D )
    if ( GetUnitCurrentOrder(udg_KB3D_Harvester) == OrderId("harvest") ) then
        set B = true
    endif
    call IssueImmediateOrder(udg_KB3D_Harvester, "stop")
    return B
endfunction

function KB3D_KillifTree takes destructable D returns nothing
    if ( KB3D_Tree_Check(D) ) then
        call KillDestructable(D)
    endif
endfunction

function KB3D_CW_Loop takes nothing returns nothing
    if IsItemVisible(GetEnumItem()) then
        set udg_CP_HiddenItems[udg_CP_HiddenItemsIndex] = GetEnumItem()
        call SetItemVisible(udg_CP_HiddenItems[udg_CP_HiddenItemsIndex], false)
        set udg_CP_HiddenItemsIndex = ( udg_CP_HiddenItemsIndex + 1 )
    endif
endfunction

function KB3D_CW takes real x, real y returns boolean
    local real x2 = 0
    local real y2 = 0
    call MoveRectTo(udg_CP_Rect, x, y)
    call EnumItemsInRect(udg_CP_Rect, null, function KB3D_CW_Loop ) 
    call SetItemPosition(udg_CP_Item, x, y)
    set x2 = GetItemX(udg_CP_Item)
    set y2 = GetItemY(udg_CP_Item)
    call SetItemVisible(udg_CP_Item, false)
    loop
        exitwhen udg_CP_HiddenItemsIndex <= 0
        set udg_CP_HiddenItemsIndex = udg_CP_HiddenItemsIndex - 1
        call SetItemVisible(udg_CP_HiddenItems[udg_CP_HiddenItemsIndex], true)
        set udg_CP_HiddenItems[udg_CP_HiddenItemsIndex] = null
    endloop
    set udg_CP_PointIsWalkable = ((x2-x)*(x2-x) + (y2-y)*(y2-y) <= 100) and (not IsTerrainPathable(x, y, PATHING_TYPE_WALKABILITY)) 
    return udg_CP_PointIsWalkable
endfunction

function KB3D_Group_Loop takes integer Loop returns nothing
    local unit U = LoadUnitHandle(udg_KB3D_HA, 0, Loop)
    local real X = GetUnitX(U)
    local real Y = GetUnitY(U)
    local real Z = GetUnitFlyHeight(U)
    local real x
    local real y
    local real z
    local real Range = LoadReal(udg_KB3D_HA, 1, Loop)
    local real Speed = LoadReal(udg_KB3D_HA, 2, Loop)
    local real Zoffset = LoadReal(udg_KB3D_HA, 3, Loop)
    local real Accel = LoadReal(udg_KB3D_HA, 4, Loop)
    local real Angle
    local real ZSpeed = LoadReal(udg_KB3D_HA, 12, Loop)
    local real ZAccel = LoadReal(udg_KB3D_HA, 13, Loop)
    local real ZTot = LoadReal(udg_KB3D_HA, 14, Loop)
    local unit Target = LoadUnitHandle(udg_KB3D_HA, 5, Loop)
    local boolean DisableUnit = LoadBoolean(udg_KB3D_HA, 6, Loop)
    local boolean UnpathableStop = LoadBoolean(udg_KB3D_HA, 7, Loop)
    local boolean DestroyTree = LoadBoolean(udg_KB3D_HA, 8, Loop)
    local string Fx = LoadStr(udg_KB3D_HA, 9, Loop)
    local string Attach = LoadStr(udg_KB3D_HA, 10, Loop)
    if ( Target == null ) then
        set Angle = LoadReal(udg_KB3D_HA, 5, Loop)
    else
        set Angle = Atan2(GetUnitY(Target) - Y, GetUnitX(Target) - X)
    endif
    set Speed = Speed + ( 0.03125 * Accel )
    set Range = Range - ( Speed * 0.03125 )
    set ZSpeed = ZSpeed + ( 0.03125 * ZAccel )
    set x = X + ( Speed * 0.03125 * Cos(Angle) )
    set y = Y + ( Speed * 0.03125 * Sin(Angle) )
    set z = Z + ( ZSpeed * 0.03125 )
    set ZTot = ZTot + ( ZSpeed * 0.03125 )
    if z >= Zoffset then
        call SaveReal(udg_KB3D_HA, 13, Loop, -1 * ZAccel)
    endif
    if ( z < 1250 ) then
        call SetUnitFlyHeight(U, z, 9999)
    endif
    if ( z > 0 ) then
        call DestroyEffect(AddSpecialEffectTarget(Fx, U, Attach))
    else
        call DestroyEffect(AddSpecialEffect(Fx, x, y))
    endif
    if ( not(UnpathableStop) or ( KB3D_CW(x, y) ) ) then
        if ( DisableUnit ) then
        else
            call SetUnitX(U, x)
            call SetUnitY(U, y)
        endif
    endif
    ////// Stop All
    if ( (Speed <= 0) or ( Range <= 0 ) or ( GetWidgetLife(U) <= 0 ) ) then
        call SaveBoolean(udg_KB3D_HA, 15, Loop, false)
        set udg_KB3D_Instances = udg_KB3D_Instances - 1
        if ( GetWidgetLife(U) <= 0 ) then
            call SetUnitFlyHeight(U, GetUnitDefaultFlyHeight(U), (GetUnitFlyHeight(U) - GetUnitDefaultFlyHeight(U)) / 0.25 )
        endif
    endif
    ////// Save Changes
    call SaveReal(udg_KB3D_HA, 1, Loop, Range)
    call SaveReal(udg_KB3D_HA, 2, Loop, Speed)
    call SaveReal(udg_KB3D_HA, 12, Loop, ZSpeed)
    call SaveReal(udg_KB3D_HA, 14, Loop, ZTot)
    ////// Clear All
    set Fx = ""
    set Attach = ""
    set U = null
    set Target = null
endfunction

function KB3D_Loop_Actions takes nothing returns boolean
    local integer x = 0
    loop
        exitwhen x >= udg_KB3D_Counter
        set x = x + 1
        if ( LoadBoolean(udg_KB3D_HA, 15, x) ) then
            call KB3D_Group_Loop(x)
        endif
    endloop
    if ( udg_KB3D_Instances == 0 ) then
        set udg_KB3D_Counter = 0
        call DisableTrigger(GetTriggeringTrigger())
    endif
    return false
endfunction

//===========================================================================
function InitTrig_KB3D takes nothing returns nothing
    ////////LOOP
    set udg_KB3D_Loop = CreateTrigger(  )
    call TriggerRegisterTimerEvent( udg_KB3D_Loop, 0.03125, true )
    call TriggerAddCondition( udg_KB3D_Loop, function KB3D_Loop_Actions )
    call DisableTrigger( udg_KB3D_Loop )
    ////////REGISTRATION
    set udg_KB3D_Registration = CreateTrigger(  )
    call TriggerAddCondition( udg_KB3D_Registration, function KB3D_Registration_Actions )
    set udg_KB3D_Harvester = CreateUnit(Player(15), 'hpea', 0, 0, 0)
    call ShowUnit(udg_KB3D_Harvester, false)
    call UnitAddAbility(udg_KB3D_Harvester, 'Aloc')
    set udg_KB3D_HA = InitHashtable()
    ////////Check Walkability System by PnF
    set udg_CP_Rect = Rect(0, 0, 128.00, 128.00)
    set udg_CP_Item = CreateItem('wtlg', 0, 0)
    call SetItemVisible( udg_CP_Item, false )
endfunction
 
Level 18
Joined
Sep 14, 2012
Messages
3,413
This loop
JASS:
function KB3D_CW takes real x, real y returns boolean
    local real x2 = 0
    local real y2 = 0
    call MoveRectTo(udg_CP_Rect, x, y)
    call EnumItemsInRect(udg_CP_Rect, null, function KB3D_CW_Loop ) 
    call SetItemPosition(udg_CP_Item, x, y)
    set x2 = GetItemX(udg_CP_Item)
    set y2 = GetItemY(udg_CP_Item)
    call SetItemVisible(udg_CP_Item, false)
    loop
    exitwhen udg_CP_HiddenItemsIndex <= 0
    set udg_CP_HiddenItemsIndex = udg_CP_HiddenItemsIndex - 1
    call SetItemVisible(udg_CP_HiddenItems[udg_CP_HiddenItemsIndex], true)
    set udg_CP_HiddenItems[udg_CP_HiddenItemsIndex] = null
    endloop
    set udg_CP_PointIsWalkable = ((x2-x)*(x2-x) + (y2-y)*(y2-y) <= 100) and (not IsTerrainPathable(x, y, PATHING_TYPE_WALKABILITY)) 
    return udg_CP_PointIsWalkable
endfunction
I corrected it in the previous code i posted ;)
 
Level 16
Joined
Jul 31, 2012
Messages
2,217
@malhorne, i don't see what's the change ...
@chobibo
the 2D Knockback has a uniform acceleration, the problem is that if that accel is null, all formulas change
the Z knockback also has auniform acceleration, it makes him go fast at first in the skies, slowly slow down and finally STOP on the demanded height, afterwards the acceleration (negative) keeps lowering the speed height making the unit go back down
 
Level 22
Joined
Sep 24, 2005
Messages
4,821
Yo guys, I'm gonna rest, I'm sleepy lol. Since master moose Malhorne's here, we can rest easy. :D Don't worry, I'll return later (after 5 hours). Good luck Jad, Malhorne, everyone!
 
Level 16
Joined
Jul 31, 2012
Messages
2,217
@malhorne
seriously, not a letter differs ...
@chobibo
ok
@all
the formulas are all correct, and work properly, except for one, the finalspeed formula for accel =/= 0

And found the bug that makes units stuck in the air (at least the source of it)
when 3 instances are created on the same unit at the same time, the unit goes to 1250 height (the max Z i added) if it was 2 instances at a time, there would be no problem, malhorne, can you see the problem of that?
 
Level 16
Joined
Jul 31, 2012
Messages
2,217
ok, so what to tell you, i added that instances addition thing
and it turned like this:
they still get stuck in the air, but not as easily as before
further more in the testings and debugs
i noticed that when the bug occurs, the speed (rate) of the Z changing and it's Acceleration dramatically increase!
here are numbers:
NORMAL:
Speed =~ +900
Accel =~ -1200
Weird:
Speed =~ +1500
Accel =~ +2000
Note that the speed is now high and the Accel is hugely BIG
So, i added a function AlwaysNeg and AlwaysPos
Result: much much less bugs, but it's still there with like 10% chance with 5 instances / unit
and now, the values of Speed and Accel don't change anymore

UPDATED first post with the new CODE
 
Hmm.. a question, this thing has been bugging me for eternity. I use a group to filter all units in a spell similar to yours. However, it doesn't follow the group. It just damages everything in range. Everything.

Now instead of simply removing, I also added a condition to check if the picked unit is in the group equal to false. WTH. Now works 50% of the time. The other 50%.. still damages everything in range. I'm gonna die.
 
Level 16
Joined
Jul 31, 2012
Messages
2,217
Results, more and more...
i am tired of testing it lol, so i think this time is the final:
Subject: BUG - stays in the skies
Statistics:
IF 3 or more instances are registered on the same unit within 0.3 seconds of time lapse, the bug occurs
When exactly?
It occurs at the instance where the unit "should" start going down
Any help would be needed, meanwhile, i am still trying to fix it

EDIT: Changed the if block ( z >= Zoffset ) to (Z >= Zoffset)
Result:
the time lapse dropped from 0.3 s to 0.2 (approx values)
 
Level 18
Joined
Sep 14, 2012
Messages
3,413
Oh cooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooool
Oups sry ^^'
Nearly felt asleep on my keyboard ^^'
But yeah let's keep those 'o' xD
Anyway i'll see it after.
 
Level 18
Joined
Sep 14, 2012
Messages
3,413
Okay so here we are for the first question :
JASS:
function EnumDestructablesInCircleBJ takes real radius, location loc, code actionFunc returns nothing
    local rect r

    if (radius >= 0) then
        set bj_enumDestructableCenter = loc
        set bj_enumDestructableRadius = radius
        set r = GetRectFromCircleBJ(loc, radius)
        call EnumDestructablesInRect(r, filterEnumDestructablesInCircleBJ, actionFunc)
        call RemoveRect(r)
    endif
endfunction

function GetRectFromCircleBJ takes location center, real radius returns rect
    local real centerX = GetLocationX(center)
    local real centerY = GetLocationY(center)
    return Rect(centerX - radius, centerY - radius, centerX + radius, centerY + radius)
endfunction

So we have to recode this (since this BJ leak zzz) : replace this line by the code (and ofc add the local rect at the begginning)
JASS:
function GoodEnumDestructableInCircle takes real radius, real x, real y, code actionFunc returns nothing
	local rect r
	//Don't use this debug keyword block in normal JASS it is just an habit.
	debug if radius < 0 then
		debug call BJDebugMsg("Radius less than 0 zzz")
		debug return
	debug endif
	set r = Rect(x-radius, y-radius, x+radius, y+radius)
	//Replace null by the wanted boolexpr if you want one.
	call EnumDestructablesInRect(r, null, actionFunc)
	call RemoveRect(r)
	set r = null
endfunction

For the collision you'll give credits to Nestharus since i'm gonna convert his vJASS library x)
I just need a parentkey in the hashtable give me one :p !
 
Level 18
Joined
Sep 14, 2012
Messages
3,413
It wouldn not set the z offset of a location ;)
Anyway
JASS:
function RegisterUnitCollision takes unit u, real x, real y, integer i returns real
    local real l = 0
    local real h = 300
    local real m = 150
    local real nm  
    loop
        if (IsUnitInRangeXY(u, x+m, y, 0)) then
            set l = m
        else
            set h = m
        endif
        set nm = (l+h)/2
        exitwhen nm+.001 >  m and nm-.001 < m
        set m = nm
    endloop
    set m = R2I(m*10)/10.
    call SaveReal( udg_KB3D, 16, GetUnitTypeId(u), m )
    return m
endfunction

function GetUnitCollision takes unit u returns real
    local integer i = GetUnitTypeId(u)
    if HaveSavedReal( udg_KB3D, 16, i) then
        return LoadReal(udg_KB3D, 16, i)
    endif
    return RegisterUnitCollision(u, GetUnitX(u), GetUnitY(u), i)
endfunction
 
Level 16
Joined
Jul 31, 2012
Messages
2,217
no, i was thinking of maybe such thing:
JASS:
call SetLocationZ( Location, Z )

but it seems it's impossible, as malhorne said, btw malhorne, you can doublepost here, if pOke didn't reply, i wouldn't have known that you edited your post ^^"

Edit, i will see this function malhorne, and thanks
 
Status
Not open for further replies.
Top