Small breakthrough: Two separate objects move as one!

Post » Tue Nov 20, 2012 7:04 am

Or at least I think it hasn't been done before. Today I managed to attach a havok object to another havok object on the fly through script. It's a container crate inside a rideable cart:

http://www.youtube.com/watch?v=bbp02KdG_q8

The concept has some potential I think, it could be used to attach all kinds of activators to followers, horses and other movable objects. For example a directly activatable backpack carried by your follower, or a directly activatable sword on your horse's saddlebags (which could also be directly activatable).


I managed this by using the AddHavokBallAndSocketConstraint function. The most annoying limitation by the function is that it can only make one constraint from one bhkCollisionObject to another. I figured out that reverting the references is possible, but to make an object rigidly attached to another you need three ball and socket constraints. In the case of the cart I was lucky enough that another bhkCollisionObject already existed that always has the same relative position to the main bhkCollisionObject node. These are the function calls:


Game.AddHavokBallAndSocketConstraint(Cart, "PrisonerCarriage", Freight, "CrateLong01", 50, -120, 130, 50, 0, 0)
Game.AddHavokBallAndSocketConstraint(Freight, "CrateLong01", Cart, "PrisonerCarriage", -50, 0, 0, -50, -120, 130)
Game.AddHavokBallAndSocketConstraint(Cart, "FrontBar", Freight, "CrateLong01", 0, 0, 0, 0, 120, -77.2948)



It might be necessary for other objects to manually add another functional bhkCollisionObject to the NIF before you can use this technique.
User avatar
Nienna garcia
 
Posts: 3407
Joined: Wed Apr 25, 2007 3:23 am

Post » Tue Nov 20, 2012 10:59 am

Innnnnnteresting...

I was never able to get AddHavokBallAndSocketConstraint to show me any love at all. I tried to attach a cabbage to my hand once, which just resulted in the cabbage falling off. It would only stay attached when my body was in ragdoll mode. Were you able to overcome this?
User avatar
tiffany Royal
 
Posts: 3340
Joined: Mon Dec 25, 2006 1:48 pm

Post » Tue Nov 20, 2012 3:05 am

You can make attachment points by adding sub-nodes connected by Havok constraints in the .nif file. I use this in my http://skyrim.nexusmods.com/mods/19741 (the cart is hoisted into the air by an invisible object to which havok impulses are applied), and Dielos uses a similar technique for his http://www.gamesas.com/topic/1415422-show-us-what-youre-working-on/page__view__findpost__p__21731875.

Really nice use of it to attach a container to a cart :) :goodjob:.

@Chesko, what were the Havok properties of the cabbage? I'm using AddHavokBallAndSocketConstraint to connect an invisible 'hook' node in a nif to a dragon and a 'missile' node in the same nif (they're joined by a spring constraint) to my character's hand, and it works just fine. Both nodes lock on and hold until I release the missile using RemoveHavokConstraints, then the missile get's dragged to the dragon by the spring.

I'm using OL_CLUTTER, MO_SYS_DYNAMIC, DEACTIVATOR_NEVER, SOLVER_DEACTIVATION_OFF and MO_QUAL_MOVING. One RigidBody is at the root, the other in a sub-node.
User avatar
Jonathan Montero
 
Posts: 3487
Joined: Tue Aug 14, 2007 3:22 am

Post » Tue Nov 20, 2012 4:44 am

Or at least I think it hasn't been done before. Today I managed to attach a havok object to another havok object on the fly through script. It's a container crate inside a rideable cart:

http://www.youtube.com/watch?v=bbp02KdG_q8

Wow. I may have to pick your brains at a later date if that's ok with you. This has given me an idea for an ambush mission...

- Hypno
User avatar
Taylrea Teodor
 
Posts: 3378
Joined: Sat Nov 18, 2006 12:20 am

Post » Tue Nov 20, 2012 12:51 pm

You can make attachment points by adding sub-nodes connected by Havok constraints in the .nif file. I use this in my http://skyrim.nexusmods.com/mods/19741 (the cart is hoisted into the air by an invisible object to which havok impulses are applied), and Dielos uses a similar technique for his http://www.gamesas.com/topic/1415422-show-us-what-youre-working-on/page__view__findpost__p__21731875.

Really nice use of it to attach a container to a cart :smile: :goodjob:.

