RollingRock¶
A rolling rock that either appears and rolls on its own or is shot from a canon. The target direction, velocity, radius, rotation, spawn timing and minimum y position limit are all configurable with the option to only have the rock roll once it hits the ground and an option to only activate the rock when another NPCControl hit
value is true.
Data Arrays¶
data[0]
: If 1, the rock starts rolling when it hits the ground with some particles, sound effect and a shake screen. If 0, the rock always rolls when theactioncooldown
expires. Any other value is considered invalid and will cause illogical behaviorsdata[2]
: 1 if a canon should shoot the rock, no canon is setup otherwisedata[3]
1: The NPCControl at the map entity id whosehit
value determines if the rock is considered active. A positive number means to test for it being true while a negative one test for it being false using the absolute value as the map entity id. This is optional, the rolling rocks remains active if it doesn't exist or is -1vectordata[0]
: The target vector of the rock which determines towards where it will start rolling and its x/z velocityvectordata[1].x
: The minimum y position allowed of the rock before respawning itvectordata[1].y
: The radius of the rock. Defaults to 3.0 if it was less than 0.1vectordata[1].z
: Theactioncooldown
of the canon which is the time before shooting if applicable or the time it takes to respawn it if we aren't shooting from a canonvectordata[2]
: The rotation angles to apply each update where the rock rolls
1: NOTE: a caveat with this value is it is only possible to test for the value being false on the id 0, it is NOT possible to test it being true. Also, it is NOT possible to test for id 1 being false because -1 is a special value to opt out of this feature and that meaning takes priority
Setup¶
- entity.
onground
is set to false - entity.
alwaysactive
is set to true - The entity.
ccol
is enabled overriding the default Start logic for objects - If
vectordata[1].y
is less than 0.1, it is set to 3.0 - The
scol
center is set to (0.0,vectordata[1].y
, 0.0) - The entity.
model
's local scale is set to Vector3.one *vectordata[1].y
- The entity.
model
's local position is set to (0.0,vectordata[1].y
, 0.0) - The
scol
radius is set tovectordata[1].y
- The
jumpheight
is halved internaldata
is initialised to a new array with 2 elements being 0.0 and 100.0- If
data[2]
is 1, see the section below about setting up shooting from a canon - All collision between the entity.
ccol
and the player.entity.ccol
are ignored - The ground detector is recreated completely via CreateFeet
When we are shooting from a canon (data[2]
is 1)¶
actioncooldown
is set tovectordata[1].z
internaltransform
is initialised to have 2 transforms:- The first is an instance of the
Prefabs/Objects/Cannon
prefab childed to the current map with a scale of Vector3.one * (vectordata[1].y
/ 2.0), a position of the entity.startpos
and with angles incremented by (0f, 0f, -90f). - The second is the first child from the root of the canon instance (the cylinder nozzle)
- The first is an instance of the
- The canon is set to rotate its y angle (not its x and z) to face the canon's current position +
vectordata[0]
. This aligns it horizontally to its target - The entity.
rigid
is locked via LockRigid(true) - The position of the the rolling rock is set to (0.0, 999.0, 0.0) which is offscreen in the air
Update¶
If data[2]
is present and 1 (we are shooting from a canon), a complete logic is performed to scale internaltransform[1]
(the nozzle of the canon) at different points in the shooting and to update the actioncooldown
. No matter if this applies or not, the main logic section can apply after.
Canon nozzle scaling¶
This section involves 2 countdown timer: internaldata[0]
and actioncooldown
. The former is reset to internaldata[1]
(100.0) after shooting and represents the interval before preparing to shoot again while the latter represents the interval before respawning the rock. They both interact with each other, but this section still remains independant of what happens after when applicable.
On the first update, internaldata[0]
is expired, but not actioncooldown
which will cause this object to be continuously positioned offscreen (0.0, 999.0, 0.0). If this happens while the data[3]
hit
check condition is fufilled or not applicable, this is where the actioncooldown
is decremented by the game's frametime. On top of this, if less than 60.0 frames is left on the actioncooldown
, the local scale of the nozzle is set to a lerp from the existing one to (0.5, 1.25, 1.25) with a factor of the 1/20 of the game's frametime. This scale signals that the canon is about to shoot by warping it mostly from the side for a brief moment.
Eventually, the actioncooldown
expires and this is detected by going below 0.0, but remaining above -1000.0. When this happens:
- The entity.
rigid
gets its velocity zeroed out - This object's position is set to the entity.
startpos
+ the normalized version ofvectordata[0]
*vectordata[1].y
+ Vector3.up * 0.25 (this places the rock back to its original position) - LockRigid(false) is called on the entity to unlock its
rigid
- The
actioncooldown
is set to -1100.0 which prevents it from entering this code block until the next shooting internaldata[0]
is set tointernaldata[1]
(100.0)- The nozzle of the canon has its local scale set to (1.25, 0.75, 0.75) which warps the canon on the opposite direction than when set earlier the instant the shooting happens
As a result of this, actioncooldown
is frozen below -1000.0, but this causes on each further updates to have the local scale of the canon nozzle to be set to a lerp between the existing one and Vector3.one with a factor of a 1/20 of the game's frametime.
From there internaldata[0]
hasn't expired which causes further updates to decrement it by the game's frametime. Eventually, it will expire which means we are back to where we started on the first update and the cycle repeats itself.
Overall, it means that:
- Every time
actioncooldown
has 60.0 or less left, the scale of the nozzle is warped to be a bit smaller horizontally - When
actioncooldown
expires, the shooting logic happens with a position set and a scale of the nozzle set to be larger horizontally - The nozzle scale slowly gets back to normal
- After 100.0 frames passed, the logic resets back to where it started with a fresh
actioncooldown
This repeates over and over until the data[3]
check is violated which freezes the actioncooldown
and prevents this section from doing any logic until the check is fufilled again.
Main logic¶
After the section above if applicable, a check is done if the rock should have its hit
set to true. It is set to true if any of the following conditions is true:
- We aren't shooting from a canon and
data[0]
is 0 or the entity isonground
- We are shooting from a canon and
actioncooldown
expired.
If we are setting hit
to true, a special case happens when if it was false before and data[0]
is 1. In that case, the impactsmoke
particle is played at this object position and if the distance between the player and this object is less than 15.0, the Thud
sound is played followed by a ShakeScreen using the vector (0.1, 0.35) without reset.
hit
value handling¶
From there, what happens depends on the value of hit
.
If it is true:
- The x and z components of the entity.
rigid
velocity are set tovectordata[0].x
andvectordata[0].z
respectively - The entity.
model
angles are incremented byvectordata[2]
* framestep - If
data[3]
is present and the NPCControl at the map entity id of its value has itshit
set to true, then PlaySound is called with theRollingRock
clip looped. Ifdata[3]
is present, but thehit
check is violated, the entity.sound
is stopped. NOTE: see the note on the data arrays section above for a caveat with this
If hit
is false, the entity.sound
is stopped as long as it is playing, it exists and the clip is still RollingRock
. The entity.sound
is then set to no longer loop.
Common steps¶
Regardless of everything, if this object's y position is below vectordata[1].x
WarpRock is called (see the section below for details).
OnTriggerStay¶
This does nothing if we are in a pause
, minipause
or inevent
and that if a battle is in progress that it's not inevent
.
If the other gameObject is the player and it's not digging
, the event 116 (Getting crushed by a RollingRock
) is called with this as the caller.
Otherwise, if the other gameObject tag is RockLimit
, BreakRock is called.
OnCollisionEnter¶
If the other gameObject is an Object NPCControl of type BreakableRock, BreakRock is called on the other's NPCControl.
BreakRock¶
This is a public method that has logic specific to this object type.
- If the player is less than 15.0 away from this object and the
RockBreak
sound wasn't playing, it is played at 0.5 volume - entity.
sound
is stopped - If the player is less than 15.0 away from the rolling rock, a ShakeScreen happen with 0.1 as the amount for 0.35 seconds without reset
- A
Prefabs/Objects/CrackRockBreak
prefab instantiated at the rolling rock position with its CrackRockBreak's initialcolor set to the rolling rock material color and a scale of Vector3.one * half ofvectordata[1].y
- entity.
rigid
has its velocity zeroed out - entity.
onground
is set to false - If
data[2]
is 1 (we are shooting from a canon) the following occurs (if not, WarpRock is called instead, see the section below for details):- The rolling rock position is offscreen in the air at (0.0, 999.0, 0.0)
- The entity.
rigid
is locked via LockRigid(true) actioncooldown
is reset tovectordata[1].z
WarpRock¶
This is a private method specific to this object type that prepares to respawn the rock.
If we are shooting from a canon (data[2]
is 1), LockRigid(true) is called on the entity and the actioncooldown
is reset to vectordata[1].z
.
If we aren't shooting from a canon:
- This object's transform is set to (0.0, 999.0, 0.0) which is offscreen in the air
- LatePos is called which sets the position of the entity to its
startpos
invectordata[1].z
seconds. hit
is set to false- The entity.
rigid
velocity is zeroed out - The entity.
onground
is set to false
All of this prepares the next rock to spawn.
Hazards.OnObjectStay¶
If the NPCControl passed has this type, it returns true which allows it to stay in collision with the Hazards.