• 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.

Knockback System

Status
Not open for further replies.
Level 4
Joined
Jan 5, 2014
Messages
79
Hello, I would like to present you my own Knockback system.

You may ask why I do what has already been done. Well, at firts I havent found a working Knockback map, which wouldn't be written in JASS. The other reason is that i wanted to do it better.


Real physics based knockback system

System uses user defined unit mass, land friction and many other

Collision and bouncing system based on user defined values

Made whole in GUI, so it is easy to use (apart from only one easy aspect)

Knockback on basic attack included

Several exemple spells included

A pool minigame




3D knockback (through air)

Spherical Knockback (units will be atrracted to some point)




0. Make sure you have the Automaticly create unknown variable on (in File - Properties)

1. Copy the whole Knockback System category

2. See the included guides

3. Ask me here or via email [email protected]

If you want to use the same way as I did to apply the on-attack knockback, you follow theese steps

1. Go to Physical Damage Detection for GUI v1.1.0.0 by looking_for_help and include it in your map (there is good guide)

2. Copy the Knockback on attack trigger in Knockback on attack category

If you want to use the spell system included in my example map, do this:

1. (Optional) Copy my example spells, if you want them to use

2. Copy the whole Spell category

If you want to use my Friction and Bouncing Region system:

1.Copy the Friction and Bouncing Regions

2. See the included guides to learn how to use them



My map includes Physical Damage Detection for GUI v1.1.0.0 by looking_for_help



KNOCKBACK SYSTEM made by MB (e-mail: [email protected])

1) Intoduction
2) Features
3) Basic guide

Introduction

Hello, this is my first map I made in Warcraft 3 World Editor. If you want to get to work, just skip to point 3, but I hope the whole text will be interesting (thats why I am writing it). So lets get to the firts question: Why have I created it? There have been two main reasons.
The first one is that I like challenges. I have worked with WC3 editor before and done some work to find out, how does it work (although I created no playable map). And the most challenging to me seemed the knockback effect I saw in many games (and I won't lie, the biggest inspiration for me were Warlocks).
The second reason was, that although I was trying hard, I didn't manage to find any open source knockback system map written in GUI which would be good and working (and honestly, I found some maps written in JASS, but they weren't compatible with the newest version also). So, although I know that WC3 is an old game, if someone wanted to use a knockback in his game and wanted it to be good, he had liitle to now chace to find what he wanted anywhere.

Game phylisophy (this sound so sublime, doesn't it?): I have seen lots of "pseudo"knockback maps with "Put some ints in unit group, set them a point and make them every 0.4 sec move away from that point". I thought, taht it was nice, but if there were more than two players and the second one would cast his knockback spell while the 1st players spell would be in work, wouldn't it be owerwritten? Thats what I wanted to avoid. So knockback in my map is unit specific, every unit can have diffrent knockback and its based on direction, rather than a point (knockbacked units are moved somewhere, rather than from some point).
I also managed to write the (almost) whole map in GUI. There were two main reasons to do so. The first one is that I am still not so good in JASS so it would take me much more time to crated it in JASS. The second and probably more important is, that I wanted everyone to be able to use this map with ease. And so, I managed to make this whole think library based, wich means that if someone wants to add something, which doesn't change tho whole system, he can do so by just setting a few conditions, variables or events. I will explain later. This is the biggest advantage of my system I think. The user-friendliness.

If you want to know, why is this article split into two, thats coz there are some limitations about the size of the text.

If you want to just add your own things, which are simmilar to those I have already created, there is an step by step guide included in every trigger.
There are always just some easy steps like add an event, add a condition and some variable.

IMPORTANT!!! If you simply add a unit, the system won't work, u have to first set up some prperties for the unit type of the unit. See Unit Properties Library trigger.

If you want something more unique, you can try and do it on your own (and on your own responsibility) or you can write me an e-mail ([email protected]) or on my personal hiveworkshop account and describe me what you want. If I were you, I'd prioritize the e-mail, coz look at it more often.
This trigger is used to turn on modes changing some functions of my system.
  • Commands
    • Events
      • Player - Player 1 (Red) types a chat message containing - as A substring
    • Conditions
    • Actions
      • -------- This is used for turning on and off the friendly fire mode (means that you can knockback friendly units) --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Entered chat string) Equal to -ff
        • Then - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • FrendlyFire Equal to True
            • Then - Actions
              • Set FrendlyFire = False
            • Else - Actions
              • Set FrendlyFire = True
        • Else - Actions
  • Initial actions
    • Events
      • Map initialization
    • Conditions
    • Actions
      • -------- My system is based on hashtable, I use only one --------
      • Hashtable - Create a hashtable
      • Set Properties = (Last created hashtable)
      • -------- This inicializes the important variables, they are in separate triiger just because I think it is more synoptic --------
      • Trigger - Run Constants Library <gen> (checking conditions)
      • -------- This part is used to save all the new properties of units that my system uses --------
      • Set TempGroup1 = (Units in (Playable map area))
      • Unit Group - Pick every unit in TempGroup1 and do (Actions)
        • Loop - Actions
          • Hashtable - Save FrictionOnLand as Friction_Hashtable of (Key (Picked unit)) in Properties
          • Set NewUnit = (Picked unit)
          • Set NewUnitHandle = (Picked unit)
          • Trigger - Run Unit Properties Library <gen> (checking conditions)
          • Trigger - Run Unit Properties Saving <gen> (checking conditions)
      • Custom script: call DestroyGroup (udg_TempGroup1)
      • -------- Turn this on together with Command closing trigger in order to make the command be usable just for some period of time after the game beggins --------
      • Countdown Timer - Start CommandsTimer as a One-shot timer that will expire in 10.00 seconds
If you enable this together with one function in Initial actions trigger, the command will be disabled some time after the start of the game
  • Command Closing
    • Events
      • Time - CommandsTimer expires
    • Conditions
    • Actions
      • Trigger - Turn off Commands <gen>
This is used to clear the mess after unit dies (coz dead unit cann't, or shouldn't be knockbacked)
  • Clearing
    • Events
      • Unit - A unit Dies
    • Conditions
    • Actions
      • Hashtable - Clear all child hashtables of child (Key (Dying unit)) in Properties
      • Unit Group - Remove (Dying unit) from UnitsBeingKnockbacked
This is used to clear the mess after unit dies (coz dead unit cann't, or shouldn't be knockbacked)
  • UnitEntersGame Actions
    • Events
      • Unit - A unit enters (Playable map area)
    • Conditions
    • Actions
      • Set NewUnit = (Entering unit)
      • Set NewUnitHandle = (Entering unit)
      • Hashtable - Save FrictionOnLand as Friction_Hashtable of (Key (Entering unit)) in Properties
      • Trigger - Run Unit Properties Library <gen> (checking conditions)
      • Trigger - Run Unit Properties Saving <gen> (checking conditions)
This is used to attach the data loaded via Unit Properties Library to units.
  • Unit Properties Saving
    • Events
    • Conditions
    • Actions
      • Hashtable - Save CollisionSize as CollisionSize_Hashtable of (Key NewUnitHandle) in Properties
      • Hashtable - Save Mass as Mass_Hashtable of (Key NewUnitHandle) in Properties
      • Hashtable - Save CanKnockbackOnAttack as CanKnockbackOnAttack_Hashtable of (Key NewUnitHandle) in Properties
      • Hashtable - Save CanBeKnockbacked as CanBeKnockbacked_Hashtable of (Key NewUnitHandle) in Properties
      • Hashtable - Save Gravity as Gravity_Hashtable of (Key NewUnitHandle) in Properties
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • CanKnockbackOnAttack Equal to True
        • Then - Actions
          • Hashtable - Save KnockbackEnergyOnAttack as KnockbackEnergyOnAttack_Hashta of (Key NewUnitHandle) in Properties
          • Hashtable - Save (AttackDamagePoint - 0.10) as AttackDamagePoint_Hashtable of (Key NewUnitHandle) in Properties
          • Hashtable - Save MeleeRanged as MeleeRanged_Hashtable of (Key NewUnitHandle) in Properties
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • MeleeRanged Equal to False
            • Then - Actions
              • Hashtable - Save ProjectileSpeed as ProjectileSpeed_Hashtable of (Key NewUnitHandle) in Properties
            • Else - Actions
        • Else - Actions
