SUB_NormalizeAngles is a handy bit of code for rotating entities. It maps a vector of angles so that each has its unique value between 0 and 360 (the range that we usually deal with angles in). A subtle bug has been causing me problems, so I will now expose it.

Here is the original code

vector ( vector ang ) SUB_NormalizeAngles = { while( ang_x > 360 ) ang_x = ang_x - 360; while( ang_x < 0 ) ang_x = ang_x + 360; while( ang_y > 360 ) ang_y = ang_y - 360; while( ang_y < 0 ) ang_y = ang_y + 360; while( ang_z > 360 ) ang_z = ang_z - 360; while( ang_z < 0 ) ang_z = ang_z + 360; return ang; };

Here is the fixed version

vector ( vector ang ) SUB_NormalizeAngles = { while( ang_x >= 360 ) ang_x = ang_x - 360; while( ang_x < 0 ) ang_x = ang_x + 360; while( ang_y >= 360 ) ang_y = ang_y - 360; while( ang_y < 0 ) ang_y = ang_y + 360; while( ang_z >= 360 ) ang_z = ang_z - 360; while( ang_z < 0 ) ang_z = ang_z + 360; return ang; };

Did you catch it?

The edge case is a well known class of bug. What makes this one interesting is that even a lot of the time when you are dealing with the edge case it doesn’t matter that this function is bugged. There will still be problems around the cutoff between 0 and 360 even after the fix. The value of changing the function like this is that now if two angles are in truth the same facing, the function will return the same value. Previously ‘0 0 0’ and ‘0 360 0’ would both be returned unchanged, even though those two vectors are equal as angles.

Does this mean the new Quoth will have a func_rotate_train that can do a loop without taking the long way back to 0 0 0?

Yes, that’s exactly the difficulty I was having when I found it.

Thank You!! I did not like having to build around that bug.