Wander¶
Periodically performs a MoveTowards call after a random amount of time passed on the entity to a random position or the closest possible before unable to move further towards it. The range of movement, maximum time period to wait between wanders and the max distance to move to between wanders are all configurable.
Frequency meaning¶
The maximum time in frames to wait before moving again. The minimum is always the 1/3 of the maximum.
Additional data¶
radiuslimit
: The max distance in which the entity is allowed to wander from its current positionwanderradius
: The x/z radius from entity.startpos
in which the entity can wander toteleportradius
: The max distance the entity can be away from itsstartpos
before being teleported to itsstartpos
SetUp (Only if it's the default behavior)¶
The actioncooldown
is set to 120 frames.
DoBehavior¶
The entity.rigid
is unlocked with LockRigid(false) if it was in kinematic or it didn't had gravity.
If returntoheight
is true, entity.height
is set to a lerp from the existing one to entity.initialheight
with a factor of 0.1
From there, there is an early exit path if the entity is in a forcemove
and any of the following is true:
- entity.
hitwall
is true - entity.
onground
is false - entity.
detect
is present and HasGroundAhead from the entity.forcetarget
returns false
When the above is fufilled, StopForceMove is called with the basestate
and this DoBehavior cycle is ended early. This is because the game concluded it is no longer possible to move further towards this position.
If we are cleared to continue, there are 4 possible branches this DoBehavior can takes (only the first one that applies is taken checked in this order):
actioncooldown
expired (the main wandering logic)maxtries
is exactly 10- The distance between entity.
startpos
and this position is higher than theteleportradius
ormaxtries
is 20 or above (meaning it went too far away or there's too much failed wander attempts) - The entity is in a
forcemove
If none of the branches above are taken, it means to wait before the next wander:
walkcooldown
is set to 0.0trycount
is set to 0actioncooldown
is decremented by the game's frametime- StopForceMove is called on the entity
actioncooldown
expired (main wandering logic)¶
This branch is essentially the main logic that manages the movement to the next point. It works by attempting to generate a random vector that satifies the wanderradius
and radiuslimit
constraints. The former dictates the range of where the entity can move and the latter dictates the maximum distance the next point can be.
The attempted next vector is 1/3 of a random one between (-wanderradius
, 0.5, -wanderradius
) and (wanderradius
, 0.5, wanderradius
) which is then added to the entity.startpos
as the wanderradius
is relative to it. When generated, the entity.moverotater
is set to look at it regardless if it's accepted or not.
If the vector is less than radiuslimit
away from the current position (meaning it's not too far to move to), then it is accepted which makes the following happen:
- MoveTowards is called on the entity to move to the vector at default everything with the exception that the y component is ignored
- The entity.
detect
is set to LookAt the vector actioncooldown
is set to be random between 1/3 of the frequency and the frequency itselfmaxtries
is set to 0
If the vector is denied, this is where trycount
comes into play as it is incremented here.
The purpose of this field and maxtries
is to regulate the timeout logic. If it reaches 50 or above, actioncooldown
is set to be random between 1/3 of the frequency and the frequency itself once again, trycount
is reset to 0 and maxtries
is incremented. It's maxtries
that can start to be more aggressive if it gets too high (this is outlined in 2 other branches).
maxtries
is exactly 10¶
MoveTowards is called on the entity to move to its startpos
ignoring the y component with a 0.3 multiplier using the default entity.walkstate
and entity.basestate
. Finally, maxtries
is set to 11. This times out the main logic such that if too much failed wander attempts happened, the entity moves back to its startpos
.
Too far or too much failed wander attempts¶
This is basically a warp to force the entity to teleport to its startpos
:
- DeathSmoke particles are played at this position if the entity is
incamera
- The position is set to the entity.
startpos
- The entity.
rigid
velocity is zeroed out - DeathSmoke particles are played at this position if the entity is
incamera
again maxtries
is set to 0actioncooldown
is set to 100.0
The entity is in a forcemove
¶
StopForceMove is called on the entity if walkcooldown
is higher than 60.0 and the entity.rigid
x and z components have a magnitude less than half its speed
.
Whether or not this happens, walkcooldown
is incremented by the game's frametime. This basically forces the entity to at least wander for 60 frames and to stop whenever the entity slows down its movement enough.