X and Y position are stored at 0x3c and 0x34 in the nightopian's data, respectively. The X and Y velocity are stored at 0x24 and 0x28. A nightopian's default speed is stored in its DNA in the higher nibble of 0x43, and is also stored at offset 0x2C multiplied by 0x4000 and may be negated depending on whether the nightopian is facing left or right. Each flight pattern is basically a looping animation with 0x100/256 frames. The current frame is stored as a single byte in the nightopian's data, which I'll refer to as the flight index.
Flight pattern 0 is simple. It sets a pian's X velocity to its default speed.
Flight pattern 7 sets both X and Y velocity to half of the nightopian's default speed, negating Y velocity if the flight index is < 0x80/128. This makes the nightopian fly in zigzags.
Flight pattern 2 is unusual. It multiplies the nightopian's speed with 0x10000 minus the flight index shifted left by 1 byte. It then stores this value as the nightopian's X velocity. The result is not always zero, but it is so small that it doesn't change the nightopian's position. In addition, if the nightopian's byte 0xE has its lowest bit set, meaning the nightopian is stationary, it moves a negative number into the nightopian's Y velocity. This causes it to move upwards.Â
The other flight patterns use a byte stored at offset 0x10 in the nightopian's data to index into a precalculated table of sine and cosine values which are then multiplied by its default speed to become its new Y and X velocity.
Flight pattern 1 does the above operation and ensures that the cosine value does not become negative. This means the nightopian moves forward in a wave made of alternating top and bottom semicircles instead of moving backwards and completing the circle.
Flight pattern 3 does pattern 0's operation unless the flight index is 0xC0/192 or above, in which case it performs pattern 1's operation with the index decremented by 0xC0, then multiplied by 4 before indexing into the sine/cosine values. This results in the pian flying straight for 3/4ths of the time, and in the remaining 1/4th making a small complete circle in its flight path. The direction of the loops depends on which way the nightopian is facing. Traveling left, the loops will point upwards, traveling right, they face downwards.
Flight pattern 4 is similar to 3, but does two loops during one cycle. It flies straight for 1/4th, makes a circle for the next 1/4th, flies straight again for 1/4th, then makes another circle in the opposite direction for the last 1/4th. The opposite circle is done by negating the index before calling the sine/cosine function. This function treats the index as an unsigned byte which effectively flips the bits, counting down from 0xFF instead of up from 0x0. The result is the nightopian alternating between making loops above and below its flight path.
Flight pattern 5 is similar to 1, but ensures both the sine and cosine values are positive. This results in the nightopian repeating a series of upwards or downwards facing semicircles, depending on which direction it is flying. The orientation of the circles changes with direction because the game multiplies the speed (which can be positive or negative) with both the X and Y velocity returned by this function.
Flight pattern 6 is similar to 4, but it ensures the sine value is positive (for the 2nd 4th) or negative (for the 4th 4th) causing the nightopian to fly straight, travel up a right and left semicircle, fly straight again, and travel down a right and left semicircle.
In-game, it is only possible for a-life to have 0 or 1 as their first flight pattern. Pattern 0 overwrites the X velocity calculated by the second pattern with a constant value, which has the effect of "flattening out" any backwards motion such as the circles in patterns 3 and 4 and the backwards semicircles in 6. Pattern 1 overwrites both the X and Y velocity of the second pattern. This means that it's not possible to observe patterns 3, 4, and 6 as they were intended without hacking.