Enemy¶
An enemy is a non interactable entity that supports ActionBehaviors with the ability to initiate a battle encounter with the player consisting of up to 4 enemies. It also features special logic to handle all of this including cases where it's frozen or dizzy. It is the NPCType with the most exclusive logic available.
Data arrays¶
vectordata: The list of random standard item the enemy can potentially drop in the x components of each element when EntityControl.Death is called on the entity. For the drop to happen on a given element, its y component (if it's not negative) must correspond to a flag slot whose value is true. If any element's y component is -2 however, the first occurence where this is the case will override the drop as it means this will dropped as a key item and it will also bypass the random check performed by EntityControl.Deathbattleids: The array of enemy ids this battle encounter consist of
Additional data¶
limit[0]: Theactivationflagof the key item drop Item object if the y component of any elements ofvectordatais -2. This also serves as the first limit like regular NPCControleventid: If it's not 0, therespawntimervalue whenever the enemy entity.iskillgoes to true
Start / SetUp¶
The arrow is initialised to a new HelpArrow parented to the NPCControl of color cyan with offset (0.75, 0.75, 0.75) with a distance of the entity.freezesize.x * 2.0 clamped from 2.5 to the entity.freezesize.x * 3.5. This prepares the help arrow to render should the enemy gets frozen. Its lockcooldown is set to true on Update as long as freezecooldown is above 0 (the enemy is frozen).
If the eventid is above 0 (we have a respawntimer feature), the entity.alwaysactive is set to true.
Update (Non dummy)¶
The lockcooldown of the arrow is set to true only if freezecooldown is above 0.
Update (Active, main logic, overrides)¶
Only 1 of 3 cases happens here (checked in order):
- This is a frozen enemy (the
freezecooldownhasn't expired yet) - This is a frozen entity of any kind (it has an
icecube, but in practice, this can only happen if an enemy is frozen because it's only on them that Freeze is called) - This is a dizzy enemy (the
dizzytimeis above 0.0)
Additionally, there's logic that happens as part of a standard active update exclusive to an enemy if none of the cases above applied and we aren't trapped.
Frozen enemy¶
If the entity.rigid y velocity is not between -0.1 and 0.1 inclusive, its x and z components are set to the icevel ones. Otherwise, icevel is set to Vector3.zero.
The absolute position is clamped to be within a radius of radiuslimit where the center is at the entity.startpos ignoring the y component.
The following occurs:
- The
pusheris disabled if it was present - The
dizzytimeis set to -1000.0 - The entity.
spinis zeroed out - The
disguisecooldownis set to 120.0 and if adisguiseobjis present, it is disabled and the entity.spriteis disabled - The entity.
emotioncooldownis set to -1.0 templayeris set to the current layer if it was negative. This is done because this also causes the current layer of the enemy to be set to 13 (NoDigGround) which prevents to dig while on theiricecubeand acts as a platform- If the entity doesn't have an
icecube, Freeze is called on the entity. Otherwise, all collisions between thescoland the entity.icecubeare ignored. - If the
boxcolisn't present, it is created non trigger with a size of the entity'sfreezesize - The center of the
boxcolis set to the entity'sfreezeoffset - The
ccolgets disabled - The
boxcolgets enabled - The entity.
heightgets decreased by the game's frametime * 0.075 then clamped from 0.0 to 999.0 - If the
icecooldownis below 100.0, the entity.shakeiceis set to the invert of the entity.inice. Otherwise, the entity.shakeiceis set to false - If the entity is
ongroundand notiniceand we aren't in anicemap, thefreezecooldowngets decreased by framestep - If the entity is
onground, thefreezeaircooldownis set to 0.0. Otherwise, it is decreased by framestep on top of thefreezecooldownbeing set to 0.0 if thefreezeaircooldownwas over 300.0 - entity.
animspeedis seto to 0.0 and entity.overrideanimset to true - If entity.
hasshadowis true, the entity.shadowis disabled
Frozen entity about to be unfrozen¶
It is assumed here that it's an enemy ready to be unfrozen, but this actually checks if entity.icecube exists to detect this.
If the player is present and it is standingon this boxcol, then the player.entity.onground is set to false and its standingon to null. This means if the player was standing on the ice block, the game forces the ground detector and its standingon field to not report to be on it.
BreakIce is called on the entity.
The layer is set to templayer if it wasn't -1 before it is set to -1. This restores the value it had when the entity was frozen previously.
The following occurs:
- entity.
shadowis enabled ifhasshadowwas true - entity.
ccolis enabled - entity.
boxcolis disabled if it was present - entity.
overrideanimis set to false - entity.
oldstateis set to -1 - entity.
oldflyis set from the opposite offlyinganim - entity.
behaviorroutineis in progress, then SetAnim is called with force to true without arguments orfif the NPCControlreturntoheightis true
Dizzy enemy¶
The disguiseobj is disabled if present.
StartBattle is called if all of the following are true:
- It's been more than 20 frames since the
startlife - We aren't in a
pause,minipauseor message - The player is present and the distance between it and this enemey is <= the entity.
ccolradius + 1.1
The following occurs:
- entity.
heightis decreased by - 0.075 clamped from 0.0 to 999.0 - entity.
spinis set to (0,dizzytime/ 5 clamped from 0.0 to 15.0, 0.0) - entity.
overrideanimis set to true - The entity.animstate is set to 11 (Hurt)
- The entity.
emoticonidis set to 1 (? emoticon) with anemoticoncooldownset to 10.0 - StopForceMove is called on the entity if the entity is
ongroundand thetouchcooldownhad expired dizzytimeis decreased according to the game's frametime.- The position is clamped to be within the radius
radiuslimitwhere the center is the entity.startposwithout consideration for the y component
Update (Active, main logic, no overrides)¶
These logic can happen as part of a standard active Update if none of the above cases applied and we aren't trapped.
If the dizzytime is above -999.0, it is set to -1000.0 with the following adjustements being done on the entity which essentially ends the dizzyness:
- enity.
spingets zeroed out - enity.animstate gets set back to entity.
basestate - enity.
overrideanimis set to false
StartBattle is called if all of the following are true:
- It's been more than 20 frames since the
startlife - We aren't in a
pause,minipauseor message - The player is present and the distance between it and this enemey is \<= the entity.
ccolradius + 1.1
Update (Inactive)¶
For every 3 frames, if the entity is in a forcemove, StopForceMove is called on the entity except if it has a SetPath or StealhAI behavior
LateUpdate (Non dummy and entity is incamera)¶
If the eventid is 0 and the entity iskill while we aren't in pause, minipause and inevent, some logic occurs depending on the respawntimer:
- If it is -100.0 or less, it is set to
eventid, - If it is above 0.0, it is decreased by the game's frametime
- If it's negative, but above -100.0, RespawnEnemy is called using the entity
spawnpoint, the entityiskillis set to false andrespawntimeris set to -110.0
LateUpdate (Every 3 frames during RefreshPlayer)¶
When the inrange value changes:
- If the new
inrangeis true, the change is only accepted if both thefreezecooldownand thedizzytimeexpired. If they have, theFindsound is played if the player wasn'tdigging - If the new
inrangeis false and bothfreezecooldownanddizzytimeexpired whilebehaviorroutineisn't in progress:- entity.
emoticonidis set to 1 (?) - entity.
emoticoncooldownis set to 70.0 - StopForceMove is called with the
Idletarget state - The
Lostsound is played - entity.
overrideonlyflipis set to false
- entity.
OnTriggerEnter¶
What happens here depends on the other collider, only one branches is ran and if it doesn't apply, nothing happens.
The other tag is Icecle¶
This does nothing if the entity is digging or its animid is FireKrawler, FireCape, FireWarden or Strider.
- The other gameObject is destroyed if it had a RigidBody
- The
freezecooldownis set to 300.0 with some exceptions: - If it's a
ToeBiterandinternaltransform[0](his boulder) is present, it is destroyed - entity.
rigidx and z velocity are zeroed out - entity.
ongroundis set to true - StopForceBehavior is called
The other tag is BeetleDash or BeetleHorn¶
The BeetleHorn tag only counts here if the player isn't dashing. This does nothing if collisionammount is 0, the entity is dead or digging or the touchcooldown hasn't expired yet.
- TempIgnoreColision is called on the entity with the other collider which ignores all collision between the entity.
ccol/ entity.detectand the other collider for 0.5 seconds - The
Damage0sound is played - If the other collider tag was
BeetleDash, thefreezecooldownis set to 0.0 - A Dizzy coroutine is started for 120.0 frames with force launch with the direction being the normalized direction from this enemy to the player * 5.0
collisionammountis incremented
The other tag is BeeRang¶
This does nothing if collisionammount is 0, the entity is dead or digging or the touchcooldown hasn't expired yet.
- The
WoodHitsound is played on the entity - A Dizzy coroutine is started for 80.0 frames with no pushforce or force launch
collisionammountis incremented
The other collider is owned by the player¶
If we aren't in a minipause, pause or inevent, StartBattle is called TODO: this seems contradictory with the Update logic ???.