@Chesko, what were the Havok properties of the cabbage? I'm using AddHavokBallAndSocketConstraint to connect an invisible 'hook' node in a nif to a dragon and a 'missile' node in the same nif (they're joined by a spring constraint) to my character's hand, and it works just fine. Both nodes lock on and hold until I release the missile using RemoveHavokConstraints, then the missile get's dragged to the dragon by the spring.

I'm using OL_CLUTTER, MO_SYS_DYNAMIC, DEACTIVATOR_NEVER, SOLVER_DEACTIVATION_OFF and MO_QUAL_MOVING. One RigidBody is at the root, the other in a sub-node.

Does this require editing a player skeleton to attach to a hand, or can you use an add-on? How do you get the missile from the dragon to the player? This is very interesting.
User avatar
Jade Payton
 
Posts: 3417
Joined: Mon Sep 11, 2006 1:01 pm

Post » Tue Nov 20, 2012 4:16 pm

Does this require editing a player skeleton to attach to a hand, or can you use an add-on? How do you get the missile from the dragon to the player? This is very interesting.
Nope, everything vanilla. The exact code is
Event OnKeyDown (Int Keycode)  ObjectReference MyShot  dfm_TestShotPosScript Tester  ObjectReference ClosestDragon  Attacking = True  TargetDragonQuest.Start ()  ClosestDragon = TargetDragon.GetReference ()  TargetDragonQuest.Stop ()  While Attacking   If ClosestDragon != None	MyShot = PlaceAtMe (HomingShot)	Tester = PlaceAtMe (ShotTest) as dfm_TestShotPosScript	Tester.ShotToTest = MyShot	Tester.ShotTarget = ClosestDragon	Game.AddHavokBallAndSocketConstraint (Pilot, "NPC R Hand [RHnd]", MyShot, "Scene Root", 0, 30, 0, 0, 0, 0)	Game.AddHavokBallAndSocketConstraint (ClosestDragon, "NPC Neck1", MyShot, "Core", 0, 0, 0, 0, 0, 0)	Game.RemoveHavokConstraints (Pilot, "NPC R Hand [RHnd]", MyShot, "Scene Root")   EndIf   Utility.Wait (0.5)  EndWhileEndEvent
When I had the shot root (visible missile) attached to the flying machine instead of the player, and the shot core (the hook) attached to the dragon, and forgot to detach the root after setting up the connections, the flying machine was dragged through the air after the dragon as if attached by a grappling hook - which, in a way, it was :smile:. I made the spring constraint connecting the visible missile to the hook guided by http://niftools.sourceforge.net/wiki/Oblivion/Oblivion_Bhk_Constraints info, and fiddled with the mass and, max linear speed and linear damping of the root rigid.

http://steamcommunity.com/sharedfiles/filedetails/?id=107601661 a pic of the nif.

@Maegfaer, if you drive the cart far enough that the container's parent cell unloads, does the container vanish? If so, a workaround is to repeatedly translate the container towards the cart's current position. I keep issuing new translate commands before the previous one ends (I saw some screwy things otherwise), calculating the translate speed to always take twice as long as my gap between new translates.

A very clunky workaround, but if you do see this problem and can't find a better solution then this might help.
User avatar
Brandi Norton
 
Posts: 3334
Joined: Fri Feb 09, 2007 9:24 pm

Post » Tue Nov 20, 2012 12:12 pm

Very cool, thanks! Gives me a few ideas....
User avatar
Roberta Obrien
 
Posts: 3499
Joined: Tue Oct 23, 2007 1:43 pm

Post » Tue Nov 20, 2012 12:27 pm

@Maegfaer, if you drive the cart far enough that the container's parent cell unloads, does the container vanish? If so, a workaround is to repeatedly translate the container towards the cart's current position. I keep issuing new translate commands before the previous one ends (I saw some screwy things otherwise), calculating the translate speed to always take twice as long as my gap between new translates.

A very clunky workaround, but if you do see this problem and can't find a better solution then this might help.

Looks like it does, in fact the entire cart vanishes. Not illogical, since it's the horse that travels. I already read about such a solution on the CK wiki, but thanks for being more specific and reminding me to test it!
User avatar
Melly Angelic
 
Posts: 3461
Joined: Wed Aug 15, 2007 7:58 am

Post » Tue Nov 20, 2012 4:11 pm