This trigger is triggered lot of times in order to change some units knockback.

IMPORTANT!!! As you can see, only four thing are needed in general to add a new knockback. The KnockbackTarget (the unit being knockbacked), The KnockbackTargetHandle (handle of the unit being knockbacked. The AngleOfKnockbackBeingAdded (direction of the knockback). And finally the KnockbackBeingAdded (the energy of the knockback).

So in general, if you want to make your own knockback event, you have to just determine who is knockbacked, what is the direction and what is the knockback energy and than just run this trigger.
  • Adding New Knockback
    • Events
    • Conditions
    • Actions
      • Unit Group - Add KnockbackTarget to GetUnitHandle
      • Unit Group - Pick every unit in GetUnitHandle and do (Actions)
        • Loop - Actions
          • Set KnockbackTargetHandle = (Picked unit)
      • Unit Group - Remove all units from GetUnitHandle
      • -------- At first we have to check, whether the unit to which is the knockback added is already being knockbacked or not --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (KnockbackTarget is in UnitsBeingKnockbacked) Equal to True
        • Then - Actions
          • -------- I used the point to calculate the total of two knockbacks --------
          • Set TempPoint1 = (Position of KnockbackTarget)
          • -------- The vector from TempPoint1 to TempPoint2 represents the knockback being added --------
          • Set TempPoint2 = (TempPoint1 offset by KnockbackBeingAdded towards AngleOfKnockbackBeingAdded degrees)
          • -------- The vector from TempPoint2 to TempPoint3 represents the knockback the unit already had before --------
          • Set TempPoint3 = (TempPoint2 offset by (Load CurrentEnergy_Hashtable of (Key KnockbackTargetHandle) from Properties) towards (Load AngelOfKnockback_Hashtable of (Key KnockbackTargetHandle) from Properties) degrees)
          • -------- So the vector from TempPoint1 to TempPoint3 represents the new knockback --------
          • Hashtable - Save (Distance between TempPoint1 and TempPoint3) as CurrentEnergy_Hashtable of (Key KnockbackTargetHandle) in Properties
          • Hashtable - Save (Angle from TempPoint1 to TempPoint3) as AngelOfKnockback_Hashtable of (Key KnockbackTargetHandle) in Properties
          • Custom script: call RemoveLocation(udg_TempPoint1)
          • Custom script: call RemoveLocation(udg_TempPoint2)
          • Custom script: call RemoveLocation(udg_TempPoint3)
        • Else - Actions
          • -------- If the unit wasn't knockbacked before, in this way the knockback is added to it --------
          • Unit Group - Add KnockbackTarget to UnitsBeingKnockbacked
          • Unit - Turn collision for KnockbackTarget Off
          • Hashtable - Save KnockbackBeingAdded as CurrentEnergy_Hashtable of (Key KnockbackTargetHandle) in Properties
          • Hashtable - Save AngleOfKnockbackBeingAdded as AngelOfKnockback_Hashtable of (Key KnockbackTargetHandle) in Properties
This is the most important trigger in my system. It is often changed and sometimes hard to explain, as the math is sometimes a bit complicated. So if you dont get the point, write me (for example an email) and I will try to eplain it better.
  • Knockback Engine
    • Events
      • Time - Every 0.02 seconds of game time
    • Conditions
    • Actions
      • -------- At first every unit being knockbacked is picked --------
      • Unit Group - Pick every unit in UnitsBeingKnockbacked and do (Actions)
        • Loop - Actions
          • -------- This is used to lower the bounce delay (the time until the unit can be bounced by another unit) --------
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Load BounceDelay_Hashtable of (Key (Picked unit)) from Properties) Greater than 0
            • Then - Actions
              • Hashtable - Save ((Load BounceDelay_Hashtable of (Key (Picked unit)) from Properties) - 1) as BounceDelay_Hashtable of (Key (Picked unit)) in Properties
            • Else - Actions
          • -------- End of bounc deley decraesement --------
          • -------- --------
          • -------- Now the length of the next move is loaded and the point to which the unit should move is determinated --------
          • Set TempPoint2 = (Position of (Picked unit))
          • Set NewCurrentLenghtOfJump = (2.00 x (Square root(((2.00 x (Load CurrentEnergy_Hashtable of (Key (Picked unit)) from Properties)) / (Load Mass_Hashtable of (Key (Picked unit)) from Properties)))))
          • Set NextPosition = (TempPoint2 offset by NewCurrentLenghtOfJump towards (Load AngelOfKnockback_Hashtable of (Key (Picked unit)) from Properties) degrees)
          • -------- If the move should be less than 0.1 long, the knockback of the unit is terminated --------
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • NewCurrentLenghtOfJump Greater than 0.10
            • Then - Actions
              • -------- If the jump is longer than 0.1, now it is the time to check for collisions --------
              • -------- The first unit is saved, as a new unit is about to be picked --------
              • Set FirstUnit = (Picked unit)
              • Set FirstUnitHandle = (Picked unit)
              • -------- I had to determine somehow which units should be taken into consideration, so these are all units in 400 distance from the point of the unit, whose knockback is being calculated --------
              • Set TempGroup2 = (Units within 400.00 of NextPosition)
              • -------- The range should egual to at least two times the largest unit collision size --------
              • Unit Group - Pick every unit in TempGroup2 and do (Actions)
                • Loop - Actions
                  • -------- IMPORTANT!!! Now a new unit is picked. So lets call the firstly pickedunit the first unit and the newly picked unit the second unit --------
                  • Set TempPoint1 = (Position of (Picked unit))
                  • -------- Now it is checked, whether the unit fulfils some conditions. The long one isto compare the unit custom collision size, otherwise the conditions are selfexplenatory --------
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • And - All (Conditions) are true
                        • Conditions
                          • (Distance between TempPoint1 and NextPosition) Less than or equal to ((Load CollisionSize_Hashtable of (Key (Picked unit)) from Properties) + ((Load CollisionSize_Hashtable of (Key FirstUnitHandle) from Properties) + 0.00))
                          • (Picked unit) Not equal to FirstUnit
                          • (Unit-type of (Picked unit)) Not equal to Dummy
                          • ((Picked unit) is alive) Equal to True
                          • (FirstUnit is alive) Equal to True
                    • Then - Actions
                      • -------- Now, if the second unit is a structure or it cannot be knockbacked, the first unit will simply bounce off and no energy will be exchanged --------
                      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                        • If - Conditions
                          • Or - Any (Conditions) are true
                            • Conditions
                              • ((Picked unit) is A structure) Equal to True
                              • (Load CanBeKnockbacked_Hashtable of (Key (Picked unit)) from Properties) Equal to False
                        • Then - Actions
                          • Set AngleOfKnockbackBeingAdded = (180.00 + ((Load AngelOfKnockback_Hashtable of (Key FirstUnitHandle) from Properties) - (2.00 x (Angle from TempPoint2 to TempPoint1))))
                          • Hashtable - Save AngleOfKnockbackBeingAdded as AngelOfKnockback_Hashtable of (Key FirstUnitHandle) in Properties
                        • Else - Actions
                          • -------- IMPORTANT!!! Imagine that the energy is a vector with lenght of current energy, direction of the angle of knockback and position of the position of the unit --------
                          • -------- But if both first unit and second unit can be knockbacked, there will surely be some energy exchange --------
                          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                            • If - Conditions
                              • ((Picked unit) is in UnitsBeingKnockbacked) Equal to True
                            • Then - Actions
                              • -------- If the second unit is also being knockbacked, it is checked whether the second unit hasn't bounced recently --------
                              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                                • If - Conditions
                                  • (Load BounceDelay_Hashtable of (Key (Picked unit)) from Properties) Less than or equal to 0
                                • Then - Actions
                                  • -------- If the second unit hasn't bounced recently, the angle of the collision (from first to second unit) is compared with the angle of knockback of the first unit --------
                                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                                    • If - Conditions
                                      • (Abs(((Load AngelOfKnockback_Hashtable of (Key (Picked unit)) from Properties) - (Angle from (Position of FirstUnit) to (Position of (Picked unit)))))) Greater than or equal to 90.00
                                    • Then - Actions
                                      • -------- If the absolute value of the of angles diffrence is lower than 90, both units will exchange part of their knockback --------
                                      • -------- Now lets divide knockback of both units into two parts, One paralell to the direction from the first to the second unit, one tangent to this direction. --------
                                      • -------- Both units will now exchange their part of the knockback paralell to the direction from the first one to the second one. --------
                                      • Set KnockbackBeingAdded = ((Load CurrentEnergy_Hashtable of (Key FirstUnitHandle) from Properties) x (Sin((Abs(((Load AngelOfKnockback_Hashtable of (Key FirstUnitHandle) from Properties) - (Angle from TempPoint2 to TempPoint1)))))))
                                      • Set AngleOfKnockbackBeingAdded = (Angle from TempPoint2 to TempPoint1)
                                      • Set KnockbackTarget = (Picked unit)
                                      • Trigger - Run Adding New Knockback <gen> (checking conditions)
                                      • Set AngleOfKnockbackBeingAdded = (AngleOfKnockbackBeingAdded + 180.00)
                                      • Set KnockbackTarget = FirstUnit
                                      • Trigger - Run Adding New Knockback <gen> (checking conditions)
                                      • Set KnockbackBeingAdded = ((Load CurrentEnergy_Hashtable of (Key (Picked unit)) from Properties) x (Sin((Abs(((Load AngelOfKnockback_Hashtable of (Key (Picked unit)) from Properties) - (Angle from TempPoint1 to TempPoint2)))))))
                                      • Set AngleOfKnockbackBeingAdded = (Angle from TempPoint1 to TempPoint2)
                                      • Set KnockbackTarget = FirstUnit
                                      • Trigger - Run Adding New Knockback <gen> (checking conditions)
                                      • Set AngleOfKnockbackBeingAdded = (AngleOfKnockbackBeingAdded + 180.00)
                                      • Set KnockbackTarget = (Picked unit)
                                      • Trigger - Run Adding New Knockback <gen> (checking conditions)
                                      • -------- And to protect the system from one bug, some bouncing delay is saved to both of the units --------
                                      • Hashtable - Save BasicBounceDelay as BounceDelay_Hashtable of (Key FirstUnitHandle) in Properties
                                      • Hashtable - Save BasicBounceDelay as BounceDelay_Hashtable of (Key (Picked unit)) in Properties
                                    • Else - Actions
                                      • -------- If the angle diffrence is bigger, it means the second unit was hit "from behind" (compared to the angle of knockback of the second unit) --------
                                      • -------- And so the first unit will give the second unit part of its knockback, but the scond unit won't give anything to the first one --------
                                      • Set KnockbackBeingAdded = ((Load CurrentEnergy_Hashtable of (Key FirstUnitHandle) from Properties) x (Sin((Abs(((Load AngelOfKnockback_Hashtable of (Key FirstUnitHandle) from Properties) - (Angle from TempPoint2 to TempPoint1)))))))
                                      • Set AngleOfKnockbackBeingAdded = (Angle from TempPoint2 to TempPoint1)
                                      • Set KnockbackTarget = (Picked unit)
                                      • Trigger - Run Adding New Knockback <gen> (checking conditions)
                                      • Set AngleOfKnockbackBeingAdded = (AngleOfKnockbackBeingAdded + 180.00)
                                      • Set KnockbackTarget = FirstUnit
                                      • Trigger - Run Adding New Knockback <gen> (checking conditions)
                                • Else - Actions
                                  • -------- If the second unit has bounced recently, it will behave as if it was unable to bounce. --------
                                  • Set AngleOfKnockbackBeingAdded = (180.00 + ((Load AngelOfKnockback_Hashtable of (Key FirstUnitHandle) from Properties) - (2.00 x (Angle from TempPoint2 to TempPoint1))))
                                  • Hashtable - Save AngleOfKnockbackBeingAdded as AngelOfKnockback_Hashtable of (Key FirstUnitHandle) in Properties
                            • Else - Actions
                              • -------- If the second unit wasn't knockbacked, it will get the paralell (paralell to the direction from the first to the second unit) part of the first units knockback --------
                              • Set AngleOfKnockbackBeingAdded = (Angle from TempPoint2 to TempPoint1)
                              • Set KnockbackBeingAdded = (Abs(((Load CurrentEnergy_Hashtable of (Key FirstUnitHandle) from Properties) x (Sin(((Load AngelOfKnockback_Hashtable of (Key FirstUnitHandle) from Properties) + (90.00 - AngleOfKnockbackBeingAdded)))))))
                              • Set KnockbackTarget = (Picked unit)
                              • Trigger - Run Adding New Knockback <gen> (checking conditions)
                              • Set AngleOfKnockbackBeingAdded = (AngleOfKnockbackBeingAdded + 180.00)
                              • Set KnockbackTarget = FirstUnit
                              • Trigger - Run Adding New Knockback <gen> (checking conditions)
                    • Else - Actions
                  • Custom script: call RemoveLocation(udg_TempPoint1)
              • -------- Now, after the bouncing calculations, the new position is counted once more, coz it might have changed --------
              • Custom script: call DestroyGroup(udg_TempGroup2)
              • Custom script: call RemoveLocation(udg_TempPoint2)
              • Custom script: call RemoveLocation(udg_NextPosition)
              • Set TempPoint2 = (Position of (Picked unit))
              • Set NewCurrentLenghtOfJump = (2.00 x (Square root(((2.00 x (Load CurrentEnergy_Hashtable of (Key (Picked unit)) from Properties)) / (Load Mass_Hashtable of (Key (Picked unit)) from Properties)))))
              • Set NextPosition = (TempPoint2 offset by NewCurrentLenghtOfJump towards (Load AngelOfKnockback_Hashtable of (Key (Picked unit)) from Properties) degrees)
              • -------- Now the hindering trees are destroyed --------
              • Destructible - Pick every destructible within TreeDestroyingRange of NextPosition and do (Actions)
                • Loop - Actions
                  • Destructible - Kill (Picked destructible)
              • -------- And the unit is finally moved to the new position. Hurray!!! --------
              • Set NextPositionX = (X of NextPosition)
              • Set NextPositionY = (Y of NextPosition)
              • Custom script: call SetUnitX(GetEnumUnit() , udg_NextPositionX)
              • Custom script: call SetUnitY(GetEnumUnit() , udg_NextPositionY)
              • -------- And the last step, some value is subtracted from the units knockback, the value depend on many factors, such as the units mass, friction and so on --------
              • Hashtable - Save ((Load CurrentEnergy_Hashtable of (Key (Picked unit)) from Properties) - ((Load Mass_Hashtable of (Key (Picked unit)) from Properties) x ((Load Friction_Hashtable of (Key (Picked unit)) from Properties) x (NewCurrentLenghtOfJump x (Load Gravity_Hashtable of ( as CurrentEnergy_Hashtable of (Key (Picked unit)) in Properties
            • Else - Actions
              • -------- If the jump lenght should be less than 0.1, via theese lines the kockback is terminated --------
              • Unit Group - Remove (Picked unit) from UnitsBeingKnockbacked
              • Unit - Turn collision for (Picked unit) On
          • Custom script: call RemoveLocation(udg_TempPoint2)
          • Custom script: call RemoveLocation(udg_NextPosition)
This is used to save some additional stats of units, which are neede throughout the whole system. These are linked with unit types, not with particular units. Let's take a closer look to all af them.

ProjectileSpeed - speed of projectile of ranged units, you dont have to set this for melee units (those with MeleeRanged = True). It should equal to what does the unit have in the Object editor.
MeĺeeRanger - True means melee, False means ranged
KnockbackEnergyOnAttack - the energy of the knockback caused by the unit of the unit type on attack, higher number means longer knockback, you can leave this out if CanKnockbackOnAttack of the unit type equale to false
Mass - Neccesary for all unit types with CanBeKnockbacked equal to true. Higher number means that the unit will be knockbacked less.
CollisionSize - Needed for all units. Should equale to the collision size in the Object editor of the unit type.
CanBeKnockbacked - If you want some unit not to be able to be knockbacked, set it to true, otherwise, you can leave this out
CanKnockbackOnAttack - If you want a unit of the unit type to cause knockback on attack, set this to true, you than also have to set MeleeRanger for the type, KnockbackEnergyOnAttack and AttackDamagePoint.
AttackDamagePoint - time between the unit of the unit type starts attacking and it ctually deals damage.

IMPORTANT: You have to set at least some of the variables for each unit type you use in your game. Otherwise it won't wotk properly.

Now see the trigger itself to learn how to add a new unit type.

How to add your unit type:

Step 1) Click on one of the If (All Conditions are True)...(Else Actions) and press Ctrl+c and than Ctrl+v to create a part for the unit type you want to add
Step 2) Set the comparison (Unit-type of NewUnit) to equal to your unit type
Step 3) Set the variables to suit your needs (see the Introdution if you have forgotten, what do they mean, but I think they are self explanatory.
  • Unit Properties Library
    • Events
    • Conditions
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Unit-type of NewUnit) Equal to Ball
        • Then - Actions
          • Set Mass = 250.00
          • Set CollisionSize = 25.00
          • Set CanBeKnockbacked = True
          • Set CanKnockbackOnAttack = False
        • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Unit-type of NewUnit) Equal to Rifleman
        • Then - Actions
          • Set ProjectileSpeed = 1900.00
          • Set MeleeRanged = False
          • Set KnockbackEnergyOnAttack = 500.00
          • Set Mass = 15.00
          • Set CollisionSize = 32.00
          • Set CanBeKnockbacked = True
          • Set CanKnockbackOnAttack = True
          • Set AttackDamagePoint = 0.17
        • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Unit-type of NewUnit) Equal to Knockback Master
        • Then - Actions
          • Set MeleeRanged = True
          • Set KnockbackEnergyOnAttack = 500.00
          • Set Mass = 15.00
          • Set CollisionSize = 32.00
          • Set CanBeKnockbacked = True
          • Set CanKnockbackOnAttack = True
          • Set AttackDamagePoint = 0.56
        • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Unit-type of NewUnit) Equal to Footman
        • Then - Actions
          • Set MeleeRanged = True
          • Set KnockbackEnergyOnAttack = 500.00
          • Set Mass = 15.00
          • Set CollisionSize = 31.00
          • Set CanBeKnockbacked = True
          • Set CanKnockbackOnAttack = True
          • Set AttackDamagePoint = 0.50
        • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Unit-type of NewUnit) Equal to DummyFootman
        • Then - Actions
          • Set MeleeRanged = True
          • Set KnockbackEnergyOnAttack = 500.00
          • Set Mass = 15.00
          • Set CollisionSize = 31.00
          • Set CanBeKnockbacked = True
          • Set CanKnockbackOnAttack = True
          • Set AttackDamagePoint = 0.50
        • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Unit-type of NewUnit) Equal to Grunt
        • Then - Actions
          • Set MeleeRanged = True
          • Set KnockbackEnergyOnAttack = 500.00
          • Set Mass = 15.00
          • Set CollisionSize = 32.00
          • Set CanBeKnockbacked = True
          • Set CanKnockbackOnAttack = True
          • Set AttackDamagePoint = 0.33
        • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Unit-type of NewUnit) Equal to Great Hall
        • Then - Actions
          • Set MeleeRanged = True
          • Set KnockbackEnergyOnAttack = 0.00
          • Set Mass = 15.00
          • Set CollisionSize = 176.00
          • Set CanBeKnockbacked = False
          • Set CanKnockbackOnAttack = False
        • Else - Actions
