• 🏆 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!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

Knock-Back Lite

Level 18
Joined
Jan 21, 2006
Messages
2,552
I didn't even see his post. You should have told me to read this page not the previous one. I have it being displayed on the same page, at least. Either way, yea I don't really know what he was talking about.
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,456
There is a problem with the item check, actually.

JASS:
((GetWidgetX(checkItem)+GetWidgetY(checkItem)-x-y)<=32)

This would have to be:

JASS:
RAbsBJ(GetWidgetX(checkItem)+GetWidgetY(checkItem)-x-y)<=32)

Logic: when y or x are greater than the unit's coordinates, this will always return true because the product opposite 32 will be negative, though it could be -5400 and still return true (flawed).

Also, this is not retrieving the actual hypotenuse. Pythagorean Theorem is l2+l2 = h2, so squaring down is not done properly as Azlier requested you use, because a true conversion will still equate SqareRoot(l2+l2) = h. Thus, your original equation:
JASS:
((iX-x)*(iX-x) + (iY-y)*(iY-y)) <= (32*32)

Is the best approach, because it still holds the correct arithmatic.
 
Level 18
Joined
Jan 21, 2006
Messages
2,552
Indeed, I think that azlier just used some sort of equation masher to produce that and seeing as how he was only holding it back from approval based on these tiny mathematical inefficiencies so I just mindlessly succumbed to his dictation.

I'm going to change the equation back for now, though it is weird that I never experienced any real bugs with this. I suppose there may have been certain flaw in the knock-back, but I didn't notice anything different upon changing it and testing it thoroughly before adjusting the calculation.
 
Level 9
Joined
Oct 11, 2009
Messages
477
I was saying you weren't using SetUnitPosition.

JASS:
//use an item to check the pathability of the new coordinate and
                //move the unit if the point is available


Read that comment move the unit if the point is available

:D:xxd: I thought you are getting serious.... No joke.
 
Level 2
Joined
Dec 31, 2009
Messages
15
Right. Squareroots are positive values, not negatives. math properties.
(a^2)^0.5 = |a|
 
Level 18
Joined
Jan 21, 2006
Messages
2,552
Actually it may not be.

JASS:
function RAbsBJ takes real a returns real
    if (a >= 0) then
        return a
    else
        return -a
    endif
endfunction

This is a fairly quick statement, while as:

JASS:
function Abs2 takes real a returns real
    return SquareRoot(a*a)
endfunction

Would probably be a little slower because of the necessity of a function call, namely the SquareRoot function. I don't know the actual benchmarks, it is just a strong assumption.

I
 
Level 18
Joined
Jan 21, 2006
Messages
2,552
Benchmarks would really be the only way to prove definitely which one is faster. I can't imagine that using the Pow native for a square root would be any faster than using the SquareRoot native; and furthermore whether or not either of those natives would be faster than an if-statement.
 
Level 19
Joined
Feb 4, 2009
Messages
1,313
your pathcheking method could be improved

the item will stay at its place if it can't move anywhere else (like a cliff full of trees)
so x and y will be equal to the item coordinates and the unit will be stuck
use a second item for that and check if the coordinates are different from the coordinates of the first item

further items will be blocked by items so one can drop an item in front of oneself to stop the knockback
pick all items in the region, save and hide them, then apply the pathing check and then reveal the items again

and units can be knocked through all paths where only items would be able to fit through (don't know how to fix that in an efficient way)
 
Level 18
Joined
Jan 21, 2006
Messages
2,552
further items will be blocked by items so one can drop an item in front of oneself to stop the knockback
pick all items in the region, save and hide them, then apply the pathing check and then reveal the items again

I was going to finish up the pathing checking actually but since nobody really uses this I just didn't. I realize that there are some cases where the pathing check will present bugs, and I suppose (since they've been noticed) I will update the code to fix those cases.

