If you are handling rotations then you generally want Polar coordinates (which would be using lengthdir) as Cartesian coordinates (x/y) are TERRIBLE for circular things.

However, that still makes no sense to me. lengthdir_x() and lengthdir_y() should be consolidated into 1 function lengthdir() since you aren't actually calculating the x/y of the position you want relative to the origin. Instead you have to calculate the angle when you are already using x/y!

Lengthdir isn't FOR calculating the angle. It is for taking an angle/length pair and converting them into x/y values (aka, converting FROM Polar). If you want to calculate an angle/distance pair from x/y (aka, TO Polar) then use the functions point_distance and point_direction to get the values.

In the case of your train, take a look at what is going on from a coordinate perspective. You want to find a linear offset (aka, the offset from the origin initially). Cartesian coordinates are great for this, polar is a pain. However, then you want to rotate the train which is a circular function. Polar coordinates are great for this, Cartesian is a pain. The goal here is to use Cartesian for the offset, convert it to Polar when you need to rotate, then convert it back to Cartesian to draw it. Whether you use lengthdir or trig functions, you are going to have to do it in some way or another which requires some math.

So to solve the train problem, you can offset easily in Cartesian w/ x/y to get the position of the smoke. You can calculate the Polar representation very easily via point_distance and point_direction between the origin and the point of smoke when not rotated. When you rotate the train, all you have to do is grab these already-calculated Polar versions, add to the angle the rotation of the train then calculate the new position back into Cartesian w/ lengthdir.

So yes, you will still have to do a lot of the math work, there isn't a simple way to do it, sadly. Does this make more sense as to why you would need lengthdir? I mean, you could pre-calculate all the values and hard-code them in, but I feel like that is a pretty tacky way of doing things. Other than that you will have to calculate them on the fly via lengthdir. Lengthdir is just hiding basic trigonometry functions which, if you know trig, you will realize it is required for anything circular.