ZeroCore Posted April 6, 2017 Share Posted April 6, 2017 (edited) Hi. I'm trying to essentially do the same thing that the J3X levitation script did; make two platforms move, one by one, beneath the player to create essentially a Morrowind-style levitation script. And I'm stuck on something. The script seems to have good logic, but it won't work and when the player tries to activate the greater power that uses the script in a spell effect, the platforms don't move. I've tried using static objects, activators, and movable static objects as platforms, but still nothing. If someone can help me with this, I'd appreciate it. I have the motion type set to keyframed because currently I'm trying to use a pair of movable static objects as the platforms. Originally I was trying to use a pair of static objects, namely two of the circular rugs you find in some homes in Skyrim (both of which had reference ID's given to them). When that didn't work I went to a pair of activators, a pair of disk-shaped plates that form the middle of the blood seal at Skyhaven Temple (also given reference ID's), and then finally this, a pair of movable static objects (namely a pair of scaled-up golden dining plates from Sovngarde, which are plates that move like plates, but cannot be picked up by the player). Here is the script in a spoiler menu: Scriptname _YetAnotherFlightAttempt extends activemagiceffect ObjectReference Property FlyingCarpetA Auto ;these two contain the invisible rugs (round rugs with the null texture set put on their meshes; they are static objects) ObjectReference Property FlyingCarpetB Auto ObjectReference LoadedCarpet ;the carpet that is currently set to be moved and tilted by the script Actor ThePlayer ;the Player int SwitchInt ;This int is for a sort of switch that lets you move the two rugs/platforms independantly of one another when used in conjunction with an update and a conditional statement (an "if" statement) float space 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) LoadedCarpet.SetAngle(AngleX, AngleY, LocalZ) EndFunction ;THIS FUNCTION IS VERY IMPORTANT. It rotates the rugs to where the player is facing and tilts them in the direction the player is looking. This is NEEDED as measurements and position adjustments in Skyrim are local to THE WORLD SPACE, and NOT the PLAYER OR ANY NPC'S, so in order to get the things set and angled LOCAL TO THE PLAYER, this bit of trig is needed. EVENT onEffectStart(Actor akTarget, Actor akCaster) ThePlayer = akCaster SwitchInt = 1 FlyingCarpetA.enable() FlyingCarpetB.enable() LoadedCarpet = FlyingCarpetA RegisterForUpdate(0.1) EndEvent EVENT onUpdate() space = LoadedCarpet.getDistance(ThePlayer) if (!ThePlayer.isSneaking() && space > 60) if (SwitchInt == 1) LoadedCarpet = FlyingCarpetA LoadedCarpet.SetMotionType(LoadedCarpet.Motion_Keyframed) LoadedCarpet.moveto(ThePlayer) LoadedCarpet.SetPosition(ThePlayer.GetPositionX(), ThePlayer.GetPositionY(), ThePlayer.GetPositionZ() - 10) SetLocalAngle(ThePlayer.GetAngleX(), 0, ThePlayer.GetAngleZ()) SwitchInt = 2 RegisterForUpdate(0.1) elseIf (SwitchInt == 2) LoadedCarpet = FlyingCarpetB LoadedCarpet.SetMotionType(LoadedCarpet.Motion_Keyframed) LoadedCarpet.moveto(ThePlayer) LoadedCarpet.SetPosition(ThePlayer.GetPositionX(), ThePlayer.GetPositionY(), ThePlayer.GetPositionZ() - 10) SetLocalAngle(ThePlayer.GetAngleX(), 0, ThePlayer.GetAngleZ()) SwitchInt = 1 RegisterForUpdate(0.1) endIf elseIf (!ThePlayer.isSneaking() && space < 60) RegisterForUpdate(0.1) elseIf (ThePlayer.isSneaking()) FlyingCarpetA.disable() FlyingCarpetB.disable() endif EndEvent It didn't work. And I don't know why. I've had some other modders look over it, and they couldn't figure it out either. If anyone can offer some help with this, I'd appreciate it. Edited April 6, 2017 by ZeroCore Link to comment Share on other sites More sharing options...
cdcooley Posted April 7, 2017 Share Posted April 7, 2017 Most likely it's the Havok settings on those items. J3X modified the Sovngarde plates by deleting the visible mesh and changing it to use a Havok collsion layer of ANIMSTATIC, the KEYFRAMED Motion System and Quality Types, and the LOW Solver Deactivation setting as well as a few other minor edits for that levitation mod. I have a levitation spell I've never published and created my own platform (mainly because I didn't like the J3X's platforms cause chaos if used indoors). You can find my InvisiblePlatform.nif in my Dropbox WIP folder if you want to use it or look at it. My version uses the STAIRHELPER collision layer since that one won't interact with clutter. https://www.dropbox.com/sh/usf77ua06h1qh8k/AAA64msQbDbTfe3URb0mmC9Qa?dl=0 You might also be running into a problem with duration. Your ActiveMagicEffect script can only register for events and be active while effect itself is active. If your power doesn't have a duration you'll have to put the actual code to control the platforms in some other script (like a quest script). Here's my version of a script that works with a concentration Levitation spell (which helpfully prevents the player from sprinting off the edge of the platform). ScriptName CDC_LevitationScript extends ActiveMagicEffect ObjectReference[] property CDC_InvisiblePlatform auto {Must be filled with two persistent references. Needs a nif with a STAIRHELPER Havok Layer, KEYFRAMED Motion and Quality, LOW Solver Deactivation, and flat collision plane (like a rug but invisible).} Actor property PlayerRef auto int ipNum ; allows alternating between the two platform objects bool active ; used as a signal to avoid trying to register again after the spell finishes Event OnEffectStart(Actor akTarget, Actor akCaster) active = true CDC_InvisiblePlatform[0].EnableNoWait() CDC_InvisiblePlatform[1].EnableNoWait() OnUpdate() ; get platform placement system started EndEvent Event OnUpdate() float direction = PlayerRef.GetAngleZ() ; horizontal angle float elevation = PlayerRef.GetAngleX() ; vertical angle if elevation < -45 ; player can't walk on vertical surfaces so limit the angle elevation = -45 elseif elevation > 45 elevation = 45 endif ipNum = 1 - ipNum ; alternates the platform used CDC_InvisiblePlatform[ipNum].MoveTo(PlayerRef,0,0,0,false) ; move it directly under the player CDC_InvisiblePlatform[ipNum].SetAngle(Math.Cos(direction)*elevation, -Math.Sin(direction)*elevation, direction) if active ; this check is trying to avoid showing an error in log file (but still doesn't always work) RegisterForSingleUpdate(0.01) ; registering on such a short interval so the player can't run off the platform endif EndEvent Event OnEffectFinish(Actor akTarget, Actor akCaster) active = false CDC_InvisiblePlatform[0].DisableNoWait() CDC_InvisiblePlatform[1].DisableNoWait() EndEvent Link to comment Share on other sites More sharing options...
Recommended Posts