Used just to make it more simple for bigginers to change the gameplay constants. I also like having all constant at one place. It is run on the game inicialization.
  • Constants Library
    • Events
    • Conditions
    • Actions
      • -------- Basic Friction --------
      • Set FrictionOnLand = 0.10
      • -------- Friction used by one of my ingame features --------
      • Set FrictionOnVines = 0.01
      • -------- This is used to prevent tome bugs connected with collisions, I recommand never letting this to be 0, or collisions might get buggy --------
      • Set BasicBounceDelay = 5
      • -------- The basic state of ingame friendly fire, can be changed by writing -ff ingame (see commandes for closer description) --------
      • Set FrendlyFire = False
      • -------- Just another system variable, no need to change it at all --------
      • Set NumberOfSpell = 0
      • -------- Every unit in this range from a knockbackedunit will be destroyed --------
      • Set TreeDestroyingRange = 150.00
      • -------- Gravity for the whole system --------
      • Set Gravity = 1.00
      • -------- Setting integers for hashtable --------
      • Set AOEDOTTimer_Hashtable = 0
      • Set AbilityAOE_Hashtable = 1
      • Set AbilityDirection_Hashtable = 2
      • Set AbilityRange_Hashtable = 3
      • Set AbilitySpeed_Hashtable = 4
      • Set AlreadyHitGroup_Hashtable = 5
      • Set AngelOfKnockback_Hashtable = 6
      • Set Attacker_Hashtable = 7
      • Set BounceDelay_Hashtable = 8
      • Set CanBeKnockbacked_Hashtable = 9
      • Set CanKnockbackOnAttack_Hashtable = 10
      • Set CasterPosition_Hashtable = 11
      • Set Caster_Hashtable = 12
      • Set CollisionSize_Hashtable = 13
      • Set CurrentEnergy_Hashtable = 14
      • Set Friction_Hashtable = 15
      • Set Gravity_Hashtable = 16
      • Set KnockbackEnergyOnAttack_Hashta = 17
      • Set Mass_Hashtable = 18
      • Set NumberOfSpell_Hashtable = 19
      • Set RemainnigIntervals_Hashtable = 20
      • Set SpellKnockback_Hashtable = 21
      • Set TargetObjectOrdered_Hashtable = 22
      • Set TargetPointOrdered_Hashtable = 23
      • Set TimeBetweenInt_Hashtable = 24
