The issue is detailed below, but it's basically a need to convert between Euler World rotation in the order Z >>> Y >>> X to a local rotation of Pitch, Roll, and yaw.
The Code on the spells:
Scriptname TestMovementControls extends activemagiceffect {Script to test movement on an object}Bool Property Roll AutoBool Property Pitch AutoBool Property Yaw Auto ; Tells the script which functions to use. Lets us use one script.Float Property RotateDegrees AutoTestObject TestMeEvent OnEffectStart(Actor Target, Actor Caster) if Test.RotatingBridgeClockwise Test.RotatingBridgeClockwise = False else Test.RotatingBridgeClockwise = True endif RegisterForUpdate(0.25) if !Test.TestSubject ; If we have no test subject Game.GetPlayer().PlaceAtMe(TestObjectType,1,False,False) endifEndEventEvent OnEffectFinish(Actor Target, Actor Caster) UnRegisterForUpdate()EndEventEvent OnUpdate() float HowMuch = RotateDegrees if !Test.RotatingBridgeClockwise Howmuch *= -1 endif If !TestMe && Test.TestSubject ; We have nothing to test, but look for one. TestMe = Test.TestSubject as TestObject elseif TestMe if Roll TestMe.RollBy(HowMuch) elseif pitch TestMe.PitchBy(HowMuch) else Testme.YawBy(HowMuch) endif endifEndEventActivator Property TestObjectType AutoTestVariables Property Test AutoThe Code on the Test Object:
Scriptname TestObject extends ObjectReference import mathBool Rotating = falseint UpdateCount = 0int MaxUpdates = 360 ; Approximate 6 minute lifespan.float NextRollfloat NextYawfloat NextPitchfloat CapRotationfloat Dxfloat Dyfloat Dzbool NeedToFix = Falsefunction Rotate(float X,Float Y, Float Z)endFunctionfunction RotateMe() Self.TranslateTo(X,Y,Z,NextRoll,NextPitch,NextYaw,1.0,CapRotation)endfunctionfloat function Fix(Float N) if sqrt(N * N) <= 1.0 ; Absolute value of N is very small return 0.0 else return N endifendfunctionFunction RollBy(float N) ; Rotate the object by N Degrees per Second around the X Axis. if !Rotating Rotating = True NextRoll = GetAngleX()+N NextPitch = GetAngleY() NextYaw = GetAngleZ()Debug.Notification("X: "+ NextRoll + "," + NextPitch + "," + NextYaw) CapRotation = Sqrt(N * N) ; Disallow negative CapRotation values. RotateMe() endifEndFunctionFunction PitchBy(float N) ; Rotate the object by N Degrees per second around the Y Axis. if !Rotating Rotating = True NextRoll = GetAngleX() NextPitch = GetAngleY()+N NextYaw = GetAngleZ()Debug.Notification("Y: "+ NextRoll + "," + NextPitch + "," + NextYaw) CapRotation = Sqrt(N * N) ; Disallow negative CapRotation values. RotateMe() endifEndFunctionFunction YawBy(float N) ; Rotate the object by N Degrees per second around the Z Axis. if !Rotating Rotating = True NextRoll = GetAngleX() NextPitch = GetAngleY() NextYaw = GetAngleZ()+NDebug.Notification("Z: "+ NextRoll + "," + NextPitch + "," + NextYaw) CapRotation = Sqrt(N * N) ; Disallow negative CapRotation values. RotateMe() endifEndFunctionEvent OnInit() Rotating = True ; Don't respond to any rotations until we're set up. Test.TestSubject = self Debug.Notification("Moving to start position") MoveTo(Game.GetPlayer(),0.0,0.0,300.0) ; Above the head of the player by 300.0 units. TranslateTo(X,Y,Z,0.0,0.0,0.0,1.0,45) ; Reset to zero rotation. NextRoll = 0.0 NextPitch = 0.0 NextYaw = 0.0 RegisterForUpdate(1) ; Start the Death ClockEndEventEvent OnTranslationComplete() Dx = GetAngleX() Dy = GetAngleY() Dz = GetAngleZ() NeedToFix = False if Dx >= 360.0 NeedToFix = True while Dx >= 360.0 Dx = Dx - 360.0 endwhile Dx = Fix(Dx) elseif Dx <= -360.0 NeedToFix = True while Dx <= 360.0 Dx = Dx + 360.0 endwhile Dx = Fix(Dx) endif if Dy >= 360.0 NeedToFix = True while Dy >= 360.0 Dy = Dy - 360.0 endwhile Dy = Fix(Dy) elseif Dy <= -360.0 NeedToFix = True while Dy <= 360.0 Dy = Dy + 360.0 endwhile Dy = Fix(Dy) endif if Dz >= 360.0 NeedToFix = True while Dz >= 360.0 Dz = Dz - 360.0 endwhile Dz = Fix(Dz) elseif Dz <= -360.0 NeedToFix = True while Dz <= 360.0 Dz = Dz + 360.0 endwhile Dz = Fix(Dz) endif if NeedToFix SetAngle(Dx,Dy,Dz) ; Snap to basically the same spot, but with angles reset. Endif NeedToFix = False ; We have now fixed any rounding errors Rotating = False ; Will now respond to the next call to a rotate function.EndEventEvent OnTranslationFailed() ; couldn't move Rotating = False Debug.Notification("Unable to move: " + self)endeventEvent OnUpdate() UpdateCount += 1 if UpdateCount == MaxUpdates Self.Disable() Self.Delete() Test.TestSubject = None endifEndEventTestVariables Property Test AutoThe Code for the Global variables
Scriptname TestVariables extends Quest {A place for those pesky test variables.}TestObject Property TestSubject Auto ; Test.TestSubjectActivator Property TestSubjectType Autobool Property RotatingObjectClockwise auto; To access these variables and functions in a script, place the following line in the script:; TestVariables Property Test AutoWhat I am wanting to do is make a nonspherical projectile (like an arrow) point at a target, regardless of whether is is above or below itself, and make it keep an "even keel" (so I could do it with a platform that was at an angle and was rotating around a shaft) - now the game has problems with the player being able to stand on a moving object, but it would be nice to be able to do it anyway.
Plus, if you're going to simulate something like a moving cart like in the opening scene, bouncing down a road and staying upright, good luck doing that using the existing TranslateTo function, and having to manually figure out how to keep the cart upright when it goes around a corner and such...with Roll, Pitch, and yaw, you can easily change the Yaw without affecting the Roll and Pitch, and going up or down a hill, you want to be able to change the pitch without affecting the roll and yaw.
the functions I'm after would be like these:
GetRoll(ObjectReference akObject) - Returns the Roll value of the current object
GetPitch(ObjectReference akObject) - Returns the Pitch value of the current object
GetYaw(ObjectReference akObject) - Returns the Yaw value of the current object.
GetX(Float akRoll, Float akPitch, Float akYaw) - Returns the X rotation corresponding to the given Roll, Pitch, ahd Yaw.
GetY(Float akRoll, Float akPitch, Float akYaw) - Returns the Y rotation corresponding to the given Roll, Pitch, ahd Yaw.
GetZ(Float akRoll, Float akPitch, Float akYaw) - Returns the Z rotation corresponding to the given Roll, Pitch, ahd Yaw.
