Entity

Custom **entities** are implemented by modules through the Nexus to add complex elements to your game. They can be anything ranging from basic mobs, projectiles, or vehicles to physics simulations and living environments.

## Setting up an entity

At its core, a custom entity is just one or more Minecraft entities that have the tags `nexus.entity`, other specific tags, and run specific functions connected to that entity type. All the functions related to a specific entity are located in `<namespace>/functions/entity/<entity name>/`. In the official standard, that folder contains a `main.mcfunction` and the folders `spawn`, `mode`, `animate`, and `assemble`. However, everything inside of the entity's folder is completely up to you.

Function references are from the Template Module. The Spider Brain will be used as the example.

## Spawning an entity

### Spawning the entities

An entity is spawned by the function `<namespace>:entity/<entity name>/spawn/main`. The first thing it does is summon all the relevant entities. Every entity that is spawned has a set of tags to indicate that they are a Nexus entity (`nexus.entity`), an entity belonging to a particular module (`temp.entity`), and another tag to designate the entity type (`temp.entity.type.spider_brain`). Of the entities that are spawned, generally, one is chosen to be the root entity, that is, the entity that executes the ticking function (`nexus.entity.ticking`). This root entity must be included in the entity tag `#nexus:generic/system`. Other entities may be spawned which are given tags to designate which part of the mob they are (`temp.entity.part.leg`). Damage sensor entities can also be spawned, which are invisible mobs. They are usually spawned 1024 blocks into the sky and teleported down to avoid them appearing for one frame. Most of the entities are riding area effect clouds which are air toggled in order to reduce interpolation lag. All entities are spawned with the tag `nexus.entity.target.spawn` so that the set of new entities can be prepared. This tag is removed at the end of the spawning function.

```
temp:entity/spider_brain/spawn/main

```

