Player is attached to Saddle using LinkToLocalSpace, Saddle is clothing weighpainted on horse and as normal attachment attached to horse. Position transformation works as expected, but looks like rotation (pitch) is ignored on client simulation.
As you can see on attached video, own player (on white horse) is not properly oriented when horse neigh, but other player (on brown horse) is correctly moving together with spine bone.
Code snippets:
Attaching in action (called ofc on both sides)
void AttachPlayer(PlayerBase player, Object obj) { vector tmPlayer[4]; vector tmTarget[4]; vector tmLocal[4]; Horse_Base target_horse; Class.CastTo(target_horse, obj); player.SetHorseObject(target_horse); target_horse.GetInputController().OverrideMovementSpeed(true,0); //player.SetPosition(obj.ModelToWorld(Vector(-0.6,0.25,-0.8))); //posun pred naskocenim - nepomaha //player.SetPosition(obj.ModelToWorld(Vector(-0.7,0.2,-0.9))); //posun pred naskocenim - nepomaha //Print("horse " + target_horse.GetOrientation() + " plr " + player.GetOrientation()); vector horse_ori = target_horse.GetOrientation(); horse_ori[0] = horse_ori[0]+90; //player.SetOrientation(horse_ori); player.GetTransform( tmPlayer ); //Print("Object " + EntityAI.Cast(obj).GetBoneObject( EntityAI.Cast(obj).GetBoneIndex("horse_saddle_proxy"))); EntityAI saddle = EntityAI.Cast(obj).FindAttachmentBySlotName("HorseSaddle"); if (!saddle) { return; } //DoggoLogger.Log("BONE " + Entity.Cast(obj).GetBoneIndex( "Head" ) + " " + (EntityAI.Cast(obj)).GetBoneObject( 16 )); //Object bone = Entity.Cast(obj).GetBoneObject( 16 ); saddle.GetTransform( tmTarget ); //obj.GetTransform( tmTarget ); //player.SetTransform(tmPlayer); //Print("BONE " + Entity.Cast(obj).GetBoneIndex( "Spine1" )); Math3D.MatrixInvMultiply4( tmTarget, tmPlayer, tmLocal ); if (!player.GetParent()) { int interactionLayer = dBodyGetInteractionLayer(player); interactionLayer &= ~PhxInteractionLayers.CHARACTER; //dBodySetInteractionLayer(player, interactionLayer | PhxInteractionLayers.NOCOLLISION | PhxInteractionLayers.AI_NO_COLLISION); ///dBodySetInteractionLayer(obj, interactionLayer); //dBodySetInteractionLayer(obj, PhxInteractionLayers.DEFAULT | PhxInteractionLayers.AI_COMPLEX | PhxInteractionLayers.FIREGEOM | PhxInteractionLayers.ITEM_LARGE | PhxInteractionLayers.TERRAIN); //dBodySetInteractionLayer(player, PhxInteractionLayers.RAGDOLL ); //dBodySetInteractionLayer(player, PhxInteractionLayers.NOCOLLISION | PhxInteractionLayers.AI_NO_COLLISION ); //dBodySetInteractionLayer(obj, PhxInteractionLayers.NOCOLLISION ); //player.LinkToLocalSpaceOf( obj, tmLocal ); player.LinkToLocalSpaceOf( saddle, tmLocal ); //saddle.RemoveChild( player ); //player.SetOrientation("90 0 90"); //90 -90 90 //saddle.AddChild( player, 13 ); //dBodyEnableGravity(player, false); //dJointCreateFixed(obj, player, "0 0.4 0", "0 0 0", false, 0.1); } }
config,cpp of horse
class Horse_Base : AnimalBase { simulation="dayzanimal"; scope=0; model="Dayz_Horse\Models\horse\horse.p3d"; displayName="#DH_horse"; descriptionShort="Horse"; //aiAgentTemplate="Herbivores_CapreolusCapreolus"; aiAgentTemplate="Horse_Follow"; injuryLevels[]={1,0.5,0.2,0}; clothingType="horse1"; collidesWithCharacterOnDeath=1; attachments[]= { "HorseShoe", "HorseLegs", "HorseBack", "HorseSaddle", "HorseNeck", "HorseHead", "HorseMouth" }; hiddenSelections[]= { "Horse_Body", "Horse_Mane1", "Horse_Mane2", "Horse_Tail" }; DamageSphereAmmos[]= { "MeleeHorse" }; class P3DAttachments { P3DProxies[]= { "spine1" }; BoneNames[]= { "Spine1" }; };
Saddle Proxy
class CfgNonAIVehicles { class ProxyAttachment; class Proxyhorse_saddle_proxy: ProxyAttachment { scope=2; inventorySlot[]= { "HorseSaddle" }; model="\dayz_horse\models\proxy\horse_saddle_proxy.p3d"; };
Slot definition
class Slot_HorseSaddle { name="HorseSaddle"; displayName="#STR_DH_saddle"; selection="slot_horse"; ghostIcon="set:horse_gui image:horse_saddle"; };