I basically calculate the sides of the right-angle triangle defined by the target viewing angle radius as the hypotenuse, and the angle created between that target viewing angle and adjacent X/Y axis.
Scriptname phiPlaceBehindScript extends ActiveMagicEffectObjectReference Property phiPlayer auto ; I usually pick the player ref in the CK after compiling.ObjectReference Property myRef auto ; The actor/object you are placing. Also defined in CK.Event OnEffectStart(Actor akTarget, Actor akCaster)float xpos = phiPlayer.GetPositionX() ; The next three lines get the X and Yfloat ypos = phiPlayer.GetPositionY() ; position of the player and their current viewing angle.float zAngle = phiPlayer.GetAngleZ()float xdistance = 216 ; This is the number of game units from the player you want to place the object.if zAngle < 180 ; This if loop is to offset our target viewing angle 180 degrees zAngle = zAngle + 180 ; which will be directly behind us, and also checks for a valueelse ; between 0-360 which may not be necessary. zAngle = zAngle - 180endif; This section does the actual calculations. Given the circle defined with the player as the center point and a radius equal tothe xdistance value, I subtract 90 degrees from the target angle for each full quadrant between that direction and0 degrees, so I can then calculate the unknown sides of the right-angle triangle defined between that target angle andthe nearest adjacent X/Y axis. The xdistance value (216 in this example) becomes the hypotenuse of this triangle. if zAngle == 0 ; These first four loops are easy, for when the target viewing angle falls exactly on an axis. xdes = xpos ydes = ypos + xdistance myRef.SetPosition(xdes, ydes, phiPlayer.GetPositionZ() + 45) elseif zAngle == 90 xdes = xpos + xdistance ydes = ypos myRef.SetPosition(xdes, ydes, phiPlayer.GetPositionZ() + 45) elseif zAngle == 180 xdes = xpos ydes = ypos - xdistance myRef.SetPosition(xdes, ydes, phiPlayer.GetPositionZ() + 45) elseif zAngle == 270 xdes = xpos - xdistance ydes = ypos myRef.SetPosition(xdes, ydes, phiPlayer.GetPositionZ() + 45) elseif zAngle <= 89.999 float xoffset = xdistance * Math.sin(zAngle) ; This side of the triangle becomes our x-offset, float yoffset = xdistance * Math.cos(zAngle) ; and this the y-offset. We add these to the player's xdes = xpos + xoffset ; X and Y position to place our reference. ydes = ypos + yoffset myRef.SetPosition(xdes, ydes, phiPlayer.GetPositionZ() + 45) ; Does the final positioning. elseif zAngle <= 179.999 ; You may need to MoveTo/PlaceAtMe disabled before doing this. float xoffset = xdistance * Math.cos(zAngle - 90) ; Different calculations for the other quadrants the float yoffset = xdistance * Math.sin(zAngle - 90) ; target angle may fall in, same idea. xdes = xpos + xoffset ydes = ypos - yoffset myRef.SetPosition(xdes, ydes, phiPlayer.GetPositionZ() + 45) ; I add 45 so the ref appears slightly above ground. elseif zAngle <= 269.999 float xoffset = xdistance * Math.sin(zAngle - 180) float yoffset = xdistance * Math.cos(zAngle - 180) xdes = xpos - xoffset ydes = ypos - yoffset myRef.SetPosition(xdes, ydes, phiPlayer.GetPositionZ() + 45) elseif zAngle <= 359.999 float xoffset = xdistance * Math.cos(zAngle - 270) float yoffset = xdistance * Math.sin(zAngle - 270) xdes = xpos - xoffset ydes = ypos + yoffset myRef.SetPosition(xdes, ydes, phiPlayer.GetPositionZ() + 45) endifEndEvent
Here is the same code, without my comments:
Spoiler Scriptname phiPlaceBehindScript extends ActiveMagicEffectObjectReference Property phiPlayer autoObjectReference Property myRef autoEvent OnEffectStart(Actor akTarget, Actor akCaster) float xpos = phiPlayer.GetPositionX() float ypos = phiPlayer.GetPositionY() float zAngle = phiPlayer.GetAngleZ() float xdistance = 216 if zAngle < 180 zAngle = zAngle + 180 else zAngle = zAngle - 180 endif if zAngle == 0 xdes = xpos ydes = ypos + xdistance myRef.SetPosition(xdes, ydes, phiPlayer.GetPositionZ() + 45) elseif zAngle == 90 xdes = xpos + xdistance ydes = ypos myRef.SetPosition(xdes, ydes, phiPlayer.GetPositionZ() + 45) elseif zAngle == 180 xdes = xpos ydes = ypos - xdistance myRef.SetPosition(xdes, ydes, phiPlayer.GetPositionZ() + 45) elseif zAngle == 270 xdes = xpos - xdistance ydes = ypos myRef.SetPosition(xdes, ydes, phiPlayer.GetPositionZ() + 45) elseif zAngle <= 89.999 float xoffset = xdistance * Math.sin(zAngle) float yoffset = xdistance * Math.cos(zAngle) xdes = xpos + xoffset ydes = ypos + yoffset myRef.SetPosition(xdes, ydes, phiPlayer.GetPositionZ() + 45) elseif zAngle <= 179.999 float xoffset = xdistance * Math.cos(zAngle - 90) float yoffset = xdistance * Math.sin(zAngle - 90) xdes = xpos + xoffset ydes = ypos - yoffset myRef.SetPosition(xdes, ydes, phiPlayer.GetPositionZ() + 45) elseif zAngle <= 269.999 float xoffset = xdistance * Math.sin(zAngle - 180) float yoffset = xdistance * Math.cos(zAngle - 180) xdes = xpos - xoffset ydes = ypos - yoffset myRef.SetPosition(xdes, ydes, phiPlayer.GetPositionZ() + 45) elseif zAngle <= 359.999 float xoffset = xdistance * Math.cos(zAngle - 270) float yoffset = xdistance * Math.sin(zAngle - 270) xdes = xpos - xoffset ydes = ypos + yoffset myRef.SetPosition(xdes, ydes, phiPlayer.GetPositionZ() + 45) endifEndEvent