There is a range in play here.
If we normalise the range to '0 - 1', things get easier. To do this we use a scale factor.
ScaleFactor = 1 / (max - min)
Since min is zero in your case, ScaleFactor = 1 / max
Max (in your case) = Sprite.LineOfSight.Range
Or .. ScaleFactor = (1 / Sprite.LineOfSight.Range)
Any distance normalised is now DistanceNormalised = (1 / Sprite.LineOfSight.Range) * Distance
Say the Range is = 300 And we are 200 away:
(1 / 300 ) * 200 = 0.666
Say the Range is = 300 And we are 75 away:
(1 / 300 ) * 75 = 0.25
So we clearly now have a value between zero and 1, representing the range (normalised), and it is a small number when closer and bigger when further away. So lets reverse that.
ScaleFactor = (1 - (1 / Sprite.LineOfSight.Range))
or DistanceNormalised = (1 - (1 / Sprite.LineOfSight.Range)) * Distance
Only problem now is that things go negative when out of range.
We solve that by ... DistanceNormalised = max((1 - (1 / Sprite.LineOfSight.Range)),0) * (Distance)
Distance = distance(button.x,button.y,mouse.x,mouse.y)
So we gonna add a small random to the button.X and button.y, that is proportional to DistanceNormalised
random(DistanceNormalised , 0 )
Set button position to ...
x = Button.RestPositionX + (ScalarX * ((random( (max((1 - (1 / Sprite.LineOfSight.Range)),0) * (distance(button.x,button.y,mouse.x,mouse.y))) , 0 ))))
y = Button.RestPositionY + (ScalarY * ((random( (max((1 - (1 / Sprite.LineOfSight.Range)),0) * (distance(button.x,button.y,mouse.x,mouse.y))) , 0 ))))
Choose a value for ScalarX and ScalarY to your liking.
Button.RestPositionX is the position for the button in rest, (else he gonna vibrate off screen) stored in an instance variable 'RestPositionX'.