and units can be knocked through all paths where only items would be able to fit through (don't know how to fix that in an efficient way)

Well the alternative is to use IsTerrainPathable, which is only going to take a single point; this would present far more of a problem when the passages that units are being knocked into are small.

the item will stay at its place if it can't move anywhere else (like a cliff full of trees)
so x and y will be equal to the item coordinates and the unit will be stuck
use a second item for that and check if the coordinates are different from the coordinates of the first item

This problem will only occur when a unit is placed in the midst of one of these zones that you are describing. Since knock-back must be applied to a unit, the item will never be placed in a zone as you are describing unless the unit is already there. I'll see what I can do, though. I was planning on fixing this up and became occupied with other things due to the lack of download interest. It seems people either use a crappy system like Dusk's knock-back library or they insist on making their own.
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,456
A lot of it has to do with the fact that people aren't looking in here for resources. Put some of your systems in your signature so people know they exist to begin with. Advertising is what makes everything from garage sales to communism function.

I recommend you join up TheHelper.net, too. They could use a bright mind like yours there and it gives you more opportunities to flex and test your skills to have feedback from an additional community.
 
Level 18
Joined
Jan 21, 2006
Messages
2,552
I do have an account on TheHelper.net, and I have for quite some time. I was never really that active there, though, their forum isn't as well developed for this type of modding scene where there are just so many resources and so many areas of development.

By the way, my account name on TheHelper.net is xombie.
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,456
I'm not sure what you mean about the development, but ok. Member since 2006? I just signed up there XD

In 2006 I was dicking around in the Battle.net forums discussing strategy under the alias CollectiveFury. I actually bought this game 1 month after it came out, but only picked up modding it last August.

I did a bit of modding for StarCraft's editor in 2001 or something; I was trying to make "billiards" with it but that GUI interface was just dust in the wind, baby. When I opened World Editor for the first time, I really freaked out because they added a third option to the trigger interface and I gave up without asking questions.
 
Level 18
Joined
Jan 21, 2006
Messages
2,552
The forum for Warcraft III modding is a lot smaller than a forum like this one or WC3 Campaigns. I don't really use forums to post things, other than random crap that I happen to script on a whiff, the other stuff is just vaulted into maps that I will likely not play much of, or will continue later.

I have been modding Warcraft III for... about 5 years.
 
Level 19
Joined
Feb 4, 2009
Messages
1,313
Well the alternative is to use IsTerrainPathable, which is only going to take a single point; this would present far more of a problem when the passages that units are being knocked into are small.

the alternative would be SetUnitPosition or making a function which will find the next pathable point within a very big region so one can knockback a unit without having to care about terrain (which is much more realistic anyway) and then on ariving at the goal move it to some pathable point
also checking the target point in a triangular shape might be an idea but it's not nice enough for me
maybe there is a way (changing some mpq value so items have bigger collision size or something o_O)

This problem will only occur when a unit is placed in the midst of one of these zones that you are describing. Since knock-back must be applied to a unit, the item will never be placed in a zone as you are describing unless the unit is already there.

I spend the last half hour finding a case where this would happen despite what you said and I found one :grin:
BRIDGES!!!! (there is no space between the end and the water)
and it might happen if the speed is rather high as well

and I just got a new idea
it might be best to check the path before the knockback even starts so it will be faster if the speed is less then 32 because you don't have to check the points between this and the problem with high speed won't occure
 
Level 18
Joined
Jan 21, 2006
Messages
2,552
the alternative would be SetUnitPosition or making a function which will find the next pathable point within a very big region so one can knockback a unit without having to care about terrain (which is much more realistic anyway) and then on ariving at the goal move it to some pathable point

I don't really know what you're saying here.

it might be best to check the path before the knockback even starts so it will be faster if the speed is less then 32 because you don't have to check the points between this and the problem with high speed won't occure

The problem with high speed occurs when a unit is moving fast enough to move "past" unpathable objects because both the current position of the unit and the next position of the unit are both perfectly valid positions, in terms of pathability - it is a point in between that is the problem.

This library (found here) performs all of the necessary checks to determine the pathability of a point. It uses an item, however, which would not solve the little problem regarding units being pushed back into places that are too small for them to fit. I don't know if it would better to hard-code it into the system or simply use that library.
 
Level 2
Joined
Dec 31, 2009
Messages
15
what about
JASS:
       set iX = GetWidgetX(checkItem) - x
                set iY = GetWidgetY(checkItem) - y
                if iX*iX + iY*iY <= 32) then
                    call SetUnitX(kb.subject, x)
                    call SetUnitY(kb.subject, y)
                endif
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,456
This requires some explaination which I do not have time for at the moment; it is basically the lightest knockback system one can have.

JASS:
library Knockback requires DequeueStruct


globals
//*********************
//* Configuration
//* ¯¯¯¯¯¯¯¯¯¯¯¯¯
//*
    private constant real       LOOP_REF        = 0.03125
//*
//*
//*****************************************************************************
endglobals
    
    
globals
    private keyword allocate
    private keyword deallocate
    private real    g_x         = 0.
    private real    g_y         = 0.
    private item    g_item      = null
    private timer   g_timer     = CreateTimer()
