🏆 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!
You could say "oh come on, a lot of people have created KnockBack already", but there are several things which separate this one from others.
* Nearly fully made in GUI (except RemoveLocation and Set\GetUnitX\Y, which are not avaible in standart war3 GUI)
* MUI
* Leak-free
* Easy to edit or configure to be avaible for multiple unittypes with different parameters
* Just 3 triggers to copy (easy ha?)
* Does not reset current unit order. Yes, that's a dream for zombie shooter.
I've seen a couple of topics featuring different methods of knockback, which were made... not really good. And in addition each of them did reset unit's current action. So I've decided to make one, that will match my own needs perfectly.
Approach to storing units: First thing I've thought of was to create a trigger that will move individual unit and then self-destruct, but then I decided to stick to something simple as GUI.
So, this system uses 'dynamic' arrays of global variables. Each array stores one of parameters (which are Unit, Angle, Remaining steps, and Knockback power). Array size grows when multiple units are knocked back at the same time (array size will grow to 100 only if you have 100 units being moved by KnockBack at the same time). Once the unit is moved (and array element is not needed anymore), it is being marked as inactive. A new unit will take place of one of inactive array elements, or increase total array size by one and write into the new element.
Approach to moving units: Each tick (0.01 seconds) system cycles through the array in search for active units, and moves them.
Since none of accessible unit movement commands preserve current unit order, I've used SetUnitX & SetUnitY to move unit. Once the unit was moved the specified number of times, array element status is set to inactive, and system will not do any calculations until a new unit takes it's place.
Usage: to add a different knockback (for other unittype), just copy KnockBack trigger, and change variables. Everything is well commented.
Overall, I expect this to turn out as a usefull resource for many users.
Description will be edited later to look more like English.
Code:
Variables (name\type)
zzBoolean - Boolean
zzReal - Real
zzX - Real
zzY - Real
zzUnit - Unit
knockCount - Integer
knockZi - Boolean Array
knockAngle - Real Array
knockPower - Real Array
knockUnit - Unit Array
knockTodo - Integer Array
knockShould - Integer Array
JASS:
//For all ye JASS' lovers.
function Trig_KnockBackJadd takes real kAng, real kPow, unit kUni, integer kStep returns nothing
local integer i = 1
local integer j = 0
set udg_zzBoolean = false
loop
exitwhen i > udg_knockCount
if not udg_knockZi[i] then
set udg_zzBoolean = true
set j = i
set i = udg_knockCount + 1
endif
set i = i + 1
endloop
if not udg_zzBoolean then
set udg_knockCount = udg_knockCount + 1
set j = udg_knockCount
endif
set udg_knockAngle[j] = kAng
set udg_knockPower[j] = kPow
set udg_knockUnit[j] = kUni
set udg_knockTodo[j] = kStep
set udg_knockShould[j] = kStep
set udg_knockZi[j] = true
call EnableTrigger( gg_trg_KnockBackMainJ )
endfunction
function Trig_KnockBackJ_Conditions takes nothing returns boolean
return GetUnitTypeId(GetAttacker()) == 'hrif'
endfunction
function Trig_KnockBackJ_Actions takes nothing returns nothing
// Knockback angle:
set udg_zzReal = Atan2(GetUnitY(GetAttackedUnitBJ())-GetUnitY(GetAttacker()),GetUnitX(GetAttackedUnitBJ())-GetUnitX(GetAttacker()))
call Trig_KnockBackJadd(udg_zzReal,15,GetAttackedUnitBJ(),12)
endfunction
//===========================================================================
function InitTrig_KnockBackJ takes nothing returns nothing
set gg_trg_KnockBackJ = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_KnockBackJ, EVENT_PLAYER_UNIT_ATTACKED )
call TriggerAddCondition( gg_trg_KnockBackJ, Condition( function Trig_KnockBackJ_Conditions ) )
call TriggerAddAction( gg_trg_KnockBackJ, function Trig_KnockBackJ_Actions )
endfunction
JASS:
function Trig_KnockBackMainJ_Actions takes nothing returns nothing
local integer i = 1
loop
exitwhen i > udg_knockCount
if udg_knockZi[i] then
set udg_zzUnit = udg_knockUnit[i]
set udg_zzReal = I2R(udg_knockTodo[i]) / udg_knockShould[i]
set udg_zzReal = (udg_zzReal * udg_zzReal) * udg_knockPower[i]
set udg_zzX = GetUnitX(udg_zzUnit) + Cos(udg_knockAngle[i]) * udg_zzReal
set udg_zzY = GetUnitY(udg_zzUnit) + Sin(udg_knockAngle[i]) * udg_zzReal
if not IsTerrainPathable(udg_zzX, udg_zzY, PATHING_TYPE_WALKABILITY) then
call SetUnitX(udg_zzUnit,udg_zzX)
call SetUnitY(udg_zzUnit,udg_zzY)
endif
set udg_knockTodo[i] = udg_knockTodo[i] - 1
if udg_knockTodo[i] <= 0 then
set udg_knockZi[i] = false
if i == udg_knockCount then
set udg_knockCount = udg_knockCount - 1
endif
endif
elseif i == udg_knockCount then
set udg_knockCount = udg_knockCount - 1
if udg_knockCount <= 0 then
call DisableTrigger(GetTriggeringTrigger())
endif
endif
set i = i + 1
endloop
endfunction
//===========================================================================
function InitTrig_KnockBackMainJ takes nothing returns nothing
set gg_trg_KnockBackMainJ = CreateTrigger( )
call TriggerRegisterTimerEventPeriodic( gg_trg_KnockBackMainJ, 0.03 )
call TriggerAddAction( gg_trg_KnockBackMainJ, function Trig_KnockBackMainJ_Actions )
endfunction
Edit 1: Fixed map description and one plain mistake
Edit 2: Improved physics and included a pure JASS version of spell
Edit 3: Added JASS version into code block in the post.
Edit 4: Added preview (youtube video)
C&C are welcome.
Keywords:
knockback, knock, back, awesome, mui, spell, easy, to, edit
12th Dec 2015
IcemanBo: Too long time as NeedsFix. Rejected.
21:38, 15th Oct 2010
The_Reborn_Devil:
We already have many knockback systems and this doesn't add anything new, in fact it got less functionality than many others. Your JASS...
12th Dec 2015
IcemanBo: Too long time as NeedsFix. Rejected.
21:38, 15th Oct 2010
The_Reborn_Devil:
We already have many knockback systems and this doesn't add anything new, in fact it got less functionality than many others. Your JASS version could also be optimized a lot. If you want to have a JASS version you should at least have a JASS version of the KnockBackMain trigger as well.
Status: Rejected until updated
Rating: N/A
PM me or another mod once you've updated this with more functionality and a better and more optimized JASS version (or no JASS version at all). Have a nice day!
* Edited. Added a map name, comment on trigger input, and fixed one small plain error. Whoever was fast enough to download the spell in these 5 minutes, redownload.
Updated. Maker, added collision checking via IsTerrainPathable.
Added "square" speed curve.
Set loop period to 0.03.
KnockCount is automatically reduced and loop is disabled if KnockCount == 0. Anachron, added a JASS version, which consists of 2 triggers. I hope you're pleased. (formatting guidelines may be not preserved because triggers were recoded from scratch through normal WE) Mainy, look once more.
Review: Interesting and simple, nice lightweight system/spell/thing
The GUI code is well considering it uses an index system rather than hashtables.
I love that doesn't reset the unit order
Overall it's nice but i have a question:
JASS:
if not IsTerrainPathable(udg_zzX, udg_zzY, PATHING_TYPE_WALKABILITY) then
Why is that in JASS in the gui version? Can you not do that in GUI?
Thanks, Zeatherann.
Common.j function was preffered over it's GUI version because then I'd need to add two more lines, one for creating and assigning a new location, and one for removing it. And recycling a lot of locations 33 times per second does not look like effective way. Mainy, done. JASS version and variable notes are now avaible in the description.
This aint JASS, this is converted GUI, even if you make them with user defined globals you can still merge the triggers.
Remove the GetAttackedUnitBJ as it returns GetTriggerUnit() which you should use instead.
Anachron didn't tell you to make it in JASS, he just pointed that the JASS is better although harder for GUIers if you don't know how to call a function.
Instead in your indexing for disabling/enabling a trigger, let it run on a normal user defined global timer which you start when there are instances and pause if there are none.
JASS:
function Trig_KnockBackJ_Conditions takes nothing returns boolean
if ( not ( GetUnitTypeId(GetAttacker()) == 'hrif' ) ) then
return false
endif
return true
endfunction
function Trig_KnockBackJ_Actions takes nothing returns nothing
// Knockback angle:
set udg_zzReal = Atan2(GetUnitY(GetAttackedUnitBJ())-GetUnitY(GetAttacker()),GetUnitX(GetAttackedUnitBJ())-GetUnitX(GetAttacker()))
call Trig_KnockBackJadd(udg_zzReal,15,GetAttackedUnitBJ(),12)
endfunction
//===========================================================================
function InitTrig_KnockBackJ takes nothing returns nothing
set gg_trg_KnockBackJ = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_KnockBackJ, EVENT_PLAYER_UNIT_ATTACKED )
call TriggerAddCondition( gg_trg_KnockBackJ, Condition( function Trig_KnockBackJ_Conditions ) )
call TriggerAddAction( gg_trg_KnockBackJ, function Trig_KnockBackJ_Actions )
endfunction
This above is just a waste, use a seperate trigger to show us the example.
I think the GUI version is alright, meh just because you use SetUnitPos (that's why the orders get interrupted).
This aint JASS, this is converted GUI, even if you make them with user defined globals you can still merge the triggers.
Remove the GetAttackedUnitBJ as it returns GetTriggerUnit() which you should use instead.
Anachron didn't tell you to make it in JASS, he just pointed that the JASS is better although harder for GUIers if you don't know how to call a function.
Instead in your indexing for disabling/enabling a trigger, let it run on a normal user defined global timer which you start when there are instances and pause if there are none.
JASS:
function Trig_KnockBackJ_Conditions takes nothing returns boolean
if ( not ( GetUnitTypeId(GetAttacker()) == 'hrif' ) ) then
return false
endif
return true
endfunction
function Trig_KnockBackJ_Actions takes nothing returns nothing
// Knockback angle:
set udg_zzReal = Atan2(GetUnitY(GetAttackedUnitBJ())-GetUnitY(GetAttacker()),GetUnitX(GetAttackedUnitBJ())-GetUnitX(GetAttacker()))
call Trig_KnockBackJadd(udg_zzReal,15,GetAttackedUnitBJ(),12)
endfunction
//===========================================================================
function InitTrig_KnockBackJ takes nothing returns nothing
set gg_trg_KnockBackJ = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_KnockBackJ, EVENT_PLAYER_UNIT_ATTACKED )
call TriggerAddCondition( gg_trg_KnockBackJ, Condition( function Trig_KnockBackJ_Conditions ) )
call TriggerAddAction( gg_trg_KnockBackJ, function Trig_KnockBackJ_Actions )
endfunction
This above is just a waste, use a seperate trigger to show us the example.
I think the GUI version is alright, meh just because you use SetUnitPos (that's why the orders get interrupted).
^ That's how a condition should look like. Edited code in the description.
Preview for ones that dont have time to download this just to see if it fits their need: http://www.youtube.com/watch?v=uoaFFcTmhm0
(or check the end of description for embed video)
Yea, didn't really screen the JASS version because this is ment to be a GUI knockback.
I have one suggestion: use x and y along with a vx and vy so you can 'add' kockbacks a bit better, just a thought. You have it so the knockbacks are added, but each time it's a new entry into the index, with vx and vy as reals you wouldn't need to add to the index.
Will say for GUI this is pretty awesome, hands down. 4/5 +votes for approval
well, i just looked in the version of jass,
and i say it could be really optimized alot,
but the gui version is amazing,
probably gonna use it for mah system after he fixed version of jass =]
I like it for lightweight and simplicity over many other system, however it does have issues with trees and stunned units.
Useful for small/slow knockbacks or maybe telekinesis spells.
🔨 Downloads and Uploads have been fixed! If you still have trouble downloading or uploading assets to or from Hive, please reach out to us in the Site Discussion board.
This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
By continuing to use this site, you are consenting to our use of cookies.