Esempio n. 1
0
        public void update(float dt)
        {
            if (pinned)
            {
                if (pinnedTo != null)
                {
                    if (pinnedTo.ShouldDespawn && pinnedTo.DespawnReason?.reason != EnumDespawnReason.Unload)
                    {
                        UnPin();
                        return;
                    }

                    // New ideas:
                    // don't apply force onto the player/entity on compression
                    // apply huge forces onto the player on strong extension (to prevent massive stretching) (just set player motion to 0 or so. or we add a new countermotion field thats used in EntityControlledPhysics?)

                    float weight = pinnedTo.Properties.Weight;
                    float counterTensionStrength = GameMath.Clamp(50f / weight, 0.1f, 2f);

                    bool  extraResist           = (pinnedTo as EntityAgent)?.Controls.Sneak == true || pinnedTo.AnimManager?.IsAnimationActive("sit") == true || pinnedTo.AnimManager?.IsAnimationActive("sleep") == true;
                    float tensionResistStrength = weight / 10f * (extraResist ? 200 : 0);

                    pinOffsetTransform.Identity();
                    pinOffsetTransform.RotateY(pinnedTo.SidedPos.Yaw - pinnedToOffsetStartYaw);
                    tmpvec.Set(pinnedToOffset.X, pinnedToOffset.Y, pinnedToOffset.Z, 1);
                    Vec4f outvec = pinOffsetTransform.TransformVector(tmpvec);

                    EntityPos pos = pinnedTo.SidedPos;
                    Pos.Set(pos.X + outvec.X, pos.Y + outvec.Y, pos.Z + outvec.Z);

                    bool pushable = !(pinnedTo is EntityPlayer eplr && eplr.Player.WorldData.CurrentGameMode == EnumGameMode.Creative);

                    if (pushable && extension > 0) // Do not act on compressive force
                    {
                        float f = counterTensionStrength * dt * 0.003f;
                        pos.Motion.Add(
                            GameMath.Clamp(Math.Abs(TensionDirection.X) - tensionResistStrength, 0, 400) * f * Math.Sign(TensionDirection.X),
                            GameMath.Clamp(Math.Abs(TensionDirection.Y) - tensionResistStrength, 0, 400) * f * Math.Sign(TensionDirection.Y),
                            GameMath.Clamp(Math.Abs(TensionDirection.Z) - tensionResistStrength, 0, 400) * f * Math.Sign(TensionDirection.Z)
                            );
                    }

                    Velocity.Set(0, 0, 0);
                }
                else
                {
                    Velocity.Set(0, 0, 0);

                    accum1s += dt;

                    if (accum1s >= 1)
                    {
                        accum1s = 0;
                        Block block = cs.api.World.BlockAccessor.GetBlock(PinnedToBlockPos);
                        if (!block.HasBehavior <BlockBehaviorRopeTieable>())
                        {
                            UnPin();
                        }
                    }
                }

                return;
            }

            // Calculate the force on this ball
            Vec3f force = Tension.Clone();

            force.Y -= GravityStrength * 10;

            // Calculate the acceleration
            Vec3f acceleration = force * (float)InvMass;

            if (CollideFlags == 0)
            {
                acceleration.X += (float)cs.windSpeed.X * InvMass;
            }


            // Update velocity
            Vec3f nextVelocity = Velocity + (acceleration * dt);

            // Damp the velocity
            nextVelocity *= dampFactor;

            // Collision detection
            float size = 0.1f;

            cs.pp.HandleBoyancy(Pos, nextVelocity, cs.boyant, GravityStrength, dt, size);
            CollideFlags = cs.pp.UpdateMotion(Pos, nextVelocity, size);

            dt *= 0.99f;
            Pos.Add(nextVelocity.X * dt, nextVelocity.Y * dt, nextVelocity.Z * dt);


            Velocity.Set(nextVelocity);
            Tension.Set(0, 0, 0);
        }