Looks like it does, in fact the entire cart vanishes. Not illogical, since it's the horse that travels. I already read about such a solution on the CK wiki, but thanks for being more specific and reminding me to test it!
Yeesh! I'd sort of assumed they'd have sorted that out with the TetherToHorse call :rolleyes:. Oh well, good enough for their opening sequence, so not exactly a bug from their point of view :shrug:.
User avatar
Genocidal Cry
 
Posts: 3357
Joined: Fri Jun 22, 2007 10:02 pm

Post » Tue Nov 20, 2012 10:56 am

Thanks a lot Maeg! :biggrin: This is just what I was looking for, as I had the same experience as Chesko when trying to use it.
User avatar
Patrick Gordon
 
Posts: 3366
Joined: Thu May 31, 2007 5:38 am

Post » Tue Nov 20, 2012 4:20 pm

Very interesting stuff, thanks for sharing it! I was just doing some spells that toss havok boulders around, too, I bet I can find a use for that spring projectile thingy...
User avatar
Phillip Hamilton
 
Posts: 3457
Joined: Wed Oct 10, 2007 3:07 pm

Post » Tue Nov 20, 2012 4:06 am

Awesome. I've begun my attempt to include something like this for my mod.

I have a nif with the bhkCollisionObject node (node 23 in list view), in tree view below is a node called bhkRigidBodyT (bhkCollisionObject is an ancestor), can this model be used? Or does the "T" on the end throw things out?
I have very minimal NifSkope experience.
User avatar
Connie Thomas
 
Posts: 3362
Joined: Sun Nov 19, 2006 9:58 am

Post » Tue Nov 20, 2012 5:22 pm

I have a nif with the bhkCollisionObject node (node 23 in list view), in tree view below is a node called bhkRigidBodyT (bhkCollisionObject is an ancestor), can this model be used? Or does the "T" on the end throw things out?

Nevermind, I found this:
The "T" suffix marks this body as active for translation and rotation, a normal bhkRigidBody ignores those properties. Because the properties are equal, a bhkRigidBody may be renamed into a bhkRigidBodyT and vice-versa.
Will I actually need to re-name this node? And how do I find the input names for my script?

Function AddHavokBallAndSocketConstraint(ObjectReference arRefA, string arRefANode, ObjectReference arRefB, string arRefBNode)
User avatar
kevin ball
 
Posts: 3399
Joined: Fri Jun 08, 2007 10:02 pm

Post » Tue Nov 20, 2012 6:35 am

Will I actually need to re-name this node? And how do I find the input names for my script?

Function AddHavokBallAndSocketConstraint(ObjectReference arRefA, string arRefANode, ObjectReference arRefB, string arRefBNode)
Leaving the node untouched should be fine. The input names for your script are, literally, the names of the bhkRigidBody (or bhkRigidBodyT) nodes in your .nif files. So, two objects, two .nif files, two rigid-bodies, two ObjectReferences and two rigid-body node names.
User avatar
SiLa
 
Posts: 3447
Joined: Tue Jun 13, 2006 7:52 am

Post » Tue Nov 20, 2012 10:37 am

Thanks. Just to be perfectly clear, http://i101.photobucket.com/albums/m57/will_cuthill/Mzandahrk/Nodename.png. My node name here is Raise01 ?
User avatar
joseluis perez
 
Posts: 3507
Joined: Thu Nov 22, 2007 7:51 am

Post » Tue Nov 20, 2012 2:07 am

Thanks. Just to be perfectly clear, http://i101.photobucket.com/albums/m57/will_cuthill/Mzandahrk/Nodename.png. My node name here is Raise01 ?
Yes. I just realised that my last post was worded badly, but you got the right answer anyway :).
User avatar
Amiee Kent
 
Posts: 3447
Joined: Thu Jun 15, 2006 2:25 pm

Post » Tue Nov 20, 2012 6:02 pm

I'm trying to attach the dwefurniturehighbenchshort01.nif object to my http://i101.photobucket.com/albums/m57/will_cuthill/Mzandahrk/Nodename.png (http://www.youtube.com/watch?v=OVydPTdM1Fc&feature=youtu.be&hd=1) but I'm having minimal luck.

Here is the script fragment:
Event OnLoad()  bool Attach1 = Game.AddHavokBallAndSocketConstraint(LiftBody, "Raise01", LiftBodyFurn, "DweFurnitureHighBenchShort01")	Debug.Notification("Attach1 is "+ Attach1)EndEvent

