Create
Abort Abort If Abort If Condition Is False Abort If Condition Is True Add Health Pool To Player Allow Button Apply Impulse Attach Players Big Message Break Call Subroutine Cancel Primary Action Chase Global Variable At Rate Chase Global Variable Over Time Chase Player Variable At Rate Chase Player Variable Over Time Clear Status Communicate Continue Create Beam Effect Create Dummy Bot Create Effect Create HUD Text Create Homing Projectile Create Icon Create In-World Text Create Progress Bar HUD Text Create Progress Bar In-World Text Create Projectile Create Projectile Effect Damage Declare Match Draw Declare Player Victory Declare Round Draw Declare Round Victory Declare Team Victory Destroy All Dummy Bots Destroy All Effects Destroy All HUD Text Destroy All Icons Destroy All In-World Text Destroy All Progress Bar HUD Text Destroy All Progress Bar In-World Text Destroy Dummy Bot Destroy Effect Destroy HUD Text Destroy Icon Destroy In-World Text Destroy Progress Bar HUD Text Destroy Progress Bar In-World Text Detach Players Disable Built-In Game Mode Announcer Disable Built-In Game Mode Completion Disable Built-In Game Mode Music Disable Built-In Game Mode Respawning Disable Built-In Game Mode Scoring Disable Death Spectate All Players Disable Death Spectate Target HUD Disable Game Mode HUD Disable Game Mode In-World UI Disable Hero HUD Disable Inspector Recording Disable Kill Feed Disable Messages Disable Movement Collision With Environment Disable Movement Collision With Players Disable Nameplates Disable Scoreboard Disable Text Chat Disable Voice Chat Disallow Button Else Else If Enable Built-In Game Mode Announcer Enable Built-In Game Mode Completion Enable Built-In Game Mode Music Enable Built-In Game Mode Respawning Enable Built-In Game Mode Scoring Enable Death Spectate All Players Enable Death Spectate Target HUD Enable Game Mode HUD Enable Game Mode In-World UI Enable Hero HUD Enable Inspector Recording Enable Kill Feed Enable Messages Enable Movement Collision With Environment Enable Movement Collision With Players Enable Nameplates Enable Scoreboard Enable Text Chat Enable Voice Chat End For Global Variable For Player Variable Go To Assemble Heroes Heal If Kill Log To Inspector Loop Loop If Loop If Condition Is False Loop If Condition Is True Modify Global Variable Modify Global Variable At Index Modify Player Score Modify Player Variable Modify Player Variable At Index Modify Team Score Move Player To Team Pause Match Time Play Effect Preload Hero Press Button Remove All Health Pools From Player Remove Health Pool From Player Remove Player Reset Player Hero Availability Respawn Restart Match Resurrect Return To Lobby Set Ability 1 Enabled Set Ability 2 Enabled Set Ability Charge Set Ability Cooldown Set Ability Resource Set Aim Speed Set Ammo Set Crouch Enabled Set Damage Dealt Set Damage Received Set Environment Credit Player Set Facing Set Global Variable Set Global Variable At Index Set Gravity Set Healing Dealt Set Healing Received Set Invisible Set Jump Enabled Set Jump Vertical Speed Set Knockback Dealt Set Knockback Received Set Match Time Set Max Ammo Set Max Health Set Melee Enabled Set Move Speed Set Objective Description Set Player Allowed Heroes Set Player Health Set Player Score Set Player Variable Set Player Variable At Index Set Primary Fire Enabled Set Projectile Gravity Set Projectile Speed Set Reload Enabled Set Respawn Max Time Set Secondary Fire Enabled Set Slow Motion Set Status Set Team Score Set Ultimate Ability Enabled Set Ultimate Charge Set Weapon Skip Skip If Small Message Start Accelerating Start Assist Start Camera Start Damage Modification Start Damage Over Time Start Facing Start Forcing Dummy Bot Name Start Forcing Player Outlines Start Forcing Player Position Start Forcing Player To Be Hero Start Forcing Spawn Room Start Forcing Throttle Start Game Mode Start Heal Over Time Start Healing Modification Start Holding Button Start Modifying Hero Voice Lines Start Rule Start Scaling Barriers Start Scaling Player Start Throttle In Direction Start Transforming Throttle Stop Accelerating Stop All Assists Stop All Damage Modifications Stop All Damage Over Time Stop All Heal Over Time Stop All Healing Modifications Stop Assist Stop Camera Stop Chasing Global Variable Stop Chasing Player Variable Stop Damage Modification Stop Damage Over Time Stop Facing Stop Forcing Dummy Bot Name Stop Forcing Player Outlines Stop Forcing Player Position Stop Forcing Player To Be Hero Stop Forcing Spawn Room Stop Forcing Throttle Stop Heal Over Time Stop Healing Modification Stop Holding Button Stop Modifying Hero Voice Lines Stop Scaling Barriers Stop Scaling Player Stop Throttle In Direction Stop Transforming Throttle Teleport Unpause Match Time Wait Wait Until While
Ability Charge Ability Cooldown Ability Icon String Ability Resource Absolute Value Add All Damage Heroes All Dead Players All Heroes All Living Players All Players All Players Not On Objective All Players On Objective All Support Heroes All Tank Heroes Allowed Heroes Altitude Of Ammo And Angle Between Vectors Angle Difference Append To Array Arccosine In Degrees Arccosine In Radians Arcsine In Degrees Arcsine In Radians Arctangent In Degrees Arctangent In Radians Array Array Contains Array Slice Assist Count Attacker Backward Button Char In String Closest Player To Color Compare Control Mode Scoring Percentage Control Mode Scoring Team Cosine From Degrees Cosine From Radians Count Of Cross Product Current Array Element Current Array Index Current Game Mode Current Map Custom Color Custom String Damage Modification Count Damage Over Time Count Direction From Angles Direction Towards Distance Between Divide Dot Product Down Empty Array Entity Count Entity Exists Evaluate Once Event Ability Event Damage Event Direction Event Healing Event Player Event Was Critical Hit Event Was Environment Event Was Health Pack Eye Position Facing Direction Of False Farthest Player From Filtered Array First Of Flag Position Forward Game Mode Global Global Variable Has Spawned Has Status Heal Over Time Count Healee Healer Healing Modification Count Health Health of Type Hero Hero Being Duplicated Hero Icon String Hero Of Horizontal Angle From Direction Horizontal Angle Towards Horizontal Facing Angle Of Horizontal Speed Of Host Player Icon String If-Then-Else Index Of Array Value Index Of String Char Input Binding String Is Alive Is Assembling Heroes Is Between Rounds Is Button Held Is CTF Mode In Sudden Death Is Communicating Is Communicating Any Is Communicating Any Emote Is Communicating Any Spray Is Communicating Any Voice line Is Control Mode Point Locked Is Crouching Is Dead Is Dummy Bot Is Duplicating Is Firing Primary Is Firing Secondary Is Flag At Base Is Flag Being Carried Is Game In Progress Is Hero Being Played Is In Air Is In Alternate Form Is In Line of Sight Is In Setup Is In Spawn Room Is In View Angle Is Jumping Is Match Complete Is Meleeing Is Moving Is Objective Complete Is On Ground Is On Objective Is On Wall Is Portrait On Fire Is Reloading Is Standing Is Team On Defense Is Team On Offense Is True For All Is True For Any Is Using Ability 1 Is Using Ability 2 Is Using Ultimate Is Waiting For Players Last Assist ID Last Created Entity Last Created Health Pool Last Damage Modification ID Last Damage Over Time ID Last Heal Over Time ID Last Healing Modification ID Last Of Last Text ID Left Local Player Local Vector Of Magnitude Of Map Mapped Array Match Round Match Time Max Max Ammo Max Health Max Health of Type Min Modulo Multiply Nearest Walkable Position Normalize Normalized Health Not Null Number of Dead Players Number of Deaths Number of Eliminations Number of Final Blows Number of Heroes Number of Living Players Number of Players Number of Players On Objective Number of Slots Objective Index Objective Position Opposite Team Of Or Payload Position Payload Progress Percentage Player Carrying Flag Player Closest To Reticle Player Hero Stat Player Stat Player Variable Players In Slot Players On Hero Players Within Radius Players in View Angle Point Capture Percentage Position Of Raise To Power Random Integer Random Real Random Value In Array Randomized Array Ray Cast Hit Normal Ray Cast Hit Player Ray Cast Hit Position Remove From Array Right Round To Integer Score Of Server Load Server Load Average Server Load Peak Sine From Degrees Sine From Radians Slot Of Sorted Array Spawn Points Speed Of Speed Of In Direction Square Root String String Contains String Length String Replace String Slice String Split Subtract Tangent From Degrees Tangent From Radians Team Of Team Score Text Count Throttle Of Total Time Elapsed True Ultimate Charge Percent Up Update Every Frame Value In Array Vector Vector Towards Velocity Of Vertical Angle From Direction Vertical Angle Towards Vertical Facing Angle Of Vertical Speed Of Victim Weapon Workshop Setting Combo Workshop Setting Hero Workshop Setting Integer Workshop Setting Real Workshop Setting Toggle World Vector Of X Component Of Y Component Of Z Component Of