```
# Summon spider brain

summon marker ~ ~ ~ {               Tags:["nexus.entity","temp.entity","temp.entity.type.spider_brain","temp.entity.part.main"                                  ,"nexus.entity.ticking","nexus.entity.target.spawn","nexus.entity.push"]}
summon area_effect_cloud ~ ~ ~ {    Tags:["nexus.entity","temp.entity","temp.entity.type.spider_brain","temp.entity.part.brain"                                                        ,"nexus.entity.target.spawn","nexus.entity.air_toggle"],Age:-2147483648,Duration:-1,WaitTime:-2147483648,Passengers:[{id:"minecraft:armor_stand",Tags:["nexus.entity","temp.entity","temp.entity.type.spider_brain","temp.entity.part.brain"                                 ,"nexus.entity.target.spawn"],NoGravity:1b,Invisible:1b,DisabledSlots:4144959,ArmorItems:[{},{},{},{id:"minecraft:magenta_terracotta",Count:1b,tag:{CustomModelData:999901}}]}]}
summon area_effect_cloud ~ ~ ~ {    Tags:["nexus.entity","temp.entity","temp.entity.type.spider_brain","temp.entity.part.front_right_leg","temp.entity.part.leg"                       ,"nexus.entity.target.spawn","nexus.entity.air_toggle"],Age:-2147483648,Duration:-1,WaitTime:-2147483648,Passengers:[{id:"minecraft:armor_stand",Tags:["nexus.entity","temp.entity","temp.entity.type.spider_brain","temp.entity.part.front_right_leg","temp.entity.part.leg","nexus.entity.target.spawn"],NoGravity:1b,Invisible:1b,DisabledSlots:4144959,ArmorItems:[{},{},{},{id:"minecraft:magenta_terracotta",Count:1b,tag:{CustomModelData:999902}}]}]}
summon area_effect_cloud ~ ~ ~ {    Tags:["nexus.entity","temp.entity","temp.entity.type.spider_brain","temp.entity.part.front_left_leg" ,"temp.entity.part.leg"                       ,"nexus.entity.target.spawn","nexus.entity.air_toggle"],Age:-2147483648,Duration:-1,WaitTime:-2147483648,Passengers:[{id:"minecraft:armor_stand",Tags:["nexus.entity","temp.entity","temp.entity.type.spider_brain","temp.entity.part.front_left_leg" ,"temp.entity.part.leg","nexus.entity.target.spawn"],NoGravity:1b,Invisible:1b,DisabledSlots:4144959,ArmorItems:[{},{},{},{id:"minecraft:magenta_terracotta",Count:1b,tag:{CustomModelData:999902}}]}]}
summon area_effect_cloud ~ ~ ~ {    Tags:["nexus.entity","temp.entity","temp.entity.type.spider_brain","temp.entity.part.back_right_leg" ,"temp.entity.part.leg"                       ,"nexus.entity.target.spawn","nexus.entity.air_toggle"],Age:-2147483648,Duration:-1,WaitTime:-2147483648,Passengers:[{id:"minecraft:armor_stand",Tags:["nexus.entity","temp.entity","temp.entity.type.spider_brain","temp.entity.part.back_right_leg" ,"temp.entity.part.leg","nexus.entity.target.spawn"],NoGravity:1b,Invisible:1b,DisabledSlots:4144959,ArmorItems:[{},{},{},{id:"minecraft:magenta_terracotta",Count:1b,tag:{CustomModelData:999902}}]}]}
summon area_effect_cloud ~ ~ ~ {    Tags:["nexus.entity","temp.entity","temp.entity.type.spider_brain","temp.entity.part.back_left_leg"  ,"temp.entity.part.leg"                       ,"nexus.entity.target.spawn","nexus.entity.air_toggle"],Age:-2147483648,Duration:-1,WaitTime:-2147483648,Passengers:[{id:"minecraft:armor_stand",Tags:["nexus.entity","temp.entity","temp.entity.type.spider_brain","temp.entity.part.back_left_leg"  ,"temp.entity.part.leg","nexus.entity.target.spawn"],NoGravity:1b,Invisible:1b,DisabledSlots:4144959,ArmorItems:[{},{},{},{id:"minecraft:magenta_terracotta",Count:1b,tag:{CustomModelData:999902}}]}]}
summon area_effect_cloud ~ ~1024 ~ {Tags:["nexus.entity","temp.entity","temp.entity.type.spider_brain","temp.entity.part.damage_sensor"                                                ,"nexus.entity.target.spawn","nexus.entity.air_toggle"],Age:-2147483648,Duration:-1,WaitTime:-2147483648,Passengers:[{id:"minecraft:slime"      ,Tags:["nexus.entity","temp.entity","temp.entity.type.spider_brain","temp.entity.part.damage_sensor"                         ,"nexus.entity.target.spawn","nexus.entity.damage_sensor.event","nexus.entity.foe"],NoAI:1b,Silent:1b,PersistenceRequired:1b,Size:3,DeathLootTable:"",Attributes:[{Base:1024.0d,Name:"minecraft:generic.max_health"}],Health:1024.0f,ActiveEffects:[{Id:14b,ShowParticles:0b,Duration:2147483647}]}]}

# Teleport offset entities

execute positioned ~ ~1024 ~ run teleport @e[type=area_effect_cloud,distance=..8,tag=temp.entity.part.damage_sensor,tag=nexus.entity.target.spawn,limit=1] ~ ~-1024 ~
execute positioned ~ ~1024 ~ run teleport @e[type=slime            ,distance=..8,tag=temp.entity.part.damage_sensor,tag=nexus.entity.target.spawn,limit=1] ~ ~-1024 ~

```

### Assigning IDs

Every custom entity has a unique value on the scoreboard objective `nexus.id` which is used to link the entities together so that one entity does not interfere with another entity. To assign it, add 1 to `#global nexus.id` and push that value onto each of the entities in your rig. Note that the target selectors here have a distance restriction, this is to prevent unnecessary lag by reducing the amount of work each target selector does.

```
temp:entity/spider_brain/spawn/main

```

```
# Assign IDs

scoreboard players add #global nexus.id 1
scoreboard players operation @e[type=#temp:generic/entity,distance=..8,tag=nexus.entity.target.spawn] nexus.id = #global nexus.id

```

### Assigning scores

The root entity executes a function to assign certain scores to it such as position, rotation, motion, various boolean scores, etc. Any damage sensors that exist have their `nexus.health` value initialized to 1024000. The miscellaneous scores at the end have certain specific functionality.

 `nexus.damage_sensor_bool` | Determines if damage sensor mobs with the tag `nexus.entity.damage_sensor.activate` are ticked during activation.

```
temp:entity/spider_brain/spawn/main

```

```
# Assign scores

execute as @e[type=marker,distance=..8,tag=nexus.entity.target.spawn,limit=1] run function temp:entity/spider_brain/spawn/scores

scoreboard players set @e[type=slime,distance=..8,tag=temp.entity.part.damage_sensor,tag=nexus.entity.target.spawn,limit=1] nexus.health 1024000

```

