Universal Hitbox Engine by Forecastles
This code is over 6 months old. The code may have expired and might no longer function.
An easy to use hitbox creation tool for easy development within the Workshop, with blocking, hitstun, and several other adjustable features. Designed for FFA.
For an example of a game I am developing using this tool, see Forecastle Fighters II.
This engine is primarily meant to create hitboxes for fighter-style games, but it's possible application is wide.
Below is a guide on how to develop using this tool. If this guide doesn't answer your questions, feel free to message me on discord @forecastles.
Overview
This guide first covers how to create hitboxes using the system, then how stun and blocking works within the system, then it will discuss limitations and general development tips. Some of this guide uses fighting game terms, as this is what the system is intended to develop for, contact me on discord @forecastles for clearer explainations.
When you want to create a hitbox, you will set the variable "hitbox array" with values for the Event Player you want to create a hitbox. After, you will activate the hitbox by setting "hitbox active" equal to the amount of frames you want the hitbox to be active. A hitbox will only hit a target once for the duration of it being active, allowing for creation of interesting and dynamic hitboxes. Below is the template for filling "hitbox array"
Event Player.hitbox_array = Array(resethittargets?, type, posx, posy, posz, hitboxradius, kbackhangle, kbackvangle, kbackpower, hitdamage, stuntype, stuntime, blockstun, blockknockbackpower, jugglestun, chip%, ultgain);
Event Player.hitbox_active = X; where X is how long you want it active.
When using this tool, copy paste this chunk each time you want to create a hitbox, replacing words with values. In the next section, I will break down what each of these words mean and how they affect the created hitbox.
A general important note is that hitboxes can be modified while in action. You can adjust values within hitbox_array as a hitbox is active by setting "hitbox array[0]", where the 0 represents the specific element you are trying to adjust.
Hitboxes stun players by setting a variable called "acting stun". I recommend you use
Event Player.acting_stun <= 0;
as a condition in any rule you intend to create hitboxes with, as it will ensure other hitboxes lock players out of action. This will be covered in the Stun section, but is an important note for the TLDR overview.
Hitbox Values
Event Player.hitbox_array = Array(resethittargets?, type, posx, posy, posz, hitboxradius, kbackhangle, kbackvangle, kbackpower, hitdamage, stuntype, stuntime, blockstun, blockknockbackpower, jugglestun, chip%, ultgain);
DO NOT FORGET TO SET "hitbox active" AFTER SETTING THESE VALUES
resethittargets?
Is this a new hitbox? If so, set this value to 1. This will reset the list of targets hit by the last hitbox, allowing for those previously hit to be hit again. You may want to leave this value as 0 when setting hitbox_array, as you can adjust other values within the array to modify the hitbox without resetting the targets.
type
The type of hitbox to be created. The table below decribes how each value affects the hitbox. Knockback is relative to player rotation unless otherwise stated. If this value is not set correctly, no hitbox will be created.
| Type | Positioning | Adjustments |
|---|---|---|
| 1 | Realtive To Player | This is the basic hitbox. |
| 2 | Realtive To Player | The knockback pulls to the centre of the hitbox. |
| 3 | Exact Coordinates | The knockback is absolute, not player facing. Useful for projectiles where you want the player knocked in the direction of the shot instead of player facing . |
| 4 | Exact Corrdinates | The knockback is player facing. |
| 5 | Relative to Event Player.effect_pos1active | The knockback is player facing. This allows you to chase Event Player.effect_pos1active as a position for smooth gliding hitboxes. |
| 6 | Relative To Player | Ignores wether a player is blocking or not. |
| 7 | Relative To Player | Ignores players in the air. |
| 8 | Relative To Player | Jumpable grab. Returns first player hit to Event Player.grab_target. Cannot be blocked, but ignores players in air. Ignores players who have Event Player.grabbable set to false. |
| 9 | Relative To Player | Ignores players on the ground. |
| 10 | Relative To Player | Air-only grab. Returns first player hit to Event Player.grab_target. Cannot be blocked, but ignores players on ground. Ignores players who have Event Player.grabbable set to false. |
posX
The x position of the hitbox. If player relative, this is the distance to one side or the other of the player. Otherwise, this is the exact X coordinate.
posY
The y position of the hitbox. If player relative, this is the vertical distance up or down from the player position. Otherwise, this is the exact Y coordinate. Try to avoid having this value as 0 if player relative, I usually set it to 0.5.
posZ
The z position of the hitbox. If player relative, this is the distance backwards or forwards from the player position. Otherwise, this is the exact z coordinate.
hitboxradius
How wide the hitbox is. As a general tip, hitboxes under 2 radius will begin to feel inconsistent as player jumping or movement otherwise could allow them to unexpectedly avoid hitbox range.
knockbackhangle (-360 to 360)
The horizontal adjustment to the knockback in degrees. Typically you will set this value to 0 unless you want sideways movement to hits. Set to 90 ot -90 for left/right, or 180 to pull towards the player.
knockbackvangle (-90 to 90)
The vertical adjustment to the knockback in degrees. Negative values create vertical knockback. Usually you will want to set this to -5 to -90, as players who are pushed without a little bit of vertical momentum will stop along the ground quickly.
kbackpower
The strength of the knockback dealt to a player who isn't blocking. Values below 3 will be hard to notice.
hitdamage
How much damage a non-blocking player takes.
stuntype
Which type of stun the target recieves when unblocked. The table below gives a brief overview of each stun type. A player who is already stunned can only have their stun type progress up in value. This value has no effect on blocked attacks, blockstun is universal across all hitbox types. See Blocking & Stun for more info.
| Type | Effect |
|---|---|
| 0 | No Stun, even if the other stun values are set. All other effects of the hitbox apply. Setting no hit/block stun will have the same effect as this. |
| 1 | Standing stun. The target will recover in the amount of frames set at stuntime. |
| 2 | Juggle stun. The target will be knocked over, and remain stunned until they touch the ground. When a knocked over player touches the ground they becomes invincible and lay on the ground for an amount of frames equal to the value set in jugglestun, after which they lose invicibility. |
| 3 | Final Hit. Functions the same as type 2, but the target becomes invincible right away instead of when they hit the ground, and remains invincible until they stand up after hitting the ground. |
stuntime
If stuntype is set to 1, how long the target will be stunned for in frames. Other stun types read different values in the array. This value should be set to at least 1, even if the hitbox is of another type.
blockstun
How long a player is stuck blocking after blocking this attack, measured in frames. A player will be unable to do anything but block during this time assuming you are using "acting stun" as a condition, even if they let go of the block button. This value should be set to at least 1, even if the hitbox ignores block.
blockknockbackpower
The strength of knockback recieved by a blocking player. When a player blocks an attack, the vertical angle of the knockback is not considered, and they will instead be pushed along the ground. I find 5 a good default value for this if you're uncertain.
jugglestun
When a player with stuntype 2 or 3 hits the ground, they will lay on the ground for an amount of frames equal to the LAST ATTACK they were hit by equal to that move's jugglestun. Jugglestun is overridden each time a character is hit by a hitbox, so if a character is launched by one move with stun type 2, and then hit by a move with stun type 1 before they hit the ground, they will still gain that new hitbox's jugglestun and stand up at the new value's time. This allows for interesting juggles, combos, and okizeme setups. This value should be set to at least 1, otherwise you may have broken juggles.
chip%
When a player blocks an attack, the hitdamage value is multiplied by this value and dealt to them instead. This value can be above 1.0 if you want attacks to deal more damage on block for some reason. (ie. if you want blocking an attack to reduce damage by half, set this value to 0.5)
ultgain
When this attack connects, how much ult the attacking character gets. Players who are hit gain half this value, and blocked attacks give reduces gain as well. This allows you to use the ult charge meter as a sort of super meter however you wish.
Blocking, Stun, and Creating Effective Fighters Using It
Blocking Basics
A player can block by holding crouch by default. This can be changed by you by simply changing the Button(Crouch) to whichever button you like on line 251, 268, and 271.
In the published version, a player must be on the ground, have an "acting stun" of 0 or less, "acting" must be set to false, and they must be alive. A player who is blocking has their speed set to 0. When a player blocks, they cannot jump until they stop blocking. These aspects are specific design considerations for the game I am developing, but are standard enough that I thought I'd include them. You may wish to adjust any of these aspects, but generally when developing for this engine you should set "acting" to true whenever a player is doing an action, and perclude players from acting when they have "acting stun".
When a player blocks an attack, they take a different amount of stun equal to blockstun in the hitbox array. A player who blocks cannot be knocked over, and is forced to block until the frames outlined by blockstun have passed. If a player who is in blockstun is hit by another attack, they continue to be forced to block until their blockstun reaches 0. When a player is experiencing blockstun, their stun is still written to "acting stun".
Typically, you will need to develop a way to incorporate grabs (hitbox type 8) into your game, as sitting there blocking often becomes a dominant strategy.
Stuntypes
This section is a detailed breakdown of the intricaies within different stuntypes. The overwatch workshop operates at 59 frames a second (from what I can tell). When creating moves, use multiples of 0.016 for your Wait times, as this will allow you to sync up stun timings accurately (See tip guide.). Stun types can only increase.
Stuntype 1
When a player gains stuntype 1, they become Stunned. The player is stunned for an amount of frames equal to the hitbox stuntime, after which they will become unstunned. If a player is hit again before stuntime runs out, they will continue to be stunned until it does run out. Stuntype 1 can become stuntype 2 or stuntype 3 if a player in stuntype 1 is hit by the relevant hitbox before the stun runs out.
Stuntype 2 and 3
When a player gains stuntype 2 or 3, they become Knocked Over. This player will be stunned until they touch the ground. For stuntype 2, the player remains vulnerable to attacks, allowing you to create new hitboxes and continue to suspend them in the air. For stuntype 3, the player becomes invincible until they touch the ground.
Once a player with either of these stuntypes touches the ground, they become invicible until they stand up. The player will lay on the ground for an amount of frames equal to the jugglestun of the last attack they were hit by, not neccesarily the attack that put them in stuntype 2 or 3. This jugglestun overwrite happens with any hitbox that connects while the target is in the air. Since 3 is immediately invincible the jugglestun will always be equal to the hitbox that gave the stuntype. Example: if a character is launched by one move with stun type 2, and then hit by a move with stun type 1 before they hit the ground, they will still gain that new hitbox's jugglestun and stand up at the new value's time.
When jugglestun runs out, the player stands, and they have 1 frame of actionable invulnerability. This allows them to block against attacks they stand up into, or even input invincible reversals if you intend to have them in your game.
Tips For Creating An Effective Fighter Using These Aspects
This section won't be as relevant to you if you aren't making a fighter.
Okizeme
Since you can control the amount of time a player lays on the ground, you can allow this time as an opportunity for the attacking player to "set up" their next attack, and depending on the movesets in your game, potentially force a guessing situation for the knocked over player as they stand up into an attack. This is called okizeme, and is a core aspect of fighting games.
Attack Timing and Frame Advantage
When creating moves, you should decide on how long you want the start, attack, and finish of the move to be. If a move does not take time to attack, your fighter will feel explosive and uncontrollable. Without a finishing period, it will feel like everything is blocked and it is impossible to make progress when fighting.
To accurately time start, attack, and finish, use Wait and Wait Until in multiples of 0.016. For example, if you wanted an attack to take 7 frames to start, you could put a Wait command with this value: 7 x 0.016 = 0.112. The chunk below will wait 7 frames, check if the target has been hit, and then creates a hitbox if not.
Event Player.acting = true;
Wait Until(Event Player.acting_stun > 0, 0.112);
If(Event Player.acting_stun <= 0);
Event Player.hitbox_array = full array here;
Event Player.hitbox_active = 5;
End;
When creating attacks, make sure your attacks have some ending to them as well. Typically this will be 10-30 frames depending on how chunky you want the attack to feel. Once you have decided on the ending lag of your attack in frames, you can decide on how long you want the target to be stunned for after this period has passed. This is called frame advantage, and is represented by a plus or minus followed by a number. (ie, +5) If a player is minus, they are more stunned than their opponent.
To determine how minus or plus an opponent is, first decide how long a move takes to end after attacking in frames. Say you pick 20. In Wait, this would look like 20 x 0.016 = 0.32. Below is an illustration of what this would look like in code.
Event Player.hitbox_array = full array here;
Event Player.hitbox_active = 5;
Wait Until(Event Player.acting_stun > 0, 0.32);
Event Player.acting = false;
Now that we know it will take 20 frames, lets pretend we wanted it to be +5 for the attacker. 20 plus 5 is 25. When you create the hitbox, you would set it's stun to be 25, making the enemy stunned 5 more frames than you are acting.
Keep in mind, too much advantage will allow people to hit attacks again before the target is unstunned. If an attack's advantage is more than another attacks startup, you can combo the first attack into the second.
#### Juggling
A player in stun type 2 will stay stunned until they hit the ground. You can use this, and specific knockbackvangle to make attacks link into other attacks before the target hits the ground. You want to be careful that people cannot create infinite hits out of the sequence of attacks you have. You may consider implimenting a counter for how many times people have been hit, and changing the stun type to 3 once a player passes a certain number.
Limitations
Since this is the workshop, there are limiations to this. Here is a list of limiations to be aware of and other concerns I have.
- You can only create one hitbox at a time per player. You can ameliorate this problem by having hitboxes that go through several states quickly.
- This can be quite intensive for the workshop. If your game keeps crashing, lower the active frames of some attacks.
- Currently there are no maps. You may be able to play it on maps after adjusting the workshop extensions, but again, it is very intensive and can crash occasionally which worsens on maps.
- I recommend only allowing 6 players. More runs the risk of overburdening the workshop.
- Currently there is only one hitbox shape, a sphere. If this is popular I will add other hitbox shapes that I've learned in my time with the workshop.
- Stuntype only increases. One day I will add a restand option, but it will take a bit of work so it's not a priority.
- Blizzard cannot make their mind up about how a character should act when recovering from stun. At the time of releasing this, clearing a character of status makes them actionable instantly, but just a couple patches ago there was 0.5 seconds of enforced stun even after clearing with the workshop. I will try my best to keep this updated, but this will certainly affect how your jugglestun setups play out if they change it again. Fingers crossed.
Development Tips
- If you're going to use this, let me know! I wouldn't mind being credited for the engine, but I'd mostly be happy to see it being used.
- In the published version, you can press interact to see an example hitbox, and mess around with the values without commiting to a project. This is the bottom rule.
- You can set Event Player.invulnerable to any number other than 0 to make a player ignore the hitbox system. Some systems stuff uses this. By default, the variable does not count down by itself. If you wanted to chase it, the stun processor accounts for that.
- You can use Event Player.grabbable to make characters immune to certain hitboxes.
- I encourage a wide moveset. The way i achieved this is by having different attacks when crouching, standing, or jumping. But you may wish for it to be different.
- You do not need to set the hitbox array every time you want to adjust a hitbox. Instead, you can modify specific array positions and it will have the same effect.
- I'll add more here as I think of them.
Thanks for trying this out!! Let me know if you find any bugs or have any questions.
-forecastles#1238