Advanced vector operations: Dot Product and Cross Product Last updated August 01, 2023

The goal here is to provide some very powerful uses for these operations that otherwise tend to be not well understood.

Dot Product

The dot product is a number that is calculated by adding the products of two vectors' individual components. Dot Product((a, b, c), (d, e, f)) = a * d + b * e + c * f. It's a simple operation, but you don't need to remember how it's calculated, all you need is how to use it.

Uses

Dot Product has two major uses in general.

  1. Find the angle between two vectors (using a combination of dot product and some trigonometry). However, in the workshop we already have Angle Between Vectors().
  2. Find out how much of a vector is in a given direction. This one is the biggest use case for Dot Product in the workshop. Take a given vector V and a given normalized direction D. The return value of Dot Product(V, D) will be equal to how much of vector V is in the direction of D.

(Given the definition of dot product above, which uses only multiplication and addition, order doesn't matter, so Dot Product(V, D) = Dot Product(D, V), so feel free to remember it in whatever way makes sense to you.)

Here's a visualization that you can play with:

  • Move the black dot to define a direction D that is normalized internally.
  • Move the green dot to define a vector V.
  • The resulting blue line is the part of vector V that is in the direction of D.
  • The red dotted line is the projection, or adjustment. It's the part of V that is NOT in the direction of D.

The blue vector is calculated by multiplying the direction D by the Dot Product of D and V. B = D * Dot Product(D, V)

As you can see, placing the direction D somewhere in the opposite direction of the vector V gives the same results as placing it in a correspending direction towards vector V. The actual Dot Product is negative when in the opposite direction of V, and positive otherwise.

This is behavior that you can handle yourself with 'If' and 'Else' statements or 'If-then-else' values that check if the Dot Product is negative. You can consider Dot Product <= 0 as "The vector V is not at all in the direction of D". However, there are many cases where this works out fine without special handling, think about your use case and if a negative Dot Product would produce unintended results...

The red vector is also a very useful value. Since the blue line B is the part of V that is in the direction of D, V - B = V - (D * (Dot Product(D, V))) = R, (the red vector), which is the part of V that is NOT in the direction of D.

Example workshop use case

These two values have many uses, but here's a good example using apply impulse. If we wanted to remove all of the motion that a player has that isn't in a given direction, its as simple as this.

Apply Impulse(Event Player, -1 * R, Magnitude of(R), To World, Incorporate Contrary Motion)

(We choose Incorporate Contrary Motion here because we're the ones doing the hard work of defining exactly how to handle contrary motion. Also, Magnitude of() returns the length of the vector, which you can think of as the "strength" of the vector.)

This function removes all momentum that isn't along our intended direction, whereas a normal impulse with Cancel Contrary Motion removes all momentum that goes directly against our intended direction.

So, substituting R with the definitions above gives us this, where D is whatever your normalized intended direction is.

Apply Impulse(Event Player,
-1 * (Velocity of(Event Player) - (D * Dot Product(D, Velocity of(Event Player)))),
Magnitude of(Velocity of(Event Player) - (D * Dot Product(D, Velocity of(Event Player)))),
To World, Incorporate Contrary Motion)

If you wanted to remove a percentage, say 50%, of the motion that isn't in the intended direction, simply multiply Magnitude of(R) * 0.5.

After this impulse, you can apply a second normal impulse with Incorporate Contrary Motion in your intended direction at whatever strength you like. Those two impulses together would effectively apply a knockback that makes sure that your velocity is only along the intended direction.

Cross Product

The Cross Product has an even more complex calculation. Cross Product((a, b, c), (d, e, f)) = Vector(b*f - c*e, c*d - a*f, a*e - b*d). Again, you don't need to remember the calculation, only its use. Know that since the Cross Product includes subtraction, the order of the input vectors does matter. However the effect of order is simple, flipping the order of the inputs only multiplies the output by -1. Cross Product(A, B) == -1 * Cross Product(B, A). So if you find that your calculation is having the perfect opposite of its intended effect, try swapping the order of the inputs to the Cross Product or multiplying the Cross Product by -1.

Use

The Cross Product only has one huge use that is obviously useful to the workshop. (Ignoring any math you may do for maths sake)

  1. The Cross Product of two vectors gives you a vector that is perpendicular to both of them. Essentially this means it returns a vector that is of the direction that is not shared between the input vectors.

So, what is the cross product of Forward and Right? Well, what is the direction that is not at all shared between Forward and Right? That direction would be Up. Equivalently, what is the cross product of the Z axis and the X axis? It's the Y axis.

The length of the Cross Product return vector depends on how dissimilar the directions of the input vectors are, with input vectors in equivalent directions resulting in a Cross Product of length zero.

You can also know for certain the sign of the perpendicular direction the Cross Product returns if you remember this relationship:

In Cross Product(A, B), if the shortest rotation from A to B is Counter-Clockwise, then the direction will be toward the viewer. If it's Clockwise, then the direction will be away from the viewer. Think of tightening a screw.

(The direction depends on the viewer, because the clockwise direction depends on the viewer. Try it, make a clockwise circle while looking down at your finger, then move your finger to where you have to look up at it, and you'll notice that the clockwise direction switches.)

Example workshop use case

Cross Product is the only operation required to position an entity (effect, icon, text) at direct screen coordinates. There are other methods that use more operations, some of which can be seen in this related tutorial.

This method will have X_POS, Y_POS, and Z_POS. The center of the screen is (X,Y) = (0,0). Positive X is to the right, and positive Y is upward. The Z position is how far into the screen you want to position the entity.

  • If you're trying to attach an effect to the first person animation of a character, use a small Z value such as 0.5 or so.
  • If you're trying to make a HUD element such as text, make the Z value fairly large such as 50.
  • The max X and Y values will be proportional to whatever you set the Z value.

In the position attribute of any entity you'd like to create, place an Eye Position(Event Player) + Facing Direction Of(Event Player) * Z_POS.

Now, how would we find the direction of the player's Right using the Cross Product? We choose two vectors that we know share no Rightward direction, the player's facing direction and Up. Then we normalize the vector to make sure that is a single standard unit.

So, Player's Right = Normalize(Cross Product(Facing Direction Of(Event Player), Up))

Now that we know this, what direction is the player's Up? The two vectors that we know share none of the player's Upward direction are the Player's Right and the the player's facing direction.

So, Player's Up = Normalize(Cross Product(Cross Product(Facing Direction Of(Event Player), Up), Facing Direction Of(Event Player)))

This gives us a final position value of -

Eye Position(Event Player) + 
Facing Direction Of(Event Player) * Z_POS +
Normalize(Cross Product(Facing Direction Of(Event Player), Up)) * X_POS + 
Normalize(Cross Product(Cross Product(Facing Direction Of(Event Player), Up), Facing Direction Of(Event Player))) * Y_POS

Here, you can see a visualization of these directions on a player:
Blue = Facing, Z
White = True Up
Red = Player's Right, X
Green = Player's Up, Y

Of course, this is nowhere near the only use case. Any time you want a perpendicular vector, think of how you could do it with Cross Product.

Join the Workshop.codes Discord