http://i101.photobucket.com/albums/m57/will_cuthill/Mzandahrk/ScreenShot842.png. I am very confused. In addition to this, it will not translate with my LiftBody object.

If I try giving them both the same translation commands they are out of synch, so I want to stick to translating a single object only.
User avatar
Chris Johnston
 
Posts: 3392
Joined: Fri Jul 07, 2006 12:40 pm

Post » Tue Nov 20, 2012 5:34 pm

I'm trying to attach the dwefurniturehighbenchshort01.nif object to my http://i101.photobucket.com/albums/m57/will_cuthill/Mzandahrk/Nodename.png (http://www.youtube.com/watch?v=OVydPTdM1Fc&feature=youtu.be&hd=1) but I'm having minimal luck.

Here is the script fragment:
Event OnLoad()  bool Attach1 = Game.AddHavokBallAndSocketConstraint(LiftBody, "Raise01", LiftBodyFurn, "DweFurnitureHighBenchShort01")	Debug.Notification("Attach1 is "+ Attach1)EndEvent

http://i101.photobucket.com/albums/m57/will_cuthill/Mzandahrk/ScreenShot842.png. I am very confused. In addition to this, it will not translate with my LiftBody object.

If I try giving them both the same translation commands they are out of synch, so I want to stick to translating a single object only.
Ok, so your OnLoad is firing twice. What object/s is that script running on? If only one object, then maybe you need to use OnInit.

Also, you've omitted the offsets from your constraint function call. That will try to link the furniture's zero point to your elevator's zero point, and you could get some really bizarre behaviour as their collision meshes clash. Try to make sure you have an offset in at least one of the object's coordinate spaces. And finally, refer back to Maegfaer's original post - you'll need at least three connection points in different positions, which means at least one of your objects will need at least two rigid bodies connected together by (probably) a hinge constraint in the .nif.

I assume the point of the final exercises is so you can activate the elevator to raise or lower, and as it's doing so activate the furniture to sit? This approach will certainly work, but would it also be possible to make the bench/chair part of the elevator mesh, make the whole elevator a piece of furniture, and have an OnActivate block that blocks default activation and starts the movement if the elevator is not in motion, otherwise runs the furniture's default activation?

Just thinking of different ways to the same end :).
User avatar
Bellismydesi
 
Posts: 3360
Joined: Sun Jun 18, 2006 7:25 am

Post » Tue Nov 20, 2012 12:37 pm

Ok, so your OnLoad is firing twice. What object/s is that script running on? If only one object, then maybe you need to use OnInit.

Also, you've omitted the offsets from your constraint function call. That will try to link the furniture's zero point to your elevator's zero point, and you could get some really bizarre behaviour as their collision meshes clash. Try to make sure you have an offset in at least one of the object's coordinate spaces. And finally, refer back to Maegfaer's original post - you'll need at least three connection points in different positions, which means at least one of your objects will need at least two rigid bodies connected together by (probably) a hinge constraint in the .nif.

I assume the point of the final exercises is so you can activate the elevator to raise or lower, and as it's doing so activate the furniture to sit? This approach will certainly work, but would it also be possible to make the bench/chair part of the elevator mesh, make the whole elevator a piece of furniture, and have an OnActivate block that blocks default activation and starts the movement if the elevator is not in motion, otherwise runs the furniture's default activation?

Just thinking of different ways to the same end :smile:.

*D'oh, of course I'm getting two onLoad events, I have two DOOR forms with this script on them. Silly me. How perceptive of you to point that out.

All this is a little over my head. I just wanted to see if I could get them to attach before trying to work out offsets. I've no clue how to work out the values for my offsets given a location I want my second object to be in. I don't even know where the nodes actually are!?
http://i101.photobucket.com/albums/m57/will_cuthill/Mzandahrk/2CollisionObjectNodes.png does have two rigid body nodes, here is the rest of the fragment:
Spoiler

Event OnLoad()bool Attach1 = Game.AddHavokBallAndSocketConstraint(LiftBody, "Raise01", LiftBodyFurn, "DweFurnitureHighBenchShort01")   Debug.Notification("Attach1 is "+ Attach1)bool Attach2 = Game.AddHavokBallAndSocketConstraint(LiftBody, "Handle", LiftBodyFurn, "DweFurnitureHighBenchShort01")   Debug.Notification("Attach2 is "+ Attach2)bool Attach3 = Game.AddHavokBallAndSocketConstraint(LiftBodyFurn, "DweFurnitureHighBenchShort01", LiftBody, "Raise01")   Debug.Notification("Attach3 is "+ Attach3)EndEvent


It's like you knew what I was thinking, if I had the skills to make the entire elevator platform a furniture piece I would, I'm thinking this would be the simplest solution to my problem.

I've had my elevator working perfectly for the player quite some time ago now, the challenge is making it NPC friendly. I've navmeshed some DOOR forms so they know where to look. I'm having difficulty getting them past perpetually trying to activate the door. If the elevator platform was furniture they are already standing close enough that I will be able to force them to "activate" the furniture and thus enter the lift without them teleporting a small distance.

I'm ranting a bit now but is there any way to have like a walk-in furniture marker???
User avatar
bonita mathews
 
Posts: 3405
Joined: Sun Aug 06, 2006 5:04 am

Post » Tue Nov 20, 2012 6:58 am

All my Attach notifications are returning TRUE but the elevator is translating without the furniture, it just sits there. What am I doing wrong?
User avatar
gary lee
 
Posts: 3436
Joined: Tue Jul 03, 2007 7:49 pm

Post » Tue Nov 20, 2012 5:56 am

All my Attach notifications are returning TRUE but the elevator is translating without the furniture, it just sits there. What am I doing wrong?
I apologise if this is a stupid question, but are you using the actual dwefurniturehighbenchshort01.nif, or a copy of it with adjusted Havok settings? The original .nif ain't going anywhere because it's set up as a static.

To make a copy that moves you'd have to change the Layer and Layer Copy from OL_STATIC to OL_PROPS, the Motion System from MO_SYS_BOX_STABILIZED to MO_SYS_DYNAMIC and the Quality Type from MO_QUAL_INVALID to MO_QUAL_MOVING.

[edit]
As to your earlier question about making a walk-in furniture marker... I'm sorry, I have no idea :(.
User avatar
Kellymarie Heppell
 
Posts: 3456
Joined: Mon Jul 24, 2006 4:37 am

Post » Tue Nov 20, 2012 11:52 am

Not a silly question at all. Yes I am using the original. I didn't have a clue about those settings, like I said, I'm very inexperienced when it comes to NifSkope and co.

I'll try adjust some of those settings in a few minutes.
User avatar
Julia Schwalbe
 
Posts: 3557
Joined: Wed Apr 11, 2007 3:02 pm

Post » Tue Nov 20, 2012 6:27 am

To make a copy that moves you'd have to change the Layer and Layer Copy from OL_STATIC to OL_PROPS, the Motion System from MO_SYS_BOX_STABILIZED to MO_SYS_DYNAMIC and the Quality Type from MO_QUAL_INVALID to MO_QUAL_MOVING.

Would I change any and all of these layers that I come across? I'm seeing multiple OL_STATIC layers in the same block.

*EDIT: Changed all the layers as you said, still no dice. I made a new base object with my altered mesh and made sure all the property's pointed to it as well.
User avatar
Nicole Kraus
 
Posts: 3432
Joined: Sat Apr 14, 2007 11:34 pm

Post » Tue Nov 20, 2012 6:35 am

Also make sure the collision has a mass of at least 1. Anything between 0 and 1 will make the body harder to move in my experience, at 0 it's completely stationary. Also check the max linear velocity.
User avatar
sam westover
 
Posts: 3420
Joined: Sun Jun 10, 2007 2:00 pm

Post » Tue Nov 20, 2012 5:14 am

*EDIT: Changed all the layers as you said, still no dice. I made a new base object with my altered mesh and made sure all the property's pointed to it as well.
Also make sure the collision has a mass of at least 1. Anything between 0 and 1 will make the body harder to move in my experience, at 0 it's completely stationary. Also check the max linear velocity.
Ah, good call by Maegfaer; the mass of the bench is 0, so that'll need to be increased - giving it a mass of around 100 might be better than 1 to reduce the chance of slight juddering; you'll have to just experiment with that, sorry. You'll also need to set bit 0 in BSXFlags, to enable Havok (make BSXFlags = 131).
User avatar
Tessa Mullins
 
Posts: 3354
Joined: Mon Oct 22, 2007 5:17 am

Next

Return to V - Skyrim