This is the reason why I needed the DamageDetectionSystem as I couldn't manage to trigger the knockback on basic attack myself.
  • Knockback on attack
    • Events
      • Game - damageEventTrigger becomes Equal to 1.00
    • Conditions
      • damageType Equal to PHYSICAL
    • Actions
      • -------- I had to use the double pick solution as the DDS outputs units and I need mostly unit handles. --------
      • Set TempGroup1 = (Units in (Playable map area) matching ((Matching unit) Equal to target))
      • Unit Group - Pick every unit in TempGroup1 and do (Actions)
        • Loop - Actions
          • Set KnockbackTarget = target
          • Set AngleOfKnockbackBeingAdded = (Angle from (Position of source) to (Position of target))
          • Set TempGroup2 = (Units in (Playable map area) matching ((Matching unit) Equal to source))
          • Unit Group - Pick every unit in TempGroup2 and do (Actions)
            • Loop - Actions
              • Set KnockbackBeingAdded = (Load KnockbackEnergyOnAttack_Hashta of (Key (Picked unit)) from Properties)
      • Custom script: call DestroyGroup(udg_TempGroup1)
      • Custom script: call DestroyGroup(udg_TempGroup2)
      • Trigger - Run Adding New Knockback <gen> (checking conditions)
See this
This is the spell library. It is used to store stats for spells. The biggest problem is, that i have already created just four types of spells which are working. So if you want some other spell, you have to either write me on [email protected] and describe me what you want, but I don't swear I will do it (I might not have enough time, or I won't be able to do so. However, I will try always) or you can try and do it on your own (after seeing the tooltip for the trigger Knockback adding in Core Cnockback Triggers category, you should be able to do so). Now please see the comments for the triggers below).

