Setting Local Rotation

From the CreationKit Wiki
Jump to navigation Jump to search

The SetAngle function rotates an object according to the global axes, not the local axes of an object. This means that if you were to script the movement of a ship, for example, you would be unable to account for pitch and roll (rotation about the x and y axes).

To rotate the object about its local axes, use this function:

Function SetLocalAngle(Float LocalX, Float LocalY, Float LocalZ)
	float AngleX = LocalX * Math.Cos(LocalZ) + LocalY * Math.Sin(LocalZ)
	float AngleY = LocalY * Math.Cos(LocalZ) - LocalX * Math.Sin(LocalZ)
	SetAngle(AngleX, AngleY, LocalZ)
EndFunction

So if you wanted to have the ship roll 15 degrees over to its left side, while experiencing some pitch causing it to tilt up 10 degrees, on a heading of 135 degrees, you would use:

SetLocalAngle(-10, 15, 135)

The function is meant to be put on a scripted object, and will move only that object when called. You can easily make it a global function by changing it to this:

Function SetLocalAngle(ObjectReference MyObject, Float LocalX, Float LocalY, Float LocalZ) Global
	float AngleX = LocalX * Math.Cos(LocalZ) + LocalY * Math.Sin(LocalZ)
	float AngleY = LocalY * Math.Cos(LocalZ) - LocalX * Math.Sin(LocalZ)
	MyObject.SetAngle(AngleX, AngleY, LocalZ)
EndFunction

Obviously, the 'MyObject' parameter is for the object you want to rotate.


Following script makes an object rotate indefinitely:

Scriptname RotatingObject extends ObjectReference  

Float Property RotationSpeed = 20.0 Auto

Event OnInit()
	SetMotionType(4)  ;this is needed if the script is attached to a havoc object
 	OnTranslationAlmostComplete()
EndEvent

Event OnCellLoad()
	OnTranslationAlmostComplete()
EndEvent

Event OnUpdate()
	OnTranslationAlmostComplete()
EndEvent

Event OnTranslationAlmostComplete()
	if Is3DLoaded()
		Float AngleZ = GetAngleZ() + 120
		if AngleZ >= 360
			AngleZ = AngleZ - 360
		endif
		TranslateTo(GetPositionX(), GetPositionY(), GetPositionZ(), GetAngleX(), GetAngleY(), AngleZ, 0.0, RotationSpeed)
	else
		RegisterForSingleUpdate(0.1)
	endif
EndEvent

(Note about the above script: OnTranslationAlmostComplete() inside the OnInit() event will make the object start rotating as soon as the game loads--whether the object is visible/loaded/near the player or not.

The OnUpdate() event and the RegisterForSingleUpdate inside the else statement work together to keep the object rotating indefinitely whether the object is visible/loaded/near the player or not.

In most use cases, you'll want to either delete or comment out lines 7, 15, and 26 in order to reduce script load.)