```
temp:entity/spider_brain/spawn/scores

```

```
# Assign position

function nexus:entity/generic/data/get/objective/pos

# Assign rotation

scoreboard players set @s nexus.yaw 0
scoreboard players set @s nexus.pitch 0
scoreboard players set @s nexus.mot_yaw 0
scoreboard players set @s nexus.mot_pitch 0
scoreboard players set @s nexus.poi_yaw 0
scoreboard players set @s nexus.poi_pitch 0

# Assign motion

scoreboard players set @s nexus.mot_x 0
scoreboard players set @s nexus.mot_y 0
scoreboard players set @s nexus.mot_z 0

# Assign miscellaneous values

scoreboard players set @s nexus.id_bool 1
scoreboard players set @s nexus.id_range 8
scoreboard players set @s nexus.tick_dist 64
scoreboard players set @s nexus.vehicle_id_bool 0
scoreboard players set @s nexus.air_toggle_bool 1
scoreboard players set @s nexus.damage_sensor_bool 0

scoreboard players set @s nexus.size 800
scoreboard players set @s nexus.mass 1500
scoreboard players set @s nexus.health 40000

```

### Processing entities

The entities are processed in the spawning function in order that any needed information on them is available right away. They run the function `nexus:entity/process/verify`.

```
temp:entity/spider_brain/spawn/main

```

```
# Process entities

execute as @e[type=#temp:generic/entity,distance=..8,tag=nexus.entity.target.spawn] run function nexus:entity/process/verify
```

### Tag removal

At the end of the spawn function, the tag `nexus.entity.target.spawn` is removed from all the entities to reset for the next time an entity will be spawned.

```
temp:entity/spider_brain/spawn/main

```

```
# Remove target tag

tag @e[type=#temp:generic/entity,distance=..8,tag=temp.entity] remove nexus.entity.target.spawn
```

## Mode system

An entity's mode system functions like a flowchart. One state, or mode, is active at a time, and it moves into another mode based on certain criterion. These criterion could be animation timers, external conditions, health, or any other thing you can imagine. Which mode is active is determined by the score `nexus.mode`.

### Main mode function

The main mode function denullifies the mode value and starts the default mode. After this it checks certain conditions based on the current mode to change the mode. Finally, it ticks the modes themselves. The fakeplayer score `#mode nexus.value` is used when modifying the mode of the entity to prevent condition trampling. For certain entities, additional code is added to the bottom to set `nexus.tick_bool` to 1 if the entity is in mid-air, or to terminate it if it falls into the void.

```
temp:entity/spider_brain/mode/main

```

```
# Denullify mode value

execute unless score @s nexus.mode = @s nexus.mode run function temp:entity/spider_brain/mode/idle/start
execute unless score @s nexus.mode = @s nexus.mode run scoreboard players set @s nexus.mode 0

# Change mode based on preexisting conditions

scoreboard players operation #mode nexus.value = @s nexus.mode

execute if score @s nexus.mode matches 00 run function temp:entity/spider_brain/mode/idle/mode
execute if score @s nexus.mode matches 01 run function temp:entity/spider_brain/mode/walk/mode
execute if score @s nexus.mode matches 02 run function temp:entity/spider_brain/mode/pursue/mode

scoreboard players operation @s nexus.mode = #mode nexus.value

# Run function for specific mode

execute if score @s nexus.mode matches 00 run function temp:entity/spider_brain/mode/idle/main
execute if score @s nexus.mode matches 01 run function temp:entity/spider_brain/mode/walk/main
execute if score @s nexus.mode matches 02 run function temp:entity/spider_brain/mode/pursue/main
execute if score @s nexus.mode matches 03 run function temp:entity/spider_brain/mode/death/main

scoreboard players operation @s nexus.mode = #mode nexus.value

# Set tick boolean

execute store result score @s nexus.tick_bool if score @s nexus.collide_y matches 0..
scoreboard players set @s nexus.tick_bool 1

```

### Start functions

When starting a mode, the score `#mode nexus.value` is set to that mode's numeric ID. Then any other things which need to occur are also done such as starting and stopping animations, setting `nexus.animation` for modes which use a timer, etc.

```
temp:entity/spider_brain/mode/pursue/start

```

```
# Manage animations

function temp:entity/spider_brain/animate/idle/stop
function temp:entity/spider_brain/animate/walk/start

# Set mode value

scoreboard players set #mode nexus.value 2

```