BEWARE: you always need to do at least two changes in two triggers, in the Ability Properties Saving trigger and in the according trigger for your spell
The only reason for this trigger is, that the Editor event response Ability being cast doesnt respond to the Event Unit finishes casting an ability. If you base your spells on one of my example spells, u need to add the condition (Ability being cast) Equal to Your spell (Your spell means the name of your spell) just below the condition of the spell on which it is based.
  • Ability Properties saving
    • Events
      • Unit - A unit Begins casting an ability
    • Conditions
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Or - Any (Conditions) are true
            • Conditions
              • (Ability being cast) Equal to AOE DOT
        • Then - Actions
          • Hashtable - Save Handle Of(Target point of ability being cast) as TargetPointOrdered_Hashtable of (Key (Casting unit)) in Properties
        • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Or - Any (Conditions) are true
            • Conditions
              • (Ability being cast) Equal to One target projectile ability
        • Then - Actions
          • Hashtable - Save Handle Of(Target unit of ability being cast) as TargetObjectOrdered_Hashtable of (Key (Casting unit)) in Properties
        • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Or - Any (Conditions) are true
            • Conditions
              • (Ability being cast) Equal to AOE Passthrough skillshot
        • Then - Actions
          • Hashtable - Save Handle Of(Target point of ability being cast) as TargetPointOrdered_Hashtable of (Key (Casting unit)) in Properties
        • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Or - Any (Conditions) are true
            • Conditions
              • (Ability being cast) Equal to Instant Target Spell
        • Then - Actions
          • Hashtable - Save Handle Of(Casting unit) as Attacker_Hashtable of (Key (Target unit of ability being cast)) in Properties
          • Hashtable - Save Handle Of(Target unit of ability being cast) as TargetObjectOrdered_Hashtable of (Key (Casting unit)) in Properties
        • Else - Actions
If you want to know what exactly is this spell, run this map and try it (your KnockbackMaster has it). How to make your own:

Step 1) Press the If (All conditions...Else Actions) line, press ctrl+c and than ctrl+v to copy it.
Step 2) Set the condition to: the (Ability being cast) Equal to (Name of your ability)
Step 3) Set the variables to suit your ability (I recommand setting them to equal to those in Object editor, if possible)
Step 4) Set the variable SpellKnockback to how strong you want the knockback caused by this spell to be.
  • Targeted Projectile Ability Library
    • Events
      • Unit - A unit Finishes casting an ability
    • Conditions
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Ability being cast) Equal to One target projectile ability
        • Then - Actions
          • Set AbilitySpeed = 1000.00
          • Set SpellKnockback = 300.00
          • Trigger - Run Targeted Projectile Ability <gen> (checking conditions)
        • Else - Actions
This is used for these abilities that damage an area several times over time (run the game and use the spell AOE DOT of your KnockbackMaster if you dont know what I am talking about). I thought that the ability should also knock the hit unitas back when it damages them. If you want to create your own, you have just to:

Step 1) Press the If (All conditions...Else Actions) line, press ctrl+c and than ctrl+v to copy it.
Step 2) Set the condition to: the (Ability being cast) Equal to (Name of your ability)
Step 3) Set the variables to suit your ability (I recommand setting them to equal to those in Object editor, if possible)
Step 4) Set the variable SpellKnockback to how strong you want the knockback caused by this spell to be.
Step 5) Set KnockbackOnStart to true if you want the spell to cause knockback immidiately after the casting is completed, otherwise the first knockback will occur after theTimeBetweenIntervals expires once.

Note: With KnockbackOnStart = True the knockback will occur NumberOfIntervals +1 times
  • AOE DOT Library
    • Events
      • Unit - A unit Finishes casting an ability
    • Conditions
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Ability being cast) Equal to AOE DOT
        • Then - Actions
          • Set SpellKnockback = 300.00
          • Set TimeBetweenIntervals = 1.00
          • Set NumberOfIntervals = 3
          • Set AbilityAOE = 200.00
          • Set KnockbacksOnStart = True
          • Trigger - Run AOE DOT <gen> (checking conditions)
        • Else - Actions
This is for abilities that instantly damage and knockback target immidiately when their casting is finished. How to create one:

Step 1) Press the If (All conditions...Else Actions) line, press ctrl+c and than ctrl+v to copy it.
Step 2) Set the condition to: the (Ability being cast) Equal to (Name of your ability)
Step 3) Set the variable SpellKnockback to how strong you want the knockback caused by this spell to be.
  • Single Target Instant Spell Library
    • Events
      • Unit - A unit Finishes casting an ability
    • Conditions
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Ability being cast) Equal to Instant Target Spell
        • Then - Actions
          • Set KnockbackBeingAdded = 300.00
          • Trigger - Run Single Target Instant Spell <gen> (checking conditions)
        • Else - Actions
This is for abilities that instantly damage and knockback target immidiately when their casting is finished. How to create one:

Step 1) Press the If (All conditions...Else Actions) line, press ctrl+c and than ctrl+v to copy it.
Step 2) Set the condition to: the (Ability being cast) Equal to (Name of your ability)
Step 3) Set the variable SpellKnockback to how strong you want the knockback caused by this spell to be.
  • AOE Passthrough Skillshot Library
    • Events
      • Unit - A unit Finishes casting an ability
    • Conditions
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Ability being cast) Equal to AOE Passthrough skillshot
        • Then - Actions
          • Set SpellKnockback = 300.00
          • Set AbilityAOE = 300.00
          • Set AbilitySpeed = 1100.00
          • Set AbilityRange = 800.00
          • Trigger - Run AOE Passthrough Skillshot <gen> (checking conditions)
        • Else - Actions
