dafydd99 Posted September 1, 2020 Author Share Posted September 1, 2020 Thanks Rasikko - yes it's all too easy to slip into Fallout4 forums! The project I most want it for is this... https://www.nexusmods.com/skyrimspecialedition/mods/38420. The Sidrat - a moveable home, that can take many different external appearances (or 'models' as I'm calling them). I've made ten models, but in some cases (eg the mushroom home, like one from Tel Mithryn) it would be great to be able to eg put lanterns on the ropes around the edge (there are more serious reasons why I need to do the rotation, but this is a good example). My scripts move the models to the new location on moving, and add an extra 'rotation' step as you exit into the arrival cell (to fix the moveto bug when you're not in the same cell as the object reference). All well and good, and works fine, as long as the RotateX and RotateY aren't set. And to put lanterns on the rope so they look natural they need to be rotate in x and y. I've thought that perhaps using 'attach ref' might work - but unfortunately I'm not sure that works when moving an objectreference between unloaded cells. But perhaps you're right - the solution might just be to work out the maths! Cheers - dafydd99 Link to comment Share on other sites More sharing options...
dafydd99 Posted September 18, 2020 Author Share Posted September 18, 2020 Have done some more work on 'attach ref' stuff, and it pretty much works. I need to make a 'marker' object, attach an 'attach node' to it in nifskope, then set the attach refs for all the objectreferences I want to attach to it. When the objects are moved to be part of the model, you can then rotate the marker object to the correct rotation and all the attached refs will rotate correctly. And every time you return to that cell you have to repeat this process as the engine seems to forget those objects. So an 'OnCellAttach' event has to be added to the marker to repeat this everytime. Also the marker must have 'respawn' turned off, or it'll break on respawn. One slight problem - it works in every situation except game load - so if you have a save just by the model the rotatable pieces will have gone on loading. Fast travel away and back and they're okay. I can't find an event that is fired at game load... as mentioned here... https://www.creationkit.com/index.php?title=OnCellAttach_-_ObjectReference Cheers - dafyd99 Link to comment Share on other sites More sharing options...
Evangela Posted September 18, 2020 Share Posted September 18, 2020 There is OnPlayerLoadGame. https://www.creationkit.com/index.php?title=OnPlayerLoadGame_-_Actor Link to comment Share on other sites More sharing options...
dafydd99 Posted September 18, 2020 Author Share Posted September 18, 2020 (edited) Thanks again for supporting this Rasikko. Hm... I was thinking that might be a little too far off as the rotation code should run when the 3d of the 'marker' object. But in theory there could be some way I could register that marker with the quest, and have an OnePlayerLoadGame event trigger this - it's a bit convoluted but it might just work! Cheers - dafydd99 Edited September 18, 2020 by dafydd99 Link to comment Share on other sites More sharing options...
dafydd99 Posted September 26, 2020 Author Share Posted September 26, 2020 Right - so I got quite some way down the OnCellAttach route - and it mostly works. But sometimes inexplicably it doesn't - it's possible it's not designed for moving objects between cells. HOWEVER! After an eternity of mucking about with the rotation stuff - I FINALLY think I might have got something that works... import utility import math function zAxisRotate(ObjectReference ref, float angleZRotate) global rotateRefAroundZAxis(ref, ref.GetAngleX(), ref.GetAngleY(), ref.GetAngleZ(), angleZRotate) endfunction function rotateRefAroundZAxis(ObjectReference ref, float originalXAngle, float originalYAngle, float originalZAngle, float angleZRotate) global float[] xyz=getRotateAroundZAxisAngles(originalXAngle, originalYAngle, originalZAngle, angleZRotate) ref.SetAngle(xyz[0], xyz[1], xyz[2]) endfunction float[] function getRotateAroundZAxisAngles(float originalXAngle, float originalYAngle, float originalZAngle, float angleZRotate) global float[] normalisedAngles=getLocalAngles(originalXAngle, originalYAngle, -originalZAngle) float[] angles=getLocalAngles(normalisedAngles[0], normalisedAngles[1], -normalisedAngles[2]+angleZRotate) return angles endfunction float[] function getLocalAngles(float localAngX, float localAngY, float localAngZ) global ;the world angles float worldAngX float worldAngY float worldAngZ localAngX=-localAngX localAngY=-localAngY localAngZ=-localAngZ ;sine and cosine of local x, y, z angles float sx=sin(localAngX) float cx=cos(localAngX) float sy=sin(localAngY) float cy=cos(localAngY) float sz=sin(localAngZ) float cz=cos(localAngZ) ;ZYX float r11=cz*cy float r12=-sz*cx+cz*sy*sx float r13=sz*sx+cz*sy*cx float r21=sz*cy float r22=cz*cx+sz*sy*sx float r23=cz*(-sx)+sz*sy*cx float r31=-sy float r32=cy*sx float r33=cy*cx ;Extraction of worldangles from rotation matrix if (r13 > 0.9998) ;positive gimbal lock worldAngX=-atan2(r32, r22) worldAngY=-90 worldAngZ=0 elseif (r13 < -0.9998) ;negative gimbal lock worldAngX=-atan2(r32, r22) worldAngY=90 worldAngZ=0 else ;no gimbal lock r23=-r23 r12=-r12 worldAngX=-atan2(r23, r33) worldAngY=-asin(r13) worldAngZ=-atan2(r12, r11) endif float[] toReturn=new float[3] toReturn[0]=worldAngX toReturn[1]=worldAngY toReturn[2]=worldAngZ return toReturn Endfunction float function atan2(float y, float x) global ; returning degrees if x>0 return atan(y/x) elseif x<0 if y>=0 return atan(y/x)+180.0 elseif y<0 return atan(y/x)+(-180.0) endif elseif x==0 if y>0 return 90 elseif y<0 return -90 else ; undefined - we'll return zero return 0.0 endif endif endfunction Above is a collection of global functions that should allow an object reference to be rotate around the Z-Axis, no matter what the X and Y rotations are. It's been very hit and miss getting here, so I suspect this could be optimised further. Once again - thanks to Rasikko for the support through this. cheers - dafydd99 Link to comment Share on other sites More sharing options...
Evangela Posted September 27, 2020 Share Posted September 27, 2020 (edited) I'm glad to hear that you got something going. I can't understand any of the math in that code so it must mean you reached your goal LOL. Edited September 27, 2020 by Rasikko Link to comment Share on other sites More sharing options...
dylbill Posted May 16, 2021 Share Posted May 16, 2021 I was looking for something exactly like this. I just tested your code and it works great! Thanks for sharing! Link to comment Share on other sites More sharing options...
AnishaDawn Posted May 16, 2021 Share Posted May 16, 2021 (edited) Oh~ that is real nifty. I think you can also use math to get the local x, y and z positions(position relative to the cell). x:13000 - ((13000 / 4096) as int * 4096) = 13000 - 12288 = x:712(12288 is the 3rd cell from the origin on the x axis) Negative positions has to be accounted for, thus the result has to be multiplied or added by -1. Edited May 16, 2021 by AnishaDawn Link to comment Share on other sites More sharing options...
dafydd99 Posted May 16, 2021 Author Share Posted May 16, 2021 My pleasure dylbill - just glad it wasn't only of use to me. It's the kind of thing that really should be built into the engine - fingers crossed we'll find it's much improved in ES6. My application of this code was to move a home constructed of several refs, and allow little add-on refs at any angle. However if I was doing this again, I might look more at doing this at the nif level as it's soooo much easier. Link to comment Share on other sites More sharing options...
dylbill Posted May 16, 2021 Share Posted May 16, 2021 Ahh gotcha, yeah doing it at the nif level would be easier. I agree that setting or modding local angles should be included in the engine. I'm going to maybe update my positioner mod with this. Right now it changes world angles of objects, but would be nice to include local angles as an option. Link to comment Share on other sites More sharing options...
Recommended Posts