### Mode functions

Mode functions check various conditions to change the active mode before the modes are ticked. This is so that if certain specific things occur that requires the entity start the new mode as soon as possible, it switches modes right away. Examples are managing the health value for damage and death animations, and going between chase and idle modes based on the proximity of players.

```
temp:entity/spider_brain/mode/pursue/mode

```

```
# Start walk mode if there is no one nearby

execute unless entity @a[distance=..40,gamemode=!spectator] run function temp:entity/spider_brain/mode/walk/start

# Manage health

function temp:entity/spider_brain/mode/generic/health/main

```

### Main functions

The main functions in each mode are where the entity's actual processing occurs for its movements, behaviors, animation triggers, etc. Any code which is shared between multiple modes is put in the `generic` mode folder. These systems can get very complex and generally utilize various systems in the Nexus such as motion, entity rotation, trigonometric and vector functions, entity push mechanics, entity damage and player damage, pathfinders, etc.

```
temp:entity/spider_brain/mode/pursue/main

```

```
# Assign point of interest to target

execute as @a[distance=..40,gamemode=!spectator,sort=nearest,limit=1] run function nexus:entity/generic/data/extract/fakeplayer/pos
scoreboard players operation #input_vector_x nexus.value = #entity_x nexus.value
scoreboard players operation #input_vector_y nexus.value = #entity_y nexus.value
scoreboard players operation #input_vector_z nexus.value = #entity_z nexus.value
scoreboard players add #input_vector_y nexus.value 1000

# Get rotation to target

scoreboard players operation #input_vector_x nexus.value -= @s nexus.x
scoreboard players operation #input_vector_y nexus.value -= @s nexus.y
scoreboard players operation #input_vector_z nexus.value -= @s nexus.z
scoreboard players remove #input_vector_y nexus.value 1000
scoreboard players set #scale_factor nexus.value 10
function nexus:generic/vector/to_gimbal/3d
scoreboard players operation #yaw nexus.value = #output_yaw nexus.value
scoreboard players operation #pitch nexus.value = #output_pitch nexus.value
scoreboard players operation #pitch nexus.value /= #3 nexus.value

# Modify rotation

scoreboard players set #rotation_acceleration nexus.value 50
function temp:entity/spider_brain/mode/generic/rotation

# Modify motion

scoreboard players set #speed temp.value 350
execute if score @s nexus.mot_y matches -1000.. run function temp:entity/spider_brain/mode/generic/walk

# Apply motion

function temp:entity/spider_brain/mode/generic/motion

# Attack players

execute if entity @s[tag=!temp.entity.animate.attack] if entity @a[distance=..3,gamemode=!spectator] run function temp:entity/spider_brain/animate/attack/start

```

## Animations

An entity's animation system sets various values associated with the entity's bones such as position and rotation relative to the entity's actual position. It is used to play walking animations, attack animations, damage animations, death animations, etc. Unlike the entity's mode system, which only has one active mode at a time, an entity can play any number of animations at once, and has a special tag and set of scores associated with each animation such as a timer and influence value. Animations have a start function, a stop function, and a main ticking function.

### Main animation function

The main animation function initializes all the parameters, optionally adjusts them for the rotation of the entity, and ticks the animations based on which tags it has.

```
temp:entity/spider_brain/animate/main

```