This trigger is used to run the spells.
  • Spell Checking
    • Events
      • Time - Every 0.02 seconds of game time
    • Conditions
    • Actions
      • -------- This part solves the AOE DOT spells --------
      • Unit Group - Pick every unit in AOEDOTDummiesGroup and do (Actions)
        • Loop - Actions
          • Set CurrentTime = (Load AOEDOTTimer_Hashtable of (Key (Picked unit)) from Properties)
          • -------- If the CurrentTime is 0, it is the right time for a knockback --------
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • CurrentTime Less than or equal to 0.00
            • Then - Actions
              • -------- As new units are about to be picked, the first unit and its handle are saved --------
              • Set FirstUnit = (Picked unit)
              • Set FirstUnitHandle = (Picked unit)
              • -------- All possible targets of the knockback are picked --------
              • Set TempGroup1 = (Units within (Load AbilityAOE_Hashtable of (Key (Picked unit)) from Properties) of (Position of (Picked unit)))
              • Unit Group - Pick every unit in TempGroup1 and do (Actions)
                • Loop - Actions
                  • -------- The knockback will happen either if the picked unit is en enemy of the caster of the spell or if the picked unit is friendly and the friendlyfire mod is on --------
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • ((Picked unit) is A structure) Equal to False
                      • Or - Any (Conditions) are true
                        • Conditions
                          • (Owner of FirstUnit) Not equal to (Owner of (Picked unit))
                          • And - All (Conditions) are true
                            • Conditions
                              • (Owner of FirstUnit) Equal to (Owner of (Picked unit))
                              • FrendlyFire Equal to True
                    • Then - Actions
                      • -------- Now the needed things for knockback are defined --------
                      • Set TempPoint1 = (Position of FirstUnit)
                      • Set TempPoint2 = (Position of (Picked unit))
                      • -------- The knockback goes weaker with the distance from the epicentre --------
                      • Set KnockbackBeingAdded = ((Load SpellKnockbackHashtable of (Key FirstUnitHandle) from Properties) x (((-1.00 x (Power((Distance between TempPoint1 and TempPoint2), 2.00))) / (Power((Load AbilityAOE_Hashtable of (Key FirstUnitHandle) from Properties), 2.00))) + 1.00))
                      • Set AngleOfKnockbackBeingAdded = (Angle from TempPoint1 to TempPoint2)
                      • Custom script: call RemoveLocation(udg_TempPoint1)
                      • Custom script: call RemoveLocation(udg_TempPoint2)
                      • Set KnockbackTarget = (Picked unit)
                      • Trigger - Run Adding New Knockback <gen> (checking conditions)
                    • Else - Actions
              • -------- If the knockback is about to happen more (some intervals are remaining), NumerOfIntervals is decreased by one and the spell carries on --------
              • -------- If not, the spell is terminated --------
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (Load RemainnigIntervals_Hashtable of (Key FirstUnitHandle) from Properties) Greater than 0
                • Then - Actions
                  • Set NewRemainingNumberOfInt = ((Load RemainnigIntervals_Hashtable of (Key FirstUnitHandle) from Properties) - 1)
                  • Hashtable - Save (Load TimeBetweenIntHashtable of (Key (Picked unit)) from Properties) as AOEDOTTimer_Hashtable of (Key (Picked unit)) in Properties
                  • Hashtable - Save NewRemainingNumberOfInt as RemainnigIntervals_Hashtable of (Key FirstUnitHandle) in Properties
                • Else - Actions
                  • Unit Group - Remove FirstUnit from AOEDOTDummiesGroup
                  • Hashtable - Clear all child hashtables of child (Key FirstUnitHandle) in Properties
                  • Unit - Remove FirstUnit from the game
              • Custom script: call DestroyGroup (udg_TempGroup1)
            • Else - Actions
              • -------- This is to lower the hashtable based timer. --------
              • Hashtable - Save (CurrentTime - 0.02) as AOEDOTTimer_Hashtable of (Key (Picked unit)) in Properties
      • -------- This part deals with One Target Projectile based spells --------
      • Unit Group - Pick every unit in AbilityDummies_OneTarget and do (Actions)
        • Loop - Actions
          • Set TempPoint1 = (Position of (Load TargetObjectOrdered_Hashtable of (Key (Picked unit)) in Properties))
          • Set TempPoint2 = (Position of (Picked unit))
          • Set TempPoint3 = (TempPoint2 offset by ((Load AbilitySpeed_Hashtable of (Key (Picked unit)) from Properties) / 50.00) towards (Angle from TempPoint2 to TempPoint1) degrees)
          • -------- If the dummy is close enough, it will trigger the knockback and get terminated, otherwise it will just move to its target --------
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Distance between TempPoint1 and TempPoint2) Less than or equal to 40.00
              • Or - Any (Conditions) are true
                • Conditions
                  • (Owner of (Load TargetObjectOrdered_Hashtable of (Key (Picked unit)) in Properties)) Not equal to (Owner of (Picked unit))
                  • And - All (Conditions) are true
                    • Conditions
                      • (Owner of (Load TargetObjectOrdered_Hashtable of (Key (Picked unit)) in Properties)) Equal to (Owner of (Picked unit))
                      • FrendlyFire Equal to True
            • Then - Actions
              • Set AngleOfKnockbackBeingAdded = (Angle from TempPoint2 to TempPoint1)
              • Set KnockbackBeingAdded = (Load SpellKnockbackHashtable of (Key (Picked unit)) from Properties)
              • Set KnockbackTarget = (Load TargetObjectOrdered_Hashtable of (Key (Picked unit)) in Properties)
              • Trigger - Run Adding New Knockback <gen> (checking conditions)
              • Unit - Remove (Picked unit) from the game
              • Unit Group - Remove (Picked unit) from AbilityDummies_OneTarget
              • Hashtable - Clear all child hashtables of child (Key (Picked unit)) in Properties
            • Else - Actions
              • Unit - Move (Picked unit) instantly to TempPoint3
          • Custom script: call RemoveLocation(udg_TempPoint1)
          • Custom script: call RemoveLocation(udg_TempPoint2)
          • Custom script: call RemoveLocation(udg_TempPoint3)
      • -------- This part deals with AOE Passthrough Skillshot abilities --------
      • Unit Group - Pick every unit in AbilityDummies_AOEPS and do (Actions)
        • Loop - Actions
          • -------- If the unit is close enough to be knockbacked, the energy is based on the distance from the point on the lane along which the spell travels closest to the position of the unit being knockbacked --------
          • -------- Each unit can be knockbacked by each particular spell only once --------
          • Set TempPoint1 = (Position of (Picked unit))
          • -------- If the spell has traveled distanc longer than its range, it will be terminated --------
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Distance between (Load CasterPosition_Hashtable of (Key (Picked unit)) in Properties) and TempPoint1) Greater than or equal to (Load AbilityRange_Hashtable of (Key (Picked unit)) from Properties)
            • Then - Actions
              • Hashtable - Clear all child hashtables of child (Key (Picked unit)) in Properties
              • Unit Group - Remove (Picked unit) from AbilityDummies_AOEPS
              • Unit - Remove (Picked unit) from the game
            • Else - Actions
              • Set TempPoint2 = (TempPoint1 offset by ((Load AbilitySpeed_Hashtable of (Key (Picked unit)) from Properties) / 50.00) towards (Load AbilityDirection_Hashtable of (Key (Picked unit)) from Properties) degrees)
              • Unit - Move (Picked unit) instantly to TempPoint2
              • Custom script: call RemoveLocation(udg_TempPoint2)
          • Custom script: call RemoveLocation(udg_TempPoint1)
          • -------- As new units are about to be picked, the first unit and its handle are saved --------
          • Set FirstUnit = (Picked unit)
          • Set FirstUnitHandle = (Picked unit)
          • -------- All possible targets of the knockback are picked --------
          • Set TempGroup1 = (Units in (Playable map area))
          • Unit Group - Pick every unit in TempGroup1 and do (Actions)
            • Loop - Actions
              • Set TempPoint1 = (Position of FirstUnit)
              • Set TempPoint2 = (Position of (Picked unit))
              • -------- Now it is determinated, whether the unit can be knockbacked --------
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • And - All (Conditions) are true
                    • Conditions
                      • (Distance between TempPoint1 and TempPoint2) Less than or equal to (Load AbilityAOE_Hashtable of (Key FirstUnitHandle) from Properties)
                      • ((Picked unit) is in (Load AlreadyHitGroup_Hashtable of (Key FirstUnitHandle) in Properties)) Equal to False
                      • (Picked unit) Not equal to (Load Caster_Hashtable of (Key FirstUnitHandle) in Properties)
                      • ((Picked unit) is A structure) Equal to False
                      • (Unit-type of (Picked unit)) Not equal to Dummy
                      • Or - Any (Conditions) are true
                        • Conditions
                          • (Owner of FirstUnit) Not equal to (Owner of (Picked unit))
                          • And - All (Conditions) are true
                            • Conditions
                              • (Owner of FirstUnit) Equal to (Owner of (Picked unit))
                              • FrendlyFire Equal to True
                • Then - Actions
                  • Unit Group - Add (Picked unit) to (Load AlreadyHitGroup_Hashtable of (Key FirstUnitHandle) in Properties)
                  • Set KnockbackBeingAdded = ((Load SpellKnockbackHashtable of (Key FirstUnitHandle) from Properties) x (((-1.00 x (Power(((Distance between TempPoint1 and TempPoint2) x (Sin(((Load AbilityDirection_Hashtable of (Key FirstUnitHandle) from Properties) - (Angle from TempPoint1 to TempPoint
                  • Set AngleOfKnockbackBeingAdded = (Angle from TempPoint1 to TempPoint2)
                  • Set KnockbackTarget = (Picked unit)
                  • Trigger - Run Adding New Knockback <gen> (checking conditions)
                • Else - Actions
              • Custom script: call RemoveLocation(udg_TempPoint1)
              • Custom script: call RemoveLocation(udg_TempPoint2)
          • Custom script: call DestroyGroup (udg_TempGroup1)
This trigger is used to save the properties of AOE DOT spell. The data are attached to a dummy unit.
  • AOE DOT
    • Events
    • Conditions
    • Actions
      • Unit - Create 1 Dummy for (Owner of (Casting unit)) at (Load TargetPointOrdered_Hashtable of (Key (Casting unit)) in Properties) facing Default building facing degrees
      • Unit Group - Add (Last created unit) to AOEDOTDummiesGroup
      • Hashtable - Save SpellKnockback as SpellKnockbackHashtable of (Key (Last created unit)) in Properties
      • Hashtable - Save TimeBetweenIntervals as TimeBetweenIntHashtable of (Key (Last created unit)) in Properties
      • Hashtable - Save AbilityAOE as AbilityAOE_Hashtable of (Key (Last created unit)) in Properties
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • KnockbacksOnStart Equal to True
        • Then - Actions
          • Hashtable - Save (NumberOfIntervals + 1) as RemainnigIntervals_Hashtable of (Key (Last created unit)) in Properties
          • Hashtable - Save 0.00 as AOEDOTTimer_Hashtable of (Key (Last created unit)) in Properties
        • Else - Actions
          • Hashtable - Save NumberOfIntervals as RemainnigIntervals_Hashtable of (Key (Last created unit)) in Properties
          • Hashtable - Save TimeBetweenIntervals as AOEDOTTimer_Hashtable of (Key (Last created unit)) in Properties
This spell resolves instantly, so it does not need any other special trigger.
  • Single Target Instant Spell
    • Events
    • Conditions
    • Actions
      • Set TempPoint1 = (Position of (Casting unit))
      • Set TempPoint2 = (Load TargetObjectOrdered_Hashtable of (Key (Casting unit)) in Properties)
      • Set AngleOfKnockbackBeingAdded = (Angle from (Position of (Casting unit)) to (Position of (Load TargetObjectOrdered_Hashtable of (Key (Casting unit)) in Properties)))
      • Set KnockbackTarget = (Load TargetObjectOrdered_Hashtable of (Key (Casting unit)) in Properties)
      • Trigger - Run Adding New Knockback <gen> (checking conditions)
      • Custom script: call RemoveLocation(udg_TempPoint1)
      • Custom script: call RemoveLocation(udg_TempPoint2)
A dummy is created, which travels along with the visibe projectile.
  • Targeted Projectile Ability
    • Events
    • Conditions
    • Actions
      • Set CastersPosition = (Position of (Casting unit))
      • Unit - Create 1 Dummy for (Owner of (Casting unit)) at CastersPosition facing Default building facing degrees
      • Unit Group - Add (Last created unit) to AbilityDummies_OneTarget
      • Hashtable - Save AbilitySpeed as AbilitySpeed_Hashtable of (Key (Last created unit)) in Properties
      • Hashtable - Save Handle Of(Load TargetObjectOrdered_Hashtable of (Key (Casting unit)) in Properties) as TargetObjectOrdered_Hashtable of (Key (Last created unit)) in Properties
      • Hashtable - Save SpellKnockback as SpellKnockbackHashtable of (Key (Last created unit)) in Properties
Apart from the main part, there is also a counter used for groups with array. Otherwise, all the data are aslo saved via hashtable to a dummy unit. The unit has the expiration timer for 2 sec. so if you want to make it last longer (slow moving long ranged spells), you have to change it. Also see AOE Edges.
  • AOE Passthrough Skillshot
    • Events
    • Conditions
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • NumberOfSpell Equal to 100
        • Then - Actions
          • Set NumberOfSpell = 0
        • Else - Actions
          • Set NumberOfSpell = (NumberOfSpell + 1)
      • Set AbilityDirection = (Angle from (Position of (Casting unit)) to (Load TargetPointOrdered_Hashtable of (Key (Casting unit)) in Properties))
      • Set CastersPosition = (Position of (Casting unit))
      • Unit - Create 1 Dummy for (Owner of (Casting unit)) at CastersPosition facing Default building facing degrees
      • Unit - Add a 2.00 second Water Elemental expiration timer to (Last created unit)
      • Unit Group - Add (Last created unit) to AbilityDummies_AOEPS
      • Hashtable - Save AbilitySpeed as AbilitySpeed_Hashtable of (Key (Last created unit)) in Properties
      • Hashtable - Save AbilityDirection as AbilityDirection_Hashtable of (Key (Last created unit)) in Properties
      • Hashtable - Save Handle Of(Casting unit) as Caster_Hashtable of (Key (Last created unit)) in Properties
      • Hashtable - Save NumberOfSpell as NumberOfSpellHashtable of (Key (Last created unit)) in Properties
      • Hashtable - Save AbilityAOE as AbilityAOE_Hashtable of (Key (Last created unit)) in Properties
      • Hashtable - Save SpellKnockback as SpellKnockbackHashtable of (Key (Last created unit)) in Properties
      • Hashtable - Save AbilityRange as AbilityRange_Hashtable of (Key (Last created unit)) in Properties
      • Hashtable - Save Handle OfCastersPosition as CasterPosition_Hashtable of (Key (Last created unit)) in Properties
      • Hashtable - Save Handle OfHitByThisAbility[NumberOfSpell] as AlreadyHitGroup_Hashtable of (Key (Last created unit)) in Properties
This trigger gets events when -edges command is enterd in-game. Otherwise you should add there regions similar to those in Bouncing Region Libraries copying the playable map area edge in order to terminate spell dummies.
  • AOE Edges Library
    • Events
    • Conditions
      • ((Entering unit) is in AbilityDummies_AOEPS) Equal to True
    • Actions
      • Unit - Remove (Entering unit) from the game
In this part the regions used for bouncing are stored. The only thing you have to do is to add an event to a library. I should probably explain, what type of bouncing is this used for. When I started my work on a knockback system, I realized, that at the end of the playable map area the knockback starts to behave weird. So I decided that I want the knockbacked units to bounce of the edges of the playablemap area. I have managed to do so with regions. I created regions which copy the edges of the playable area and when unit unters one of this region, it chnges its direction as a rolling ball hitting a wall would. If you want to see the diffrence, try my map and knock some unit out of the map. Then enter to chat -edges and see the diffrence (u have to use another unit, I haven't found a way how to save a unit from the outside of the map). So now what these two libraries used for.

An example. You have an square and u unit inside. You want a unit to bounce inside the square when being knockbacked. You have to do this:

Note: I have already created one square in my map (right bottom corner) so you can check if what you have done is similar what i have. My square is berdered by one level higher terrain, but it is not necceary since the system is region based. On the other hand the knockback I have made will behave strange if you dont make bouncing regions for every place where terrain level differs.

Step 1) Determine the corner points of your square (Useful only if you want to use regions created via trigger, if you place them in editor, just skip to step 2; you can do it in main editor window, in the left bottom corner the position of the cursor is shown).
Step 2) Create four regions, each copying one of the edges (see my example).
Step 3) Add to the TopDown Region Library two times the event Unit enters region. TopDown means, that the unit is comming from north or south when it bounces. (In my example I add the events Unit-Unit enters North Edge and Unit-Unit enters South Edge).
Step 4) Do the same for the left and right (or western and eastern edge), but this time, add the events to the LeftRight Region Library. (In my example I add Unit-Unit enters West Edge and Unit-Unit enters East Edge)

You can virtually use these regions in any way you want, not only to create something simmilar to an arena as I have. This is just to let you know, how does it works.
  • TopDown Region Library
    • Events
      • Unit - A unit enters South Edge <gen>
      • Unit - A unit enters North Edge <gen>
    • Conditions
      • ((Entering unit) is in UnitsBeingKnockbacked) Equal to True
    • Actions
      • Set AngleOfKnockbackBeingAdded = (0.00 - (Load AngelOfKnockback_Hashtable of (Key (Entering unit)) from Properties))
      • Hashtable - Save AngleOfKnockbackBeingAdded as AngelOfKnockback_Hashtable of (Key (Entering unit)) in Properties
  • LeftRight Region Library
    • Events
      • Unit - A unit enters East Edge <gen>
      • Unit - A unit enters West Edge <gen>
    • Conditions
      • ((Entering unit) is in UnitsBeingKnockbacked) Equal to True
    • Actions
      • Set AngleOfKnockbackBeingAdded = (180.00 - (Load AngelOfKnockback_Hashtable of (Key (Entering unit)) from Properties))
      • Hashtable - Save AngleOfKnockbackBeingAdded as AngelOfKnockback_Hashtable of (Key (Entering unit)) in Properties
The friction system is region based, which means u need (either manualy, when u have created the regions in editor, or via trigger) two events. The first one is "Unit-Unit leaves a region" where the region the unit is leaving is the region where friction is diffrent from normal. U have to add this event to Friction reseting. The second one is "Unit-Unit enters a region" where the region is also the one where the friction is diffrent. You have to add this one to the trigger which saves the friction u want in that region. If you want many diffrent regions with diffrent friction, you have to create one trigger for yeach value of friction.

An example: Normal friction in my map is 0.1. You want a place where the friction is 0.2 (the unit stops earlier) and one with friction 0.05 (unit will move longer). I reccomand really trying the guide step by step if you are not sure. I have done it too, so you can than compare if you have the same.

Step 1) Create two regions, one for friction 0.2 (lets call it Region1), one for friction 0.05 (Region2) (I have alredy created the regions in this map).
Step 1.5)(optional) If you want to have all constants on one place as me, add to trigger Constants Library in the category Constants Library this: Set (name of your variable) = (friction you want), my example is Set FrictionOnVines = 0.01 (you can chech and see, that it really is there)
Step 2) Create new trigger (I reccomand creating it in the trigger category Friction Region Library). Give it any name you want ( for example Friction Region Library 1, but you can obviously use anything smplier).
Step 3) As the event the the newly created trigger enter Unit-Unit enters Region1.
Step 4) Copy the only line of code which is in Friction Region Library Vines to the actions in your new trigger and replace the FrictionOnVines with either 0.2 or the constant if you have created one.
Step 5) Add the event Unit-Unit leaves Region1 to Friction Reseting trigger.
Step 6) Now try it on your own and Steps 2 to 5 for Region2.
  • Friction Reseting
    • Events
      • Unit - A unit leaves Region1 <gen>
      • Unit - A unit leaves Region2 <gen>
    • Conditions
    • Actions
      • Hashtable - Save FrictionOnLand as Friction_Hashtable of (Key (Leaving unit)) in Properties
This is the library for regions, where the friction is not the basic one.
  • Friction Region Library Vines
    • Events
    • Conditions
    • Actions
      • Hashtable - Save FrictionOnVines as Friction_Hashtable of (Key (Entering unit)) in Properties
  • Friction Region Library 1
    • Events
      • Unit - A unit enters Region1 <gen>
    • Conditions
    • Actions
      • Hashtable - Save 0.20 as Friction_Hashtable of (Key (Entering unit)) in Properties
  • Friction Region Library 2
    • Events
      • Unit - A unit enters Region2 <gen>
    • Conditions
    • Actions
      • Hashtable - Save 0.05 as Friction_Hashtable of (Key (Entering unit)) in Properties

v 0.54 - Pool included
v 0.53 - Added some ingame info so you know what is going on
v 0.52 - First version revealed to public


These are some basic specifications of my system.
I would like you to try it and be as critical as possible, look for mistakes and errors.
Anything from leaks, spelling or gramatical mistakes and incomprihensible explanations to suggestions. The most important case in which you should tell me is when something doesn't work properly. Please tell me here or via email [email protected].

Thank you
 

Attachments

  • KnockbackSystem 0.56.w3x
    84.9 KB · Views: 109
Last edited:
Level 4
Joined
Jan 5, 2014
Messages
79
srry, didn't know, how can I move it?

or should I post it once more there? can i delete this somehow?
 
Level 4
Joined
Jan 5, 2014
Messages
79
Full triggers posted, so if you want to see them, feel free to do so, but there is little bit more of that stuff, so be prepeared =)
 
Btw, just asking; does your system do any Z-collision-checking for units for gameplay relevant stuff or is it only used for SetUnitFlyHeight?

If it does need Z-collision based on GetLocationZ(), then the system might desync in multiplayer with walkable destructables, as the Z height of a location or unit depends on the render state of walkable destructables underneath.
 
Level 23
Joined
Apr 16, 2012
Messages
4,041
Btw, just asking; does your system do any Z-collision-checking for units for gameplay relevant stuff or is it only used for SetUnitFlyHeight?

If it does need Z-collision based on GetLocationZ(), then the system might desync in multiplayer with walkable destructables, as the Z height of a location or unit depends on the render state of walkable destructables underneath.

also terrain deformation
 
Status
Not open for further replies.
Top