Also, for sign(x), if you're dealing with integers or at least a known level of granularity you can use round() and 'jiggle' it a bit: sign([[@{x}]]) = [[round(@{x}/abs(@{x}+0.001))]] If you're dealing with fractional values but you don't mind losing bits that are less than 0.00001: sign([[@{x}]]) = [[round(@{x}*10000/abs(@{x}*10000+0.001))]] That way you get 0 on the dot when x=0, and it will actually get more precise the farther from 0 that X gets, so you don't have to worry about edge cases. Obviously if you can't afford to pick a granularity then this won't work but it's a small price to pay! This provides us with a way to convert between Size bonus (+8, +4, +2, +1, +0, -1, -2, -4, -8) and Fly bonus (+8, +6, +4, +2, 0, -2, -4, -6, -8): (round((@{size}+8)/abs((@{size}+8)+0.001)) + round((@{size}+4)/abs((@{size}+4)+0.001)) + round((@{size}+2)/abs((@{size}+2)+0.001)) + round((@{size}+1)/abs((@{size}+1)+0.001)) + round((@{size}+0)/abs((@{size}+0)+0.001)) + round((@{size}-1)/abs((@{size}-1)+0.001)) + round((@{size}-2)/abs((@{size}-2)+0.001)) + round((@{size}-4)/abs((@{size}-4)+0.001)) + round((@{size}-8)/abs((@{size}-8)+0.001)) )