```
# Reset positions and rotations of the bones

scoreboard players set #brain_position_x temp.value 0
scoreboard players set #brain_position_y temp.value 0
scoreboard players set #brain_position_z temp.value 0
scoreboard players set #brain_rotation_x temp.value 0
scoreboard players set #brain_rotation_y temp.value 0
scoreboard players set #brain_rotation_z temp.value 0

scoreboard players set #front_right_leg_position_x temp.value 0
scoreboard players set #front_right_leg_position_y temp.value 0
scoreboard players set #front_right_leg_position_z temp.value 0
scoreboard players set #front_right_leg_rotation_x temp.value 0
scoreboard players set #front_right_leg_rotation_y temp.value 450
scoreboard players set #front_right_leg_rotation_z temp.value 0

scoreboard players set #front_left_leg_position_x temp.value 0
scoreboard players set #front_left_leg_position_y temp.value 0
scoreboard players set #front_left_leg_position_z temp.value 0
scoreboard players set #front_left_leg_rotation_x temp.value 0
scoreboard players set #front_left_leg_rotation_y temp.value -450
scoreboard players set #front_left_leg_rotation_z temp.value 0

scoreboard players set #back_right_leg_position_x temp.value 0
scoreboard players set #back_right_leg_position_y temp.value 0
scoreboard players set #back_right_leg_position_z temp.value 0
scoreboard players set #back_right_leg_rotation_x temp.value 0
scoreboard players set #back_right_leg_rotation_y temp.value 1350
scoreboard players set #back_right_leg_rotation_z temp.value 0

scoreboard players set #back_left_leg_position_x temp.value 0
scoreboard players set #back_left_leg_position_y temp.value 0
scoreboard players set #back_left_leg_position_z temp.value 0
scoreboard players set #back_left_leg_rotation_x temp.value 0
scoreboard players set #back_left_leg_rotation_y temp.value -1350
scoreboard players set #back_left_leg_rotation_z temp.value 0

# Modify values based on rotation of entity

scoreboard players operation #brain_rotation_y temp.value += @s nexus.yaw
scoreboard players operation #brain_rotation_x temp.value += @s nexus.pitch
scoreboard players operation #front_right_leg_rotation_y temp.value += @s nexus.yaw
scoreboard players operation #front_left_leg_rotation_y temp.value += @s nexus.yaw
scoreboard players operation #back_right_leg_rotation_y temp.value += @s nexus.yaw
scoreboard players operation #back_left_leg_rotation_y temp.value += @s nexus.yaw

# Play animations

execute if entity @s[tag=temp.entity.animate.idle  ] run function temp:entity/spider_brain/animate/idle/main
execute if entity @s[tag=temp.entity.animate.walk  ] run function temp:entity/spider_brain/animate/walk/main
execute if entity @s[tag=temp.entity.animate.jump  ] run function temp:entity/spider_brain/animate/jump/main
execute if entity @s[tag=temp.entity.animate.land  ] run function temp:entity/spider_brain/animate/land/main
execute if entity @s[tag=temp.entity.animate.attack] run function temp:entity/spider_brain/animate/attack/main
execute if entity @s[tag=temp.entity.animate.damage] run function temp:entity/spider_brain/animate/damage/main
execute if entity @s[tag=temp.entity.animate.death ] run function temp:entity/spider_brain/animate/death/main
```

### Start function

The start function of an animation adds the tag associated with it and resets any scores associated with it as well. It will only initialize the parameters if the animation isn't already playing to avoid discontinuous jumps in the animation. The animation timer is the amount of time since the animation has begun. It does not have to necessarily count ticks but can count up faster depending on the entity's speed. The influence value is a timer as well, but it stops at a predefined value. It is used to compute an influence factor from 0 to 1000 (representing 0 to 1) which affects how much influence this animation has over the final state of the entity's bones. 0 means no influence, 500 (0.5) means half of what this animation contributes is used, and 1000 (1) means all of it is used. This is so that animations can ease in and out instead of instantly starting and stopping. When the influence timer starts, the influence factor is 0; when the influence timer reaches its maximum value, the influence factor is 1000 (1).

```
temp:entity/spider_brain/animate/walk/start

```

```
# Set influence value

scoreboard players set @s[tag=!temp.entity.animate.walk] nexus.anim_infl_01 1

# Reset timer

scoreboard players set @s[tag=!temp.entity.animate.walk] nexus.anim_time_01 0

# Add tag

tag @s add temp.entity.animate.walk
```

### Stop function

The stop function of an animation generally sets the influence value to a negative value. In the main function of the animation, the influence value is constantly ticking upwards and the influence factor is computed from the *absolute value* of the influence timer, which means flipping its sign does not create a discontinuous jump in the influence factor. It ticking up has the effect of easing out of the influence of the animation until it reaches 0, at which point it has no effect, then the animation stops. Some animations don't have a stop function such as death animations, jump animations, swing animations, etc. These animations go off for a set amount of time and then stop automatically, while animations that loop have stop functions. They don't compute the influence factor nor do they apply it since they play a single, discrete animation.

```
temp:entity/spider_brain/animate/walk/stop

```

```
# Set influence value

scoreboard players set @s[tag=temp.entity.animate.walk] nexus.anim_infl_01 -10
```

### Main function

The main function of an animation computes the parameters mathematically, multiplies them by the influence factor, and adds them to the total parameters which affect how the entity is assembled.

#### Computing influence

It begins by incrementing the influence value and computing the influence factor from it. It uses missed ticks to increment it, and smoothstep to compute the factor from the value. The influence value is stored in `nexus.anim_infl_<num>` while the influence factor is stored in `#influence temp.value`.

