DoActionTap¶
This page focuses more on the coroutine which includes the actuation procedure and requirements for all fields abilitis. For information on what these abilities do, check the fields abilities documentation.
DoActionTap is a coroutine that where the leader party member's tap action will be performed. It's called a tap action because it involves holding the ability inputs for less than 20.0 frames in GetInput which is considered a tap.
Some actions may go differently when a second tap is detected shortly after the first. This is part of why this is a coroutine: it allows to wait and check for a second tap.
At any point however, the action may be cancelled by calling CancelAction which will among other things, forcefully stop this coroutine (the coroutine is meant to be stored in actioncoroutine
which is set to null when completed).
It's also possible this coroutine is called from DoActionHold, but only if the conditions for performing the hold actions aren't met. In that case, it's treated the same as if it was a tap action.
It should also be noted that it's not guaranteed the action ends up happening because any requires the player to not be in a submarine
and each action may have their own set of requirements that must be fufilled (the same goes for their double tap variant).
This page describes what the coroutine ends up doing to perform each action.
Setup¶
The coroutine starts by resetting lastactionid
to 0 (this will only be used later when Beetle
performs an action since they get less actioncooldown
).
From there, it's possible the action isn't performed if the player is in a submarine
. If this happens, digging
is toggled. This is because DoActionTap changes completely if the player is in a submarine
where it toggles whether they are underwater or not. If they aren't in a submarine
, the action is performed as normal.
No matter what, actioncoroutine
is always set to null at the end.
Action setup¶
Here's what happens before any actions:
- entity.
flip
is set totrueflip
- entity StopMoving with a targetstate of 0 (
Idle
) actionhold
is reset to 0.0- entity.
backsprite
is reset to false action
is set to true to mark the tap action being in progresslockkeys
is set to true which locks all of regular movement inputs processing in Update and GetInput in general
Finally, an angle is obtained via GetAngle that will be used during the action based on entity.detect
y angle to angle entity.sprite
. The math for it is incorrect, but it will resolve to these angles (an entity.detect
y angle of 0.0 means forward towards the screen and a result angle of 0.0 means left which matches how the entity.sprite
is setup):
entity.detect y angle |
entity.flip ? |
Result angle |
---|---|---|
[0, 90] | false | 45.0 |
]90, 225[ | false | 315.0 |
[225, 315] | false | 90.0 + entity.detect y angle |
[315, 360[ | false | 45.0 |
[0, 45[ | true | 135.0 |
[45, 135] | true | 90.0 + entity.detect y angle |
]135, 360[ | true | 225.0 |
Single this angle will be used as the new entity.sprite
y angle, they end up working out when limited to digital movement inputs because moving always sets entity.flip
in a consistent manner and these angles works with this.
However, when using analogue movement inputs, it's possible to move while entity.flip
doesn't follow. In such case, it can lead to unexpected behaviors where entity.sprite
or the action itself doesn't take place in an expected spot.
Bee
's tap action (Beemerang Toss)¶
This action only happens when playerdata[0]
's animid
(not its entity.animid
) is 0 which should mean that their entity.animid is Bee
.
It also requires that any of the following conditions is fufilled, the action doesn't happen and the coroutine goes directly to the action cleanup section below:
If any of the conditions above are fufilled, the action is performed:
- entity.animstate set to 100
Toss
sound plays on entity- entity's y
spin
set to -30.0 if entity.flip
is false, 30.0 instead if it's true - Yield for 0.2 seconds
- entity.
animstate
set to 101 - entity.
spin
zeroed out beemerang
is set to a newPrefabs/Objects/Beerang
GameObject childed to the player on layer 0 () with aninsideid
set to the current inside (instance.insideid
) and whose EntityControl has the following properties:speed
: 0.075spin
: (0.0, 0.0, 20.0)flip
: player's entity.flip
- entity.
overrideflip
is set to true - entity.
sprite
y angle is set to the angle obtained earlier in action setup beemerang
.vectordata[0]
is set to its position +lastdelta
* 7.5 which is its attempted destination (check the Beemerang documentation to learn more). If MainManager.snapTo8 is true (the 8 directional snap setting is enabled), the value oflastdelta
used will be a MainManager.Snap version of it with a step of Vector3.one which means all components will get snapped to -1.0, 0.0 or 1.0 depending on the closest one- Yield for 0.25 seconds
There is technically no double tap action because the second optional part of the action is the Halt feature which is handled separately in the Beemerang logic. It is where the requirements for it are checked as well as the inputs needed.
Beetle
's tap action (Horn Slash / Horn Dash)¶
This action only happens when playerdata[0]
's animid
(not its entity.animid
) is 1 which should mean that their entity.animid is Beetle
:
No matter what happens, lastactionid
is set to 1 which implies actioncooldown
will have a lesser value later, but the action still requires that the player wasn't dashing
as otherwise, this happens instead of the action:
- entity StopMoving with a targetstate of -1 (defaults to the
basestate
if theiranimstate
was theirwalkstate
) dashing
is set to false which stops DashBehavior from being called- entity.
jumpcooldown
is set to 5.0
However, it should be noted that it's impossible we ever get into this situation. Not only the player dashing
prevents GetInput from ever calling this coroutine, if the player was dashing
, DashBehavior would have stopped the dash already because it would have seen the input was pressed and call StopDash immediately. The logic above is actually incorrect because StopDash more exhaustively clean up things like tbox
and smoke
while the logic above doesn't. Effectively, this logic should never happen and if it did, it could leave the dash in a bad state.
If the player wasn't dashing
, then the action happens:
- entity's
overridejump
,overrideanim
andoverrideflip
are set to true - entity.animstate set to 100
- entity.
sprite
y angle is set to the angle obtained earlier in action setup Cut
sound plays at 0.5 volume- Over the course of the next 15.0 frames, the ability input (without hold) is monitored to see if a second tap is detected. If it is and flag 699 is true (obtained the dash), the frame yields stops and the dash will be done instead of the slash. NOTE: Even if flag 699 is false, the 15.0 frames yields still happens despite the fact that the double tap cannot be registered so no matter what, the Horn Slash always ends up being delayed by 15.0 frames
tbox
is initialised to be the BoxCollider of a new rooted GameObject namedcut
with aBeetleHorn
tag (see the section below for details) and its angles set to the entity's angles. Here are thetbox
properties:- size: (1.0, 1.5, 2.25)
- center: (0.0, 1.0, 0.0)
- isTrigger: true
From there, what happens in the action depends on if a double tap was registered earlier or not.
Single tap (Horn Slash)¶
This section only happens if no double tap was registered earlier:
tbox
gets destroyed in 0.15 seconds- Yield for 0.15 seconds
Double tap (Horn Dash)¶
This section happens only if a double tap was registered earlier:
spin4
sound playssmoke
is initialised to be the ParticleSystem of a newPrefabs/Particles/WalkDust
GameObject childed to this player with a local position of (0.0, 0.25, 0.1), an x angle of -90.0 and a Renderer's material.renderQueue of 3001 (This allows to render over fading BeetleGrass)diggingpart
set tosmoke
smoke
has its ParticleSystem gets some adjustements:- MainModule's startlifetime: 1.0 constant curve
- MainModule's startSize: 0.75 constant curve
- EmissionModule's rateOverTime: 5.0 constant curve
tbox
gets childed to the player entity with a local position of Vector3.zero and the following adjustments:- center set to (0.0, 1.5, 1.0)
- size set to (1.0, 1.5, 1.0)
- entity.
overridejump
set to true - entity.
animstate
set to 116 - entity gets Jump called on them with an h of 5.0
- Yield for 0.1 seconds
- Yield until entity.
onground
is true, but for up to 120.0 frames where the yields will stop regardless (it's a failsafe) - entity.
offgroundframes
is reset to 0.0 (reset the coyote time frame counter) dashing
is set to true which means the regular inputs processing Update does will get overriden by DashBehavior from now ondashdelta
is initialised tolasdelta
.normalized * 4.0 (this doesn't do anything becausedashdelta
will soon get overriden by DashBehavior, but it gives a sensible initial value)dashtarget
is set todashdelta
(this is needed for DashBehavior to start with something consistent during movement)smoke
has its ParticleSystem gets some adjustements:- MainModule's startSize: 1.1 constant curve
- EmissionModule's rateOverTime: 10.0 constant curve
- The tag of
tbox
is determined depending on flag 39 (got the upgraded dash):- true:
BeetleDash
(the Horn dash collider) - false:
BeetleHorn
(the Horn slash / Dash collider)
- true:
Moth
's tap action (Freeze / Icicle)¶
This action only happens when playerdata[0]
's animid
(not its entity.animid
) is 2 which should mean that their entity.animid is Moth
:
- entity.animstate set to 111
- entity.
overrideflip
set to true - entity.
sprite
y angle is set to the angle obtained earlier in action setup - A new
Prefabs/Particles/mothicenormal
GameObject is created rooted at the player position + Vector3.up +lastdelta
* 2.0 with a y angle of entity.detect
's y angle + 90.0, a tag ofIcecle
and a BoxCollider with the following properties:- size: (2.0, 1.0, 1.0)
- center: (0.5, 0.0, 0.0)
- isTrigger: true
OverworldIce
sound plays with 0.8 volume- The BoxCollider of the
Prefabs/Particles/mothicenormal
GameObject gets destroyed in 0.25 seconds Prefabs/Particles/mothicenormal
GameObject gets destroyed in 1.0 seconds
The double tap part of the action may happen here if flag 171 is true (obtained Icicle), but if it's false, the action ends here with a yield for 0.1 seconds.
If the flag is true, the double tap is checked here for the next 25.0 frames. It is detected if the ability input is pressed without hold during those 25.0 frames which will cause this wait to stop immedietaly (the wait still happens for 25.0 frames even if the input hasn't been pressed).
If the double tap isn't detected, the action ends immediately.
Double tap part (Icicle)¶
This section only happens if the double tap was registered earlier:
Freeze
sounf plays at 0.5 volume and 1.25 pitch- entity.
overrideanim
set to true - entity.
animstate
set to 108 - If
icecle
is null:icecle
is initialised to be a new instance ofPrefabs/Objects/icecle
. This has a tag oficecle
iceclesize
is reset to 0.0
icecle
position is set to the player position + (0.0, 4.0, 0.0) +lastdelta
* 2.0- Yield all frames until
iceclesize
reaches 1.0 where it is increased by TieFramerate(0.05) before each frame yield (so this lasts ~20.0 frames). Before a frame yield, the following also happens:icecle
y angle increased by 20.0icecle
scale set to Vector3.one *iceclesize
- DropIcecle called which does the following:
icecle
scale set to Vector3.oneicecle
gets some components added:- Rigidbody with constraints set to
FreezeRotation
(this will make the object fall due to gravity) - DestroyOnLayer SetUp with
IceShatter
deathparticles for 2.0 particletime on particlelayer 8 (Ground
) with a partoffset of 0.5 in y and a partangle of -90.0 in x - DestroyOnLayer SetUp with
IceShatter
deathparticles for 2.0 particletime on particlelayer 13 (NoDigGround
) with a partoffset of 0.5 in y and a partangle of -90.0 in x
- Rigidbody with constraints set to
icecle
's BoxCollider gets disabled then a new one gets added with the following properties:- size: (1.0, 1.5, 1.0)
- isTrigger: true
- All entityonly colliders of the current
map
gets their collisions ignored withicecle
's new BoxCollider icecle
gets destroyed in 1.0 secondsicecle
is set to null
- Yield for 0.2 seconds
Action cleanup¶
Here's what happens at the end of every action:
- Yield for a frame
lastdelta
is reset to a value that depends on entity.flip
:- true:
CamDir
's right vector normalized - true:
CamDir
's -right vector normalized (so the left vector normalized)
- true:
action
is reset to falselockkeys
is reset to false so inputs processing can happen again- entity's
overrideanim
,overrideflip
andoverridejump
are reset to false - ActionCooldown is called which sets
actioncooldown
to a value depending onlastactionid
:- 1 (
Beetle
): 5.0 frames - Any other values (
Bee
orMoth
): 17.0 frames
- 1 (