endglobals
    
    
struct knockback extends array
    
    implement DequeueStruct
    
    readonly    unit    subject
    readonly    real    velocity
    readonly    real    friction
    
    private     real    rotationCos
    private     real    rotationSin
    private     real    time
    
    
    private static method onRef takes nothing returns nothing
        local thistype kb = 0
        local unit u
        local real x
        local real y
        local real iX
        local real iY
        local real vel
        loop
            set kb = kb.next()
            exitwhen kb == 0
            set vel= kb.velocity
            set u  = kb.subject
            set x  = GetUnitX(u) + vel * kb.rotationCos
            set y  = GetUnitY(u) + vel * kb.rotationSin
            //use an item to check the pathability of the new coordinate and
            //move the unit if the point is available.
            call SetItemPosition(g_item, x, y)
            set iX = GetWidgetX(g_item) - x
            set iY = GetWidgetY(g_item) - y
            if (iX*iX + iY*iY <= 32) then
                call SetUnitX(u, x)
                call SetUnitY(u, y)
            endif
            
            set kb.velocity  = vel + kb.friction
            set kb.time = kb.time - LOOP_REF
            if (kb.time <= 0.00) then
                call kb.deallocate()
                if (thistype.getLength() == 0) then
                    call PauseTimer(g_timer)
                endif
            endif
        endloop
        call SetItemPosition(g_item, g_x, g_y)
        call SetItemVisible(g_item, false)
        set u = null
    endmethod
    
    static method create takes unit u, real angle, real distance, real time returns thistype
        local thistype kb   = thistype.allocate()
        set kb.subject      = u
        set kb.rotationCos  = Cos(angle)
        set kb.rotationSin  = Sin(angle)
        set kb.time         = time
        
        set kb.velocity = (2 * distance/time) * LOOP_REF
        set kb.friction = (-kb.velocity/time) * LOOP_REF * LOOP_REF
        if (thistype.getLength() == 1) then
            call TimerStart(g_timer, LOOP_REF, true, function thistype.onRef)
        endif
        return kb
    endmethod
    
    private static method onInit takes nothing returns nothing
        //the item will be have maintained invisibility as to not interfere with
        //in-game actions, such as a unit picking the item up.
        set g_x = GetRectMaxX(bj_mapInitialPlayableArea)
        set g_y = GetRectMaxY(bj_mapInitialPlayableArea)
        set g_item = CreateItem('afac', g_x, g_y)
        call SetItemVisible(g_item, false)
    endmethod
    
endstruct

endlibrary
 
Level 1
Joined
Nov 7, 2010
Messages
3
Hey Guys i have a problem :[
i know there up is a tutorial / libary with all but i want to try it myself so..
I want to test a simple system why knocks back a target here is the code:

globals
integer KB_Counter
real KB_Distance
unit KB_Attacker
unit KB_Defender
location KB_DefLoc
location KB_AtkLoc
timer KB_Timer
endglobals

function KB_A1 takes nothing returns nothing
call DisplayTimedTextToForce(bj_FORCE_ALL_PLAYERS, 10.00, "Knockback Started!")
set KB_Counter = 1
set KB_Distance = 10.00
set KB_Attacker = GetAttacker()
set KB_Defender = GetAttackedUnitBJ()
set KB_AtkLoc = GetUnitLoc(GetAttacker())
set KB_DefLoc = GetUnitLoc(GetAttackedUnitBJ())
call StartTimerBJ(KB_Timer, true, 0.05)
endfunction

function KB_A2 takes nothing returns nothing
if KB_Counter != 50 then
set KB_Counter = (KB_Counter + 1)
set KB_Distance = (KB_Distance + 10)
call SetUnitPositionLoc(KB_Defender, PolarProjectionBJ(KB_AtkLoc, KB_Distance, AngleBetweenPoints(KB_AtkLoc, KB_DefLoc)))
else
call PauseTimerBJ(true, KB_Timer)
endif
endfunction

function InitTrig_KB takes nothing returns nothing
local trigger KB_M1 = CreateTrigger()
local trigger KB_M2 = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(KB_M1, EVENT_PLAYER_UNIT_ATTACKED)
call TriggerAddAction(KB_M1, function KB_A1)
call TriggerRegisterTimerExpireEventBJ(KB_M2, KB_Timer)
call TriggerAddAction(KB_M2, function KB_A2)
endfunction

but it happens nothing ;O what is wrong??
 
Top