```
temp:entity/spider_brain/animate/walk/main

```

```
# Calculate influence

scoreboard players operation #previous nexus.anim_infl_01 = @s nexus.anim_infl_01
scoreboard players operation @s nexus.anim_infl_01 += #missed_ticks nexus.value
execute if score #previous nexus.anim_infl_01 matches 1..10 run scoreboard players set @s[scores={nexus.anim_infl_01=10..}] nexus.anim_infl_01 10
execute if score #previous nexus.anim_infl_01 matches ..000 run scoreboard players set @s[scores={nexus.anim_infl_01=0.. }] nexus.anim_infl_01 0

scoreboard players operation #input nexus.value = @s nexus.anim_infl_01
execute if score #input nexus.value matches ..-1 run scoreboard players operation #input nexus.value *= #-1 nexus.value
scoreboard players operation #input nexus.value *= #100 nexus.value
function nexus:generic/interpolation/smoothstep
scoreboard players operation #influence temp.value = #output nexus.value
```

#### Increment timer

Next it assigns its velocity and default velocity and increments the animation timer. The velocity values are often used to change the intensity of an animation depending on how fast the entity is moving. For instance the stride length and frequency of a walking animation.

```
temp:entity/spider_brain/animate/walk/main

```

```
# Increment timer

scoreboard players operation #velocity temp.value = @s nexus.velocity
scoreboard players operation #velocity temp.value *= #missed_ticks nexus.value

scoreboard players operation #previous nexus.anim_time_01 = @s nexus.anim_time_01
scoreboard players operation @s nexus.anim_time_01 += #velocity temp.value

scoreboard players set #default_velocity temp.value 250
```

#### Playing sounds

In a walking animation, generally you would have a footstep sound play. You can compare the current timer value to the previous timer value and scale them down to see when it crosses over a certain boundary. This has the same effect as playing a sound every *n* ticks, except here, *n* is based on the entity's speed.

```
temp:entity/spider_brain/animate/walk/main

```

```
# Play sounds

scoreboard players operation #math_00 temp.value = @s nexus.anim_time_01
scoreboard players operation #math_01 temp.value = #previous nexus.anim_time_01
scoreboard players operation #math_00 temp.value /= #default_velocity temp.value
scoreboard players operation #math_01 temp.value /= #default_velocity temp.value
scoreboard players operation #math_00 temp.value /= #5 nexus.value
scoreboard players operation #math_01 temp.value /= #5 nexus.value

execute unless score #math_00 temp.value = #math_01 temp.value run playsound minecraft:entity.goat.ram_impact hostile @a
```

#### Using sinewaves to compute parameters

After this, it begins computing the parameters for the bones themselves, which are composed mostly of sinewaves. The frequency and magnitude of the sinewaves are assigned and the output of the sinewave is fed directly into the parameters of the bone. Often the outputs of the sinewaves are fed through the limiter function, which changes the shape of the sinewave and makes the inclines steeper and the peaks and troughs flatter. Additionally, the keyframe system can be used if you are making a complex animation that needs to pass through specific keyframes at specific points in time.

This part of the animation controls the up and down bobbing of the brain:

```
temp:entity/spider_brain/animate/walk/main

```

```
# Apply quarter-second cosine wave to bones

scoreboard players operation #input nexus.value = @s nexus.anim_time_01
scoreboard players operation #input nexus.value *= #720 nexus.value
scoreboard players operation #input nexus.value /= #default_velocity temp.value
function nexus:generic/trigonometry/cosine

scoreboard players set #input nexus.value 1000
scoreboard players operation #input nexus.value -= #output nexus.value
scoreboard players operation #input nexus.value *= @s nexus.velocity
scoreboard players operation #input nexus.value /= #default_velocity temp.value
scoreboard players set #amplitude nexus.value 1000
scoreboard players set #rate nexus.value 4000
function nexus:generic/limiter

scoreboard players operation #output nexus.value /= #4 nexus.value
scoreboard players operation #output nexus.value *= #-1 nexus.value
scoreboard players operation #animate_brain_position_y temp.value = #output nexus.value
scoreboard players operation #output nexus.value /= #4 nexus.value
scoreboard players operation #animate_brain_rotation_x temp.value = #output nexus.value
```

#### Parameter merging

Once the values are computed, it multiplies the temporary values (denoted with the prefix `#animate_`) by the influence factor and adds them into the main values.

