public virtual void Init(MyDebrisBaseDescription desc) { HkShape shape; base.Init(null, desc.Model, null, 1f, null); this.LifespanInMiliseconds = MyUtils.GetRandomInt(desc.LifespanMinInMiliseconds, desc.LifespanMaxInMiliseconds); MyDebrisBase.MyDebrisPhysics physics = (MyDebrisBase.MyDebrisPhysics) this.GetPhysics(RigidBodyFlag.RBF_DEBRIS); base.Container.Entity.Physics = physics; float mass = this.CalculateMass(((MyEntity)base.Entity).Render.GetModel().BoundingSphere.Radius); physics.CreatePhysicsShape(out shape, out this.m_massProperties, mass); physics.CreateFromCollisionObject(shape, Vector3.Zero, MatrixD.Identity, new HkMassProperties?(this.m_massProperties), 20); HkMassChangerUtil.Create(physics.RigidBody, -21, 1f, 0f); new HkEasePenetrationAction(physics.RigidBody, 3f) { InitialAllowedPenetrationDepthMultiplier = 10f }.RemoveReference(); base.Container.Entity.Physics.Enabled = false; shape.RemoveReference(); base.m_entity.Save = false; base.Container.Entity.Physics.PlayCollisionCueEnabled = true; base.NeedsUpdate = MyEntityUpdateEnum.EACH_FRAME; base.Container.Entity.NeedsUpdate = MyEntityUpdateEnum.EACH_FRAME; this.m_onCloseCallback = desc.OnCloseAction; }
public void StopManipulation() { if (m_state != MyState.NONE && Owner != null) { var characterMovementState = Owner.GetCurrentMovementState(); switch (characterMovementState) { case MyCharacterMovementEnum.Walking: case MyCharacterMovementEnum.BackWalking: case MyCharacterMovementEnum.WalkingLeftFront: case MyCharacterMovementEnum.WalkingRightFront: case MyCharacterMovementEnum.WalkingLeftBack: case MyCharacterMovementEnum.WalkingRightBack: case MyCharacterMovementEnum.WalkStrafingLeft: case MyCharacterMovementEnum.WalkStrafingRight: case MyCharacterMovementEnum.Running: case MyCharacterMovementEnum.Backrunning: case MyCharacterMovementEnum.RunStrafingLeft: case MyCharacterMovementEnum.RunStrafingRight: case MyCharacterMovementEnum.RunningRightFront: case MyCharacterMovementEnum.RunningRightBack: case MyCharacterMovementEnum.RunningLeftFront: case MyCharacterMovementEnum.RunningLeftBack: Owner.PlayCharacterAnimation("WalkBack", MyBlendOption.Immediate, MyFrameOption.Loop, 0.2f, 1f); break; case MyCharacterMovementEnum.Standing: case MyCharacterMovementEnum.RotatingLeft: case MyCharacterMovementEnum.RotatingRight: case MyCharacterMovementEnum.Flying: Owner.PlayCharacterAnimation("Idle", MyBlendOption.Immediate, MyFrameOption.Loop, 0.2f, 1f); break; } } if (m_constraint != null) { if (OwnerVirtualPhysics != null) { OwnerVirtualPhysics.RemoveConstraint(m_constraint); } m_constraint.Dispose(); m_constraint = null; } if (m_fixedConstraintData != null) { if (!m_fixedConstraintData.IsDisposed) { m_fixedConstraintData.Dispose(); } m_fixedConstraintData = null; } m_headLocalPivotMatrix = Matrix.Zero; m_otherLocalPivotMatrix = Matrix.Zero; if (m_otherEntity != null) { SetTransparent(m_otherEntity); if (m_state == MyState.HOLD) { SetMotionOnClient(m_otherEntity, HkMotionType.Dynamic); // Do not send when disconnecting if (IsOwnerLocalPlayer() && !MyEntities.CloseAllowed && !(m_otherEntity is MyCharacter)) { Sync.Players.RemoveControlledEntity(m_otherEntity); } } m_manipulatedEntitites.Remove(m_otherEntity); var handler = ManipulationStopped; if (handler != null) { handler(m_otherEntity); } m_otherEntity.SyncFlag = true; if (m_otherEntity.Physics != null && m_otherRigidBody != null && !m_otherRigidBody.IsDisposed) { SetManipulated(m_otherEntity, false); //m_otherRigidBody.AngularDamping = m_otherAngularDamping; //m_otherRigidBody.LinearDamping = m_otherLinearDamping; if (m_otherEntity is MyCharacter) { m_otherEntity.Physics.SetRagdollDefaults(); } else { m_otherRigidBody.Restitution = m_otherRestitution; m_otherRigidBody.MaxLinearVelocity = m_otherMaxLinearVelocity; m_otherRigidBody.MaxAngularVelocity = m_otherMaxAngularVelocity; if (m_massChange != null) { m_massChange.Remove(); } m_massChange = null; // Clamp output velocity m_otherRigidBody.LinearVelocity = Vector3.Clamp(m_otherRigidBody.LinearVelocity, -2 * Vector3.One, 2 * Vector3.One); m_otherRigidBody.AngularVelocity = Vector3.Clamp(m_otherRigidBody.AngularVelocity, -Vector3.One * (float)Math.PI, Vector3.One * (float)Math.PI); if (!m_otherRigidBody.IsActive) { m_otherRigidBody.Activate(); } m_otherRigidBody.EnableDeactivation = false; m_otherRigidBody.EnableDeactivation = true; //resets deactivation counter } m_otherRigidBody = null; } m_otherEntity.OnClosing -= OtherEntity_OnClosing; m_otherEntity = null; } m_constraintInitialized = false; RemoveOwnerVirtualPhysics(); if (Owner != null) { Owner.ManipulatedEntity = null; } m_state = MyState.NONE; }
public void StartManipulation(MyState state, MyEntity otherEntity, Vector3D hitPosition, ref MatrixD ownerWorldHeadMatrix, bool fromServer = false) { Debug.Assert(m_constraintInitialized == false); // Commenting this out to allow picking up dead bodies and characters if (otherEntity is MyCharacter) { return; } if (Owner == null) { Debug.Assert(!fromServer, "Desync!"); return; } if (otherEntity.Physics == null) { return; } m_otherRigidBody = otherEntity.Physics.RigidBody; m_otherPhysicsBody = otherEntity.Physics; if (otherEntity is MyCharacter) { if (!(otherEntity as MyCharacter).IsDead || !((otherEntity as MyCharacter).Components.Has <MyCharacterRagdollComponent>() && (otherEntity as MyCharacter).Components.Get <MyCharacterRagdollComponent>().IsRagdollActivated)) { Debug.Assert(!fromServer, "Desync!"); return; } m_otherRigidBody = (otherEntity as MyCharacter).Physics.Ragdoll.GetRootRigidBody(); } // else (!otherEntity.Physics.RigidBody.InWorld) // Do we need to check if the body is in the world when this was returned byt RayCast ? Commenting this out for now.. var characterMovementState = Owner.GetCurrentMovementState(); if (!CanManipulate(characterMovementState)) { Debug.Assert(!fromServer, "Desync!"); return; } if (!CanManipulateEntity(otherEntity)) { Debug.Assert(!fromServer, "Desync!"); return; } m_otherRigidBody.Activate(); Vector3D hitUp = Vector3D.Up; Vector3D hitRight; double dot = Vector3D.Dot(ownerWorldHeadMatrix.Forward, hitUp); if (dot == 1 || dot == -1) { hitRight = ownerWorldHeadMatrix.Right; } else { hitRight = Vector3D.Cross(ownerWorldHeadMatrix.Forward, hitUp); hitRight.Normalize(); } Vector3D hitForward = Vector3D.Cross(hitUp, hitRight); hitForward.Normalize(); // Matrix of constraint for other body in world MatrixD otherWorldMatrix = MatrixD.Identity; otherWorldMatrix.Forward = hitForward; otherWorldMatrix.Right = hitRight; otherWorldMatrix.Up = hitUp; otherWorldMatrix.Translation = hitPosition; const float headPivotOffset = 1.5f; MatrixD headPivotWorldMatrix = ownerWorldHeadMatrix; headPivotWorldMatrix.Translation = ownerWorldHeadMatrix.Translation + headPivotOffset * ownerWorldHeadMatrix.Forward; //float distanceToHead = (float)(headPivotWorldMatrix.Translation - otherWorldMatrix.Translation).Length(); //distanceToHead = MathHelper.Clamp(distanceToHead, 0.6f, 2.5f); // Matrix of constraint for other body in local m_otherLocalPivotMatrix = (Matrix)(otherWorldMatrix * otherEntity.PositionComp.WorldMatrixNormalizedInv); m_otherWorldPivotOrigin = otherWorldMatrix.Translation; MatrixD ownerWorldMatrixInverse = MatrixD.Normalize(MatrixD.Invert(ownerWorldHeadMatrix)); m_headLocalPivotMatrix = Matrix.Identity; m_headLocalPivotMatrix.Translation = Vector3D.Transform(headPivotWorldMatrix.Translation, ownerWorldMatrixInverse); HkConstraintData data; if (state == MyState.HOLD) { if (!fromServer) { float mass = 0; if (otherEntity is MyCubeGrid) { var group = MyCubeGridGroups.Static.Physical.GetGroup((otherEntity as MyCubeGrid)); foreach (var node in group.Nodes) { if (node.NodeData.IsStatic) //fixed constraint on part connected to static grid isnt good idea { return; } mass += node.NodeData.Physics.Mass; } mass = GetRealMass(mass); } else if (otherEntity is MyCharacter) { mass = (otherEntity as MyCharacter).Definition.Mass; } else { mass = GetRealMass(m_otherRigidBody.Mass); } // Player can hold large projectile (~222kg) if ((mass > 210) || ((otherEntity is MyCharacter) && (otherEntity.Physics.Mass > 210))) { return; } } if (!CreateOwnerVirtualPhysics()) { return; } if (IsOwnerLocalPlayer()) { var controllingPlayer = Sync.Players.GetControllingPlayer(otherEntity); if (controllingPlayer != null) { RemoveOwnerVirtualPhysics(); return; } if (!(otherEntity is MyCharacter)) // this would cause to start controlling the dead body.. { Sync.Players.TrySetControlledEntity(Owner.ControllerInfo.Controller.Player.Id, otherEntity); } } SetMotionOnClient(otherEntity, HkMotionType.Dynamic); data = CreateFixedConstraintData(ref m_otherLocalPivotMatrix, headPivotOffset); if (otherEntity is MyCharacter) { if (MyFakes.MANIPULATION_TOOL_VELOCITY_LIMIT) { HkMalleableConstraintData mcData = data as HkMalleableConstraintData; mcData.Strength = 0.005f; } else { HkFixedConstraintData fcData = data as HkFixedConstraintData; fcData.MaximumAngularImpulse = 0.0005f; fcData.MaximumLinearImpulse = 0.0005f; fcData.BreachImpulse = 0.0004f; } } } else { if (!CreateOwnerVirtualPhysics()) { return; } data = CreateBallAndSocketConstraintData(ref m_otherLocalPivotMatrix, ref m_headLocalPivotMatrix); if (otherEntity is MyCharacter) { HkMalleableConstraintData mcData = data as HkMalleableConstraintData; mcData.Strength = 0.005f; } } m_otherEntity = otherEntity; m_otherEntity.OnClosing += OtherEntity_OnClosing; //m_otherAngularDamping = m_otherRigidBody.AngularDamping; //m_otherLinearDamping = m_otherRigidBody.LinearDamping; m_otherRestitution = m_otherRigidBody.Restitution; m_otherMaxLinearVelocity = m_otherRigidBody.MaxLinearVelocity; m_otherMaxAngularVelocity = m_otherRigidBody.MaxAngularVelocity; SetManipulated(m_otherEntity, true); if (state == MyState.HOLD) { if (m_otherEntity is MyCharacter) { foreach (var body in m_otherEntity.Physics.Ragdoll.RigidBodies) { //body.AngularDamping = TARGET_ANGULAR_DAMPING; //body.LinearDamping = TARGET_LINEAR_DAMPING; //body.Mass = 5; body.Restitution = TARGET_RESTITUTION; body.MaxLinearVelocity = m_limitingLinearVelocity; body.MaxAngularVelocity = (float)Math.PI * 0.1f; } } else { m_massChange = HkMassChangerUtil.Create(m_otherRigidBody, int.MaxValue, 1, 0.001f); //m_otherRigidBody.AngularDamping = TARGET_ANGULAR_DAMPING; //m_otherRigidBody.LinearDamping = TARGET_LINEAR_DAMPING; m_otherRigidBody.Restitution = TARGET_RESTITUTION; m_otherRigidBody.MaxLinearVelocity = m_limitingLinearVelocity; m_otherRigidBody.MaxAngularVelocity = (float)Math.PI; } const float holdingTransparency = 0.4f; SetTransparent(otherEntity, holdingTransparency); } m_constraint = new HkConstraint(m_otherRigidBody, OwnerVirtualPhysics.RigidBody, data); OwnerVirtualPhysics.AddConstraint(m_constraint); m_constraintCreationTime = MySandboxGame.Static.UpdateTime; m_state = state; m_previousCharacterMovementState = Owner.GetCurrentMovementState(); if (m_state == MyState.HOLD) { Owner.PlayCharacterAnimation("PickLumber", MyBlendOption.Immediate, MyFrameOption.PlayOnce, 0.2f, 1f); } else { Owner.PlayCharacterAnimation("PullLumber", MyBlendOption.Immediate, MyFrameOption.PlayOnce, 0.2f, 1f); } m_manipulatedEntitites.Add(m_otherEntity); Owner.ManipulatedEntity = m_otherEntity; var handler = ManipulationStarted; if (handler != null) { handler(m_otherEntity); } }
public void StopManipulation() { if (m_state != MyState.NONE && Owner != null) { var characterMovementState = Owner.GetCurrentMovementState(); switch (characterMovementState) { case MyCharacterMovementEnum.Walking: case MyCharacterMovementEnum.BackWalking: case MyCharacterMovementEnum.WalkingLeftFront: case MyCharacterMovementEnum.WalkingRightFront: case MyCharacterMovementEnum.WalkingLeftBack: case MyCharacterMovementEnum.WalkingRightBack: case MyCharacterMovementEnum.WalkStrafingLeft: case MyCharacterMovementEnum.WalkStrafingRight: case MyCharacterMovementEnum.Running: case MyCharacterMovementEnum.Backrunning: case MyCharacterMovementEnum.RunStrafingLeft: case MyCharacterMovementEnum.RunStrafingRight: case MyCharacterMovementEnum.RunningRightFront: case MyCharacterMovementEnum.RunningRightBack: case MyCharacterMovementEnum.RunningLeftFront: case MyCharacterMovementEnum.RunningLeftBack: Owner.PlayCharacterAnimation("WalkBack", true, MyPlayAnimationMode.Immediate | MyPlayAnimationMode.Play, 0.2f, 1f); break; case MyCharacterMovementEnum.Standing: case MyCharacterMovementEnum.RotatingLeft: case MyCharacterMovementEnum.RotatingRight: case MyCharacterMovementEnum.Flying: Owner.PlayCharacterAnimation("Idle", true, MyPlayAnimationMode.Immediate | MyPlayAnimationMode.Play, 0.2f, 1f); break; } } if (m_constraint != null) { if (Owner != null && Owner.VirtualPhysics != null) { Owner.VirtualPhysics.RemoveConstraint(m_constraint); } m_constraint.Dispose(); m_constraint = null; } if (m_fixedConstraintData != null) { if (!m_fixedConstraintData.IsDisposed) { m_fixedConstraintData.Dispose(); } m_fixedConstraintData = null; } m_headLocalPivotMatrix = Matrix.Zero; m_otherLocalPivotMatrix = Matrix.Zero; if (m_otherEntity != null) { SetTransparent(m_otherEntity); SetTransparent(m_otherEntity); if (m_state == MyState.HOLD) { SetMotionOnClient(m_otherEntity, HkMotionType.Keyframed); } m_manipulatedEntitites.Remove(m_otherEntity); m_otherEntity.SyncFlag = true; if (m_otherEntity.Physics != null && m_otherRigidBody != null && !m_otherRigidBody.IsDisposed) { SetManipulated(m_otherEntity, false); //m_otherRigidBody.AngularDamping = m_otherAngularDamping; //m_otherRigidBody.LinearDamping = m_otherLinearDamping; m_otherRigidBody.Restitution = m_otherRestitution; m_otherRigidBody.MaxLinearVelocity = m_otherMaxLinearVelocity; m_otherRigidBody.MaxAngularVelocity = m_otherMaxAngularVelocity; if (m_massChange != null) { m_massChange.Remove(); } m_massChange = null; // Clamp output velocity m_otherRigidBody.LinearVelocity = Vector3.Clamp(m_otherRigidBody.LinearVelocity, -2 * Vector3.One, 2 * Vector3.One); m_otherRigidBody.AngularVelocity = Vector3.Clamp(m_otherRigidBody.AngularVelocity, -Vector3.One * (float)Math.PI, Vector3.One * (float)Math.PI); if (!m_otherRigidBody.IsActive) { m_otherRigidBody.Activate(); } m_otherRigidBody.EnableDeactivation = false; m_otherRigidBody.EnableDeactivation = true; //resets deactivation counter m_otherRigidBody = null; } m_otherEntity.OnClosing -= OtherEntity_OnClosing; m_otherEntity = null; } m_constraintInitialized = false; if (Owner != null) { Owner.ManipulatedEntity = null; } m_state = MyState.NONE; }
private void InitInternal() { MyPhysicalItemDefinition physicalItemDefinition = MyDefinitionManager.Static.GetPhysicalItemDefinition(this.Item.Content); this.m_health = physicalItemDefinition.Health; this.VoxelMaterial = null; if (physicalItemDefinition.VoxelMaterial != MyStringHash.NullOrEmpty) { this.VoxelMaterial = MyDefinitionManager.Static.GetVoxelMaterialDefinition(physicalItemDefinition.VoxelMaterial.String); } else if (this.Item.Content is MyObjectBuilder_Ore) { string subtypeName = physicalItemDefinition.Id.SubtypeName; string materialName = (this.Item.Content as MyObjectBuilder_Ore).GetMaterialName(); bool flag = (this.Item.Content as MyObjectBuilder_Ore).HasMaterialName(); foreach (MyVoxelMaterialDefinition definition2 in MyDefinitionManager.Static.GetVoxelMaterialDefinitions()) { if ((flag && (materialName == definition2.Id.SubtypeName)) || (!flag && (subtypeName == definition2.MinedOre))) { this.VoxelMaterial = definition2; break; } } } if ((this.VoxelMaterial != null) && (this.VoxelMaterial.DamagedMaterial != MyStringHash.NullOrEmpty)) { this.VoxelMaterial = MyDefinitionManager.Static.GetVoxelMaterialDefinition(this.VoxelMaterial.DamagedMaterial.ToString()); } string model = physicalItemDefinition.Model; if (physicalItemDefinition.HasModelVariants) { int length = physicalItemDefinition.Models.Length; this.m_modelVariant = this.m_modelVariant % length; model = physicalItemDefinition.Models[this.m_modelVariant]; } else if ((this.Item.Content is MyObjectBuilder_Ore) && (this.VoxelMaterial != null)) { float num5 = 50f; model = MyDebris.GetAmountBasedDebrisVoxel(Math.Max((float)this.Item.Amount, num5)); } float scale = 0.7f; this.FormatDisplayName(this.m_displayedText, this.Item); float?nullable = null; this.Init(this.m_displayedText, model, null, nullable, null); HkMassProperties massProperties = new HkMassProperties(); float mass = MathHelper.Clamp((float)((MyPerGameSettings.Destruction ? MyDestructionHelper.MassToHavok(physicalItemDefinition.Mass) : physicalItemDefinition.Mass) * ((float)this.Item.Amount)), (float)3f, (float)100000f); HkShape shape = this.GetPhysicsShape(mass, scale, out massProperties); massProperties.Mass = mass; Matrix identity = Matrix.Identity; if (this.Physics != null) { this.Physics.Close(); } this.Physics = new MyPhysicsBody(this, RigidBodyFlag.RBF_DEBRIS); int collisionFilter = (mass > MyPerGameSettings.MinimumLargeShipCollidableMass) ? 0x17 : 10; this.Physics.LinearDamping = 0.1f; this.Physics.AngularDamping = 2f; if (!shape.IsConvex || (shape.ShapeType == HkShapeType.Sphere)) { this.Physics.CreateFromCollisionObject(shape, Vector3.Zero, MatrixD.Identity, new HkMassProperties?(massProperties), collisionFilter); this.Physics.Enabled = true; } else { HkConvexTransformShape shape2 = new HkConvexTransformShape((HkConvexShape)shape, ref identity, HkReferencePolicy.None); this.Physics.CreateFromCollisionObject((HkShape)shape2, Vector3.Zero, MatrixD.Identity, new HkMassProperties?(massProperties), collisionFilter); this.Physics.Enabled = true; shape2.Base.RemoveReference(); } this.Physics.Friction = 2f; this.Physics.MaterialType = this.EvaluatePhysicsMaterial(physicalItemDefinition.PhysicalMaterial); this.Physics.PlayCollisionCueEnabled = true; this.Physics.RigidBody.ContactSoundCallbackEnabled = true; base.NeedsUpdate = MyEntityUpdateEnum.EACH_FRAME; this.Physics.RigidBody.SetProperty(HkCharacterRigidBody.FLOATING_OBJECT, 0f); this.Physics.RigidBody.CenterOfMassLocal = Vector3.Zero; HkMassChangerUtil.Create(this.Physics.RigidBody, 0x10200, 1f, 0f); }
public void StartManipulation(MyState state, MyEntity otherEntity, Vector3D hitPosition, ref MatrixD ownerWorldHeadMatrix) { Debug.Assert(m_constraintInitialized == false); // Commenting this out to allow picking up dead bodies and characters //if (otherEntity is MyCharacter) // return; if (Owner == null || Owner.VirtualPhysics == null || !Owner.VirtualPhysics.RigidBody.InWorld) { return; } var ownerRigidBody = Owner.VirtualPhysics.RigidBody; if (otherEntity.Physics == null) { return; } m_otherRigidBody = otherEntity.Physics.RigidBody; if (otherEntity is MyCharacter) { if (!(otherEntity as MyCharacter).IsDead || !(otherEntity as MyCharacter).IsRagdollActivated) { return; } m_otherRigidBody = (otherEntity as MyCharacter).Physics.Ragdoll.GetRootRigidBody(); } // else (!otherEntity.Physics.RigidBody.InWorld) // Do we need to check if the body is in the world when this was returned byt RayCast ? Commenting this out for now.. var characterMovementState = Owner.GetCurrentMovementState(); if (!CanManipulate(characterMovementState)) { return; } if (!CanManipulateEntity(otherEntity)) { return; } // PetrM:TODO: Make all client grids dynamic. if (!(otherEntity is MyCharacter && (otherEntity as MyCharacter).IsRagdollActivated) && state == MyState.HOLD) // In case of picking up a ragdoll don't turn off and on the physics { otherEntity.Physics.Enabled = false; otherEntity.SyncFlag = false; m_otherRigidBody.UpdateMotionType(HkMotionType.Dynamic); otherEntity.Physics.Enabled = true; // HACK: This is here only because disabling and enabling physics puts constraints into inconsistent state. otherEntity.RaisePhysicsChanged(); } Owner.VirtualPhysics.RigidBody.Activate(); m_otherRigidBody.Activate(); Vector3D hitUp = Vector3D.Up; Vector3D hitRight; double dot = Vector3D.Dot(ownerWorldHeadMatrix.Forward, hitUp); if (dot == 1 || dot == -1) { hitRight = ownerWorldHeadMatrix.Right; } else { hitRight = Vector3D.Cross(ownerWorldHeadMatrix.Forward, hitUp); hitRight.Normalize(); } Vector3D hitForward = Vector3D.Cross(hitUp, hitRight); hitForward.Normalize(); // Matrix of constraint for other body in world MatrixD otherWorldMatrix = MatrixD.Identity; otherWorldMatrix.Forward = hitForward; otherWorldMatrix.Right = hitRight; otherWorldMatrix.Up = hitUp; otherWorldMatrix.Translation = hitPosition; const float headPivotOffset = 1.5f; MatrixD headPivotWorldMatrix = ownerWorldHeadMatrix; headPivotWorldMatrix.Translation = ownerWorldHeadMatrix.Translation + headPivotOffset * ownerWorldHeadMatrix.Forward; //float distanceToHead = (float)(headPivotWorldMatrix.Translation - otherWorldMatrix.Translation).Length(); //distanceToHead = MathHelper.Clamp(distanceToHead, 0.6f, 2.5f); // Matrix of constraint for other body in local m_otherLocalPivotMatrix = (Matrix)(otherWorldMatrix * otherEntity.PositionComp.WorldMatrixNormalizedInv); m_otherWorldPivotOrigin = otherWorldMatrix.Translation; MatrixD ownerWorldMatrixInverse = MatrixD.Normalize(MatrixD.Invert(ownerWorldHeadMatrix)); m_headLocalPivotMatrix = Matrix.Identity; m_headLocalPivotMatrix.Translation = Vector3D.Transform(headPivotWorldMatrix.Translation, ownerWorldMatrixInverse); HkConstraintData data; if (state == MyState.HOLD) { float mass = 0; if (otherEntity is MyCubeGrid) { var group = MyCubeGridGroups.Static.Physical.GetGroup((otherEntity as MyCubeGrid)); foreach (var node in group.Nodes) { mass += node.NodeData.Physics.Mass; } mass = GetRealMass(mass); } else { mass = GetRealMass(otherEntity.Physics.Mass); } // Player can hold large projectile (~222kg) if ((mass <= 210) || ((otherEntity is MyCharacter) && (otherEntity.Physics.Mass < 210))) { data = CreateFixedConstraintData(ref m_otherLocalPivotMatrix, headPivotOffset); } else { return; } if (otherEntity is MyCharacter) { if (MyFakes.MANIPULATION_TOOL_VELOCITY_LIMIT) { HkMalleableConstraintData mcData = data as HkMalleableConstraintData; mcData.Strength = 0.005f; } else { HkFixedConstraintData fcData = data as HkFixedConstraintData; fcData.MaximumAngularImpulse = 2.0f; fcData.MaximumLinearImpulse = 2.0f; } } } else { data = CreateBallAndSocketConstraintData(ref m_otherLocalPivotMatrix, ref m_headLocalPivotMatrix); if (otherEntity is MyCharacter) { HkMalleableConstraintData mcData = data as HkMalleableConstraintData; mcData.Strength = 0.005f; } } m_otherEntity = otherEntity; m_otherEntity.OnClosing += OtherEntity_OnClosing; //m_otherAngularDamping = m_otherRigidBody.AngularDamping; //m_otherLinearDamping = m_otherRigidBody.LinearDamping; m_otherRestitution = m_otherRigidBody.Restitution; m_otherMaxLinearVelocity = m_otherRigidBody.MaxLinearVelocity; m_otherMaxAngularVelocity = m_otherRigidBody.MaxAngularVelocity; SetManipulated(m_otherEntity, true); if (state == MyState.HOLD) { m_massChange = HkMassChangerUtil.Create(m_otherRigidBody, int.MaxValue, 1, 0.001f); //m_otherRigidBody.AngularDamping = TARGET_ANGULAR_DAMPING; //m_otherRigidBody.LinearDamping = TARGET_LINEAR_DAMPING; m_otherRigidBody.Restitution = TARGET_RESTITUTION; m_otherRigidBody.MaxLinearVelocity = m_limitingLinearVelocity; m_otherRigidBody.MaxAngularVelocity = (float)Math.PI; if (m_otherEntity is MyCharacter) { foreach (var body in m_otherEntity.Physics.Ragdoll.RigidBodies) { //body.AngularDamping = TARGET_ANGULAR_DAMPING; //body.LinearDamping = TARGET_LINEAR_DAMPING; body.Restitution = TARGET_RESTITUTION; body.MaxLinearVelocity = m_limitingLinearVelocity; body.MaxAngularVelocity = (float)Math.PI; } } const float holdingTransparency = 0.4f; SetTransparent(otherEntity, holdingTransparency); //TODO jt: why it must be called twice? SetTransparent(otherEntity, holdingTransparency); } m_constraint = new HkConstraint(m_otherRigidBody, Owner.VirtualPhysics.RigidBody, data); Owner.VirtualPhysics.AddConstraint(m_constraint); m_constraintCreationTime = MySandboxGame.Static.UpdateTime; m_state = state; m_previousCharacterMovementState = Owner.GetCurrentMovementState(); if (m_state == MyState.HOLD) { Owner.PlayCharacterAnimation("PickLumber", false, MyPlayAnimationMode.Immediate | MyPlayAnimationMode.Play, 0.2f, 1f); } else { Owner.PlayCharacterAnimation("PullLumber", false, MyPlayAnimationMode.Immediate | MyPlayAnimationMode.Play, 0.2f, 1f); } m_manipulatedEntitites.Add(m_otherEntity); Owner.ManipulatedEntity = m_otherEntity; }