```
temp:entity/spider_brain/animate/walk/main

```

```
# Merge animation with native values

scoreboard players operation #animate_brain_position_y temp.value *= #influence temp.value
scoreboard players operation #animate_brain_position_y temp.value /= #1000 nexus.value
scoreboard players operation #brain_position_y temp.value += #animate_brain_position_y temp.value

scoreboard players operation #animate_brain_rotation_x temp.value *= #influence temp.value
scoreboard players operation #animate_brain_rotation_x temp.value /= #1000 nexus.value
scoreboard players operation #brain_rotation_x temp.value += #animate_brain_rotation_x temp.value
```

#### Animation end

Finally, when the influence factor is detected to be 0, it will end the animation by removing the tag. Certain animations like jumping, attacking, death, etc. stop when the animation timer exceeds a certain value.

```
temp:entity/spider_brain/animate/walk/main

```

```
# Stop animation when influence timer is 0

execute if score #influence temp.value matches 0 run tag @s remove temp.entity.animate.walk
```

## Assembly

The assembly function is the final stage of the entity's ticking process. It is where the entity takes all of the parameters from the animations and puts all the bones into place.

### Main bone position

Most entities have a bone hierarchy, i.e. the legs go where the body goes. The first thing which is computed is the location of the main bone, which in the case of the Spider Brain, is the brain itself. Any offsets on the X or Z axes need to be modified by the entity's yaw value so that the offsets follow its rotation. The bone offset value, 1912 (1.912 blocks), denotes the distance between the head pivot of a large armor stand and the position of the area effect cloud that the armor stand is riding. The bone offset is applied at the end to derive the true position of the entities since the position which is computed is of the pivots.

```
temp:entity/spider_brain/assemble/main

```

```
# Set body bone position

scoreboard players set #bone_offset temp.value 1912

scoreboard players operation #input_vector_x nexus.value = #brain_position_x temp.value
scoreboard players operation #input_vector_z nexus.value = #brain_position_z temp.value
scoreboard players operation #input_yaw nexus.value = @s nexus.yaw
function nexus:generic/vector/rotate/2d/yaw
scoreboard players operation #brain_position_x temp.value = #output_vector_x nexus.value
scoreboard players operation #brain_position_z temp.value = #output_vector_z nexus.value

scoreboard players add #brain_position_y temp.value 1200
scoreboard players operation #brain_position_x temp.value += @s nexus.x
scoreboard players operation #brain_position_y temp.value += @s nexus.y
scoreboard players operation #brain_position_z temp.value += @s nexus.z

```

### Main bone orientation matrix

An orientation matrix is computed from the gimbals of the main bone in order to place the bones where they go. This allows an entity to have arms and legs and not have them become dislocated regardless of how the body is oriented.

```
temp:entity/spider_brain/assemble/main

```

```
# Compute body orientation matrix

scoreboard players set #input_angle_x nexus.value 0
scoreboard players operation #input_angle_y nexus.value = #brain_rotation_y temp.value
function nexus:generic/matrix/from_gimbal/3d/yaw_pitch
scoreboard players operation #input_matrix_x_x nexus.value = #output_matrix_x_x nexus.value
scoreboard players operation #input_matrix_x_y nexus.value = #output_matrix_x_y nexus.value
scoreboard players operation #input_matrix_x_z nexus.value = #output_matrix_x_z nexus.value
scoreboard players operation #input_matrix_y_x nexus.value = #output_matrix_y_x nexus.value
scoreboard players operation #input_matrix_y_y nexus.value = #output_matrix_y_y nexus.value
scoreboard players operation #input_matrix_y_z nexus.value = #output_matrix_y_z nexus.value
scoreboard players operation #input_matrix_z_x nexus.value = #output_matrix_z_x nexus.value
scoreboard players operation #input_matrix_z_y nexus.value = #output_matrix_z_y nexus.value
scoreboard players operation #input_matrix_z_z nexus.value = #output_matrix_z_z nexus.value
```

### Transform bone positions

The child bones of the entity first assign their position relative to the main bone, then feed that vector through a linear transformation using the main bone's orientation matrix to get the final position of that bone relative to the entity.

```
temp:entity/spider_brain/assemble/main

```

```
# Offset bone positions from body

scoreboard players remove #front_right_leg_position_x temp.value 300
scoreboard players add #front_right_leg_position_z temp.value 300

scoreboard players operation #input_vector_x nexus.value = #front_right_leg_position_x temp.value
scoreboard players operation #input_vector_y nexus.value = #front_right_leg_position_y temp.value
scoreboard players operation #input_vector_z nexus.value = #front_right_leg_position_z temp.value
function nexus:generic/matrix/transform/direct/3d
scoreboard players operation #front_right_leg_position_x temp.value = #output_vector_x nexus.value
scoreboard players operation #front_right_leg_position_y temp.value = #output_vector_y nexus.value
scoreboard players operation #front_right_leg_position_z temp.value = #output_vector_z nexus.value
```

### Offset bone positions

The bone positions are then offset using the absolute position of the main bone, and then shifted downward using the bone offset to get the final position of each of the entities.

```
temp:entity/spider_brain/assemble/main

```

```
# Offset everything from the body position

scoreboard players operation #front_right_leg_position_x temp.value += #brain_position_x temp.value
scoreboard players operation #front_right_leg_position_y temp.value += #brain_position_y temp.value
scoreboard players operation #front_right_leg_position_z temp.value += #brain_position_z temp.value
scoreboard players operation #front_left_leg_position_x temp.value += #brain_position_x temp.value
scoreboard players operation #front_left_leg_position_y temp.value += #brain_position_y temp.value
scoreboard players operation #front_left_leg_position_z temp.value += #brain_position_z temp.value
scoreboard players operation #back_right_leg_position_x temp.value += #brain_position_x temp.value
scoreboard players operation #back_right_leg_position_y temp.value += #brain_position_y temp.value
scoreboard players operation #back_right_leg_position_z temp.value += #brain_position_z temp.value
scoreboard players operation #back_left_leg_position_x temp.value += #brain_position_x temp.value
scoreboard players operation #back_left_leg_position_y temp.value += #brain_position_y temp.value
scoreboard players operation #back_left_leg_position_z temp.value += #brain_position_z temp.value

scoreboard players operation #brain_position_y temp.value -= #bone_offset temp.value
scoreboard players operation #front_right_leg_position_y temp.value -= #bone_offset temp.value
scoreboard players operation #front_left_leg_position_y temp.value -= #bone_offset temp.value
scoreboard players operation #back_right_leg_position_y temp.value -= #bone_offset temp.value
scoreboard players operation #back_left_leg_position_y temp.value -= #bone_offset temp.value
```

### Writing data to entities

Lastly, the entities are put into position. The area effect clouds have their position assigned, and the armor stands have their head pose assigned.

```
temp:entity/spider_brain/assemble/main

```

```
# Push data to entities

data modify storage temp:data tag set value {Pos:[0.0d,0.0d,0.0d],Pose:{Head:[0.0f,0.0f,0.0f]}}
execute store result storage temp:data tag.Pos[0] double 0.001000 run scoreboard players get #brain_position_x temp.value
execute store result storage temp:data tag.Pos[1] double 0.001000 run scoreboard players get #brain_position_y temp.value
execute store result storage temp:data tag.Pos[2] double 0.001000 run scoreboard players get #brain_position_z temp.value
execute store result storage temp:data tag.Pose.Head[0] float 0.1 run scoreboard players get #brain_rotation_x temp.value
execute store result storage temp:data tag.Pose.Head[1] float 0.1 run scoreboard players get #brain_rotation_y temp.value
execute store result storage temp:data tag.Pose.Head[2] float 0.1 run scoreboard players get #brain_rotation_z temp.value
data modify entity @e[type=area_effect_cloud,distance=..8,tag=temp.entity.part.brain,tag=nexus.entity.target,limit=1] Pos set from storage temp:data tag.Pos
data modify entity @e[type=armor_stand      ,distance=..8,tag=temp.entity.part.brain,tag=nexus.entity.target,limit=1] Pose.Head set from storage temp:data tag.Pose.Head

...

execute as @e[type=area_effect_cloud,distance=..8,tag=nexus.entity.target] at @s run teleport @s ~ ~ ~
teleport @e[type=area_effect_cloud,distance=..8,tag=temp.entity.part.damage_sensor,tag=nexus.entity.target,limit=1] ~ ~-0.375 ~
```

## History

 1.8.0
 1.8.6
`nexus.anim_t_##` ==> `nexus.anim_time_##`
`nexus.anim_i_##` ==> `nexus.anim_infl_##`

## See also

* Motion
* Keyframes
* Module
* Missed ticks
* Generic functions
* Concepts