Example #1
0
 partial void UpdateProjSpecific(float deltaTime)
 {
     LimbJoints.ForEach(j => j.UpdateDeformations(deltaTime));
     foreach (var deformation in SpriteDeformations)
     {
         if (deformation.DeformationParams.UseMovementSine)
         {
             if (this is AnimController animator)
             {
                 //deformation.Phase = MathUtils.WrapAngleTwoPi(animator.WalkPos + MathHelper.Pi);
                 deformation.Phase = MathUtils.WrapAngleTwoPi(animator.WalkPos * deformation.DeformationParams.Frequency + MathHelper.Pi * deformation.DeformationParams.SineOffset);
             }
         }
         else
         {
             deformation.Update(deltaTime);
         }
     }
 }
Example #2
0
        public void ServerWrite(IWriteMessage msg, Client c, object[] extraData = null)
        {
            float MaxVel        = NetConfig.MaxPhysicsBodyVelocity;
            float MaxAngularVel = NetConfig.MaxPhysicsBodyAngularVelocity;

            msg.Write(SimPosition.X);
            msg.Write(SimPosition.Y);

#if DEBUG
            if (Math.Abs(FarseerBody.LinearVelocity.X) > MaxVel ||
                Math.Abs(FarseerBody.LinearVelocity.Y) > MaxVel)
            {
                DebugConsole.ThrowError($"Entity velocity out of range ({(UserData?.ToString() ?? "null")}, {FarseerBody.LinearVelocity})");
            }
#endif

            msg.Write(FarseerBody.Awake);
            msg.Write(FarseerBody.FixedRotation);

            if (!FarseerBody.FixedRotation)
            {
                msg.WriteRangedSingle(MathUtils.WrapAngleTwoPi(FarseerBody.Rotation), 0.0f, MathHelper.TwoPi, 8);
            }
            if (FarseerBody.Awake)
            {
                FarseerBody.Enabled        = true;
                FarseerBody.LinearVelocity = new Vector2(
                    MathHelper.Clamp(FarseerBody.LinearVelocity.X, -MaxVel, MaxVel),
                    MathHelper.Clamp(FarseerBody.LinearVelocity.Y, -MaxVel, MaxVel));
                msg.WriteRangedSingle(FarseerBody.LinearVelocity.X, -MaxVel, MaxVel, 12);
                msg.WriteRangedSingle(FarseerBody.LinearVelocity.Y, -MaxVel, MaxVel, 12);
                if (!FarseerBody.FixedRotation)
                {
                    FarseerBody.AngularVelocity = MathHelper.Clamp(FarseerBody.AngularVelocity, -MaxAngularVel, MaxAngularVel);
                    msg.WriteRangedSingle(FarseerBody.AngularVelocity, -MaxAngularVel, MaxAngularVel, 8);
                }
            }

            msg.WritePadBits();
        }
        public void ServerWrite(NetBuffer msg, Client c, object[] extraData = null)
        {
            float MaxVel        = NetConfig.MaxPhysicsBodyVelocity;
            float MaxAngularVel = NetConfig.MaxPhysicsBodyAngularVelocity;

            msg.Write(SimPosition.X);
            msg.Write(SimPosition.Y);

#if DEBUG
            if (Math.Abs(body.LinearVelocity.X) > MaxVel ||
                Math.Abs(body.LinearVelocity.Y) > MaxVel)
            {
                DebugConsole.ThrowError("Item velocity out of range (" + body.LinearVelocity + ")");
            }
#endif

            msg.Write(FarseerBody.Awake);
            msg.Write(FarseerBody.FixedRotation);

            if (!FarseerBody.FixedRotation)
            {
                msg.WriteRangedSingle(MathUtils.WrapAngleTwoPi(body.Rotation), 0.0f, MathHelper.TwoPi, 8);
            }
            if (FarseerBody.Awake)
            {
                body.Enabled        = true;
                body.LinearVelocity = new Vector2(
                    MathHelper.Clamp(body.LinearVelocity.X, -MaxVel, MaxVel),
                    MathHelper.Clamp(body.LinearVelocity.Y, -MaxVel, MaxVel));
                msg.WriteRangedSingle(body.LinearVelocity.X, -MaxVel, MaxVel, 12);
                msg.WriteRangedSingle(body.LinearVelocity.Y, -MaxVel, MaxVel, 12);
                if (!FarseerBody.FixedRotation)
                {
                    body.AngularVelocity = MathHelper.Clamp(body.AngularVelocity, -MaxAngularVel, MaxAngularVel);
                    msg.WriteRangedSingle(body.AngularVelocity, -MaxAngularVel, MaxAngularVel, 8);
                }
            }

            msg.WritePadBits();
        }
        void UpdateSineAnim(float deltaTime)
        {
            if (CurrentSwimParams == null)
            {
                return;
            }
            movement = TargetMovement;

            if (movement.LengthSquared() > 0.00001f)
            {
                Collider.LinearVelocity = Vector2.Lerp(Collider.LinearVelocity, movement, 0.5f);
            }

            //limbs are disabled when simple physics is enabled, no need to move them
            if (SimplePhysicsEnabled)
            {
                return;
            }

            MainLimb.PullJointEnabled = true;
            //MainLimb.PullJointWorldAnchorB = Collider.SimPosition;

            if (movement.LengthSquared() < 0.00001f)
            {
                WalkPos = MathHelper.SmoothStep(WalkPos, MathHelper.PiOver2, deltaTime * 5);
                MainLimb.PullJointWorldAnchorB = Collider.SimPosition;
                return;
            }

            Vector2 transformedMovement = reverse ? -movement : movement;
            float   movementAngle       = MathUtils.VectorToAngle(transformedMovement) - MathHelper.PiOver2;
            float   mainLimbAngle       = 0;

            if (MainLimb.type == LimbType.Torso && TorsoAngle.HasValue)
            {
                mainLimbAngle = TorsoAngle.Value;
            }
            else if (MainLimb.type == LimbType.Head && HeadAngle.HasValue)
            {
                mainLimbAngle = HeadAngle.Value;
            }
            mainLimbAngle *= Dir;
            while (MainLimb.Rotation - (movementAngle + mainLimbAngle) > MathHelper.Pi)
            {
                movementAngle += MathHelper.TwoPi;
            }
            while (MainLimb.Rotation - (movementAngle + mainLimbAngle) < -MathHelper.Pi)
            {
                movementAngle -= MathHelper.TwoPi;
            }

            if (CurrentSwimParams.RotateTowardsMovement)
            {
                Collider.SmoothRotate(movementAngle, CurrentSwimParams.SteerTorque);
                if (TorsoAngle.HasValue)
                {
                    Limb torso = GetLimb(LimbType.Torso);
                    if (torso != null)
                    {
                        SmoothRotateWithoutWrapping(torso, movementAngle + TorsoAngle.Value * Dir, MainLimb, TorsoTorque);
                    }
                }
                if (HeadAngle.HasValue)
                {
                    Limb head = GetLimb(LimbType.Head);
                    if (head != null)
                    {
                        SmoothRotateWithoutWrapping(head, movementAngle + HeadAngle.Value * Dir, MainLimb, HeadTorque);
                    }
                }
                if (TailAngle.HasValue)
                {
                    Limb tail = GetLimb(LimbType.Tail);
                    if (tail != null)
                    {
                        SmoothRotateWithoutWrapping(tail, movementAngle + TailAngle.Value * Dir, MainLimb, TailTorque);
                    }
                }
            }
            else
            {
                movementAngle = Dir > 0 ? -MathHelper.PiOver2 : MathHelper.PiOver2;
                if (reverse)
                {
                    movementAngle = MathUtils.WrapAngleTwoPi(movementAngle - MathHelper.Pi);
                }
                if (MainLimb.type == LimbType.Head && HeadAngle.HasValue)
                {
                    Collider.SmoothRotate(HeadAngle.Value * Dir, CurrentSwimParams.SteerTorque);
                }
                else if (MainLimb.type == LimbType.Torso && TorsoAngle.HasValue)
                {
                    Collider.SmoothRotate(TorsoAngle.Value * Dir, CurrentSwimParams.SteerTorque);
                }
                if (TorsoAngle.HasValue)
                {
                    Limb torso = GetLimb(LimbType.Torso);
                    torso?.body.SmoothRotate(TorsoAngle.Value * Dir, TorsoTorque);
                }
                if (HeadAngle.HasValue)
                {
                    Limb head = GetLimb(LimbType.Head);
                    head?.body.SmoothRotate(HeadAngle.Value * Dir, HeadTorque);
                }
                if (TailAngle.HasValue)
                {
                    Limb tail = GetLimb(LimbType.Tail);
                    tail?.body.SmoothRotate(TailAngle.Value * Dir, TailTorque);
                }
            }

            var waveLength    = Math.Abs(CurrentSwimParams.WaveLength * RagdollParams.JointScale);
            var waveAmplitude = Math.Abs(CurrentSwimParams.WaveAmplitude);

            if (waveLength > 0 && waveAmplitude > 0)
            {
                WalkPos -= transformedMovement.Length() / Math.Abs(waveLength);
                WalkPos  = MathUtils.WrapAngleTwoPi(WalkPos);
            }

            foreach (var limb in Limbs)
            {
                switch (limb.type)
                {
                case LimbType.LeftFoot:
                case LimbType.RightFoot:
                    if (CurrentSwimParams.FootAnglesInRadians.ContainsKey(limb.limbParams.ID))
                    {
                        SmoothRotateWithoutWrapping(limb, movementAngle + CurrentSwimParams.FootAnglesInRadians[limb.limbParams.ID] * Dir, MainLimb, FootTorque);
                    }
                    break;

                case LimbType.Tail:
                    if (waveLength > 0 && waveAmplitude > 0)
                    {
                        float waveRotation = (float)Math.Sin(WalkPos);
                        limb.body.ApplyTorque(waveRotation * limb.Mass * CurrentSwimParams.TailTorque * waveAmplitude);
                    }
                    break;
                }
            }

            for (int i = 0; i < Limbs.Length; i++)
            {
                if (Limbs[i].SteerForce <= 0.0f)
                {
                    continue;
                }

                Vector2 pullPos = Limbs[i].PullJointWorldAnchorA;
                Limbs[i].body.ApplyForce(movement * Limbs[i].SteerForce * Limbs[i].Mass, pullPos);
            }

            Vector2 mainLimbDiff = MainLimb.PullJointWorldAnchorB - MainLimb.SimPosition;

            if (CurrentSwimParams.UseSineMovement)
            {
                MainLimb.PullJointWorldAnchorB = Vector2.SmoothStep(
                    MainLimb.PullJointWorldAnchorB,
                    Collider.SimPosition,
                    mainLimbDiff.LengthSquared() > 10.0f ? 1.0f : (float)Math.Abs(Math.Sin(WalkPos)));
            }
            else
            {
                //MainLimb.PullJointWorldAnchorB = Collider.SimPosition;
                MainLimb.PullJointWorldAnchorB = Vector2.Lerp(
                    MainLimb.PullJointWorldAnchorB,
                    Collider.SimPosition,
                    mainLimbDiff.LengthSquared() > 10.0f ? 1.0f : 0.5f);
            }

            floorY = Limbs[0].SimPosition.Y;
        }
        public override void UpdateAnim(float deltaTime)
        {
            if (Frozen)
            {
                return;
            }
            if (MainLimb == null)
            {
                return;
            }

            if (!character.AllowInput)
            {
                levitatingCollider = false;
                Collider.FarseerBody.FixedRotation = false;
                if (GameMain.NetworkMember == null || !GameMain.NetworkMember.IsClient)
                {
                    Collider.LinearVelocity            = MainLimb.LinearVelocity;
                    Collider.FarseerBody.FixedRotation = false;
                    Collider.SetTransformIgnoreContacts(MainLimb.SimPosition, MainLimb.Rotation);
                }
                if (character.IsDead && deathAnimTimer < deathAnimDuration)
                {
                    deathAnimTimer += deltaTime;
                    UpdateDying(deltaTime);
                }
                return;
            }
            else
            {
                deathAnimTimer = 0.0f;
            }

            //re-enable collider
            if (!Collider.Enabled)
            {
                var lowestLimb = FindLowestLimb();

                Collider.SetTransform(new Vector2(
                                          Collider.SimPosition.X,
                                          Math.Max(lowestLimb.SimPosition.Y + (Collider.radius + Collider.height / 2), Collider.SimPosition.Y)),
                                      0.0f);

                Collider.Enabled = true;
            }

            ResetPullJoints();

            if (strongestImpact > 0.0f)
            {
                character.Stun  = MathHelper.Clamp(strongestImpact * 0.5f, character.Stun, 5.0f);
                strongestImpact = 0.0f;
            }

            if (inWater && !forceStanding)
            {
                Collider.FarseerBody.FixedRotation = false;
                UpdateSineAnim(deltaTime);
            }
            else if (CanEnterSubmarine && (currentHull != null || forceStanding) && CurrentGroundedParams != null)
            {
                //rotate collider back upright
                float standAngle = dir == Direction.Right ? CurrentGroundedParams.ColliderStandAngleInRadians : -CurrentGroundedParams.ColliderStandAngleInRadians;
                if (Math.Abs(MathUtils.GetShortestAngle(Collider.Rotation, standAngle)) > 0.001f)
                {
                    Collider.AngularVelocity           = MathUtils.GetShortestAngle(Collider.Rotation, standAngle) * 60.0f;
                    Collider.FarseerBody.FixedRotation = false;
                }
                else
                {
                    Collider.FarseerBody.FixedRotation = true;
                }

                UpdateWalkAnim(deltaTime);
            }

            //don't flip or drag when simply physics is enabled
            if (SimplePhysicsEnabled)
            {
                return;
            }

            if (!character.IsRemotePlayer && (character.AIController == null || character.AIController.CanFlip))
            {
                if (!inWater || (CurrentSwimParams != null && CurrentSwimParams.Mirror))
                {
                    if (targetMovement.X > 0.1f && targetMovement.X > Math.Abs(targetMovement.Y) * 0.2f)
                    {
                        TargetDir = Direction.Right;
                    }
                    else if (targetMovement.X < -0.1f && targetMovement.X < -Math.Abs(targetMovement.Y) * 0.2f)
                    {
                        TargetDir = Direction.Left;
                    }
                }
                else
                {
                    float refAngle = 0.0f;
                    Limb  refLimb  = GetLimb(LimbType.Head);
                    if (refLimb == null)
                    {
                        refAngle = CurrentAnimationParams.TorsoAngleInRadians;
                        refLimb  = GetLimb(LimbType.Torso);
                    }
                    else
                    {
                        refAngle = CurrentAnimationParams.HeadAngleInRadians;
                    }

                    float rotation = refLimb.Rotation;
                    if (!float.IsNaN(refAngle))
                    {
                        rotation -= refAngle * Dir;
                    }

                    rotation = MathHelper.ToDegrees(MathUtils.WrapAngleTwoPi(rotation));

                    if (rotation < 0.0f)
                    {
                        rotation += 360;
                    }

                    if (rotation > 20 && rotation < 160)
                    {
                        TargetDir = Direction.Left;
                    }
                    else if (rotation > 200 && rotation < 340)
                    {
                        TargetDir = Direction.Right;
                    }
                }
            }

            if (character.SelectedCharacter != null)
            {
                DragCharacter(character.SelectedCharacter, deltaTime);
            }

            if (!CurrentFishAnimation.Flip || IsStuck)
            {
                return;
            }
            if (character.AIController != null && !character.AIController.CanFlip)
            {
                return;
            }

            flipCooldown -= deltaTime;

            if (TargetDir != Direction.None && TargetDir != dir)
            {
                flipTimer += deltaTime;
                if ((flipTimer > 0.5f && flipCooldown <= 0.0f) || character.IsRemotePlayer)
                {
                    Flip();
                    if (!inWater || (CurrentSwimParams != null && CurrentSwimParams.Mirror))
                    {
                        Mirror();
                    }
                    flipTimer    = 0.0f;
                    flipCooldown = 1.0f;
                }
            }
            else
            {
                flipTimer = 0.0f;
            }
        }
Example #6
0
        public static VertexPositionTexture[] GenerateWallShapes(List <VoronoiCell> cells, Level level)
        {
            float outWardThickness = 30.0f;

            List <VertexPositionTexture> verticeList = new List <VertexPositionTexture>();

            foreach (VoronoiCell cell in cells)
            {
                CompareCCW compare = new CompareCCW(cell.Center);
                foreach (GraphEdge edge in cell.Edges)
                {
                    if (edge.Cell1 != null && edge.Cell1.Body == null && edge.Cell1.CellType != CellType.Empty)
                    {
                        edge.Cell1 = null;
                    }
                    if (edge.Cell2 != null && edge.Cell2.Body == null && edge.Cell2.CellType != CellType.Empty)
                    {
                        edge.Cell2 = null;
                    }

                    if (compare.Compare(edge.Point1, edge.Point2) == -1)
                    {
                        var temp = edge.Point1;
                        edge.Point1 = edge.Point2;
                        edge.Point2 = temp;
                    }
                }
            }

            foreach (VoronoiCell cell in cells)
            {
                foreach (GraphEdge edge in cell.Edges)
                {
                    if (!edge.IsSolid)
                    {
                        continue;
                    }

                    GraphEdge leftEdge  = cell.Edges.Find(e => e != edge && (edge.Point1 == e.Point1 || edge.Point1 == e.Point2));
                    GraphEdge rightEdge = cell.Edges.Find(e => e != edge && (edge.Point2 == e.Point1 || edge.Point2 == e.Point2));

                    Vector2 leftNormal = Vector2.Zero, rightNormal = Vector2.Zero;

                    float inwardThickness1 = 100;
                    float inwardThickness2 = 100;
                    if (leftEdge != null && !leftEdge.IsSolid)
                    {
                        leftNormal = edge.Point1 == leftEdge.Point1 ?
                                     Vector2.Normalize(leftEdge.Point2 - leftEdge.Point1) :
                                     Vector2.Normalize(leftEdge.Point1 - leftEdge.Point2);
                        inwardThickness1 = Vector2.Distance(leftEdge.Point1, leftEdge.Point2) / 2;
                    }
                    else
                    {
                        leftNormal       = Vector2.Normalize(cell.Center - edge.Point1);
                        inwardThickness1 = Vector2.Distance(edge.Point1, cell.Center) / 2;
                    }

                    if (!MathUtils.IsValid(leftNormal))
                    {
#if DEBUG
                        DebugConsole.ThrowError("Invalid left normal");
#endif
                        GameAnalyticsManager.AddErrorEventOnce("CaveGenerator.GenerateWallShapes:InvalidLeftNormal:" + level.Seed,
                                                               GameAnalyticsSDK.Net.EGAErrorSeverity.Warning,
                                                               "Invalid left normal (leftedge: " + leftEdge + ", rightedge: " + rightEdge + ", normal: " + leftNormal + ", seed: " + level.Seed + ")");

                        if (cell.Body != null)
                        {
                            GameMain.World.RemoveBody(cell.Body);
                            cell.Body = null;
                        }
                        leftNormal = Vector2.UnitX;
                        break;
                    }

                    if (rightEdge != null && !rightEdge.IsSolid)
                    {
                        rightNormal = edge.Point2 == rightEdge.Point1 ?
                                      Vector2.Normalize(rightEdge.Point2 - rightEdge.Point1) :
                                      Vector2.Normalize(rightEdge.Point1 - rightEdge.Point2);
                        inwardThickness2 = Vector2.Distance(rightEdge.Point1, rightEdge.Point2) / 2;
                    }
                    else
                    {
                        rightNormal      = Vector2.Normalize(cell.Center - edge.Point2);
                        inwardThickness2 = Vector2.Distance(edge.Point2, cell.Center) / 2;
                    }

                    if (!MathUtils.IsValid(rightNormal))
                    {
#if DEBUG
                        DebugConsole.ThrowError("Invalid right normal");
#endif
                        GameAnalyticsManager.AddErrorEventOnce("CaveGenerator.GenerateWallShapes:InvalidRightNormal:" + level.Seed,
                                                               GameAnalyticsSDK.Net.EGAErrorSeverity.Warning,
                                                               "Invalid right normal (leftedge: " + leftEdge + ", rightedge: " + rightEdge + ", normal: " + rightNormal + ", seed: " + level.Seed + ")");

                        if (cell.Body != null)
                        {
                            GameMain.World.RemoveBody(cell.Body);
                            cell.Body = null;
                        }
                        rightNormal = Vector2.UnitX;
                        break;
                    }

                    float point1UV = MathUtils.WrapAngleTwoPi(MathUtils.VectorToAngle(edge.Point1 - cell.Center));
                    float point2UV = MathUtils.WrapAngleTwoPi(MathUtils.VectorToAngle(edge.Point2 - cell.Center));
                    //handle wrapping around 0/360
                    if (point1UV - point2UV > MathHelper.Pi)
                    {
                        point2UV += MathHelper.TwoPi;
                    }
                    //the texture wraps around the cell 4 times
                    //TODO: define the uv scale in level generation parameters?
                    point1UV = point1UV / MathHelper.TwoPi * 4;
                    point2UV = point2UV / MathHelper.TwoPi * 4;

                    for (int i = 0; i < 2; i++)
                    {
                        Vector2[] verts = new Vector2[3];
                        VertexPositionTexture[] vertPos = new VertexPositionTexture[3];

                        if (i == 0)
                        {
                            verts[0] = edge.Point1 - leftNormal * outWardThickness;
                            verts[1] = edge.Point2 - rightNormal * outWardThickness;
                            verts[2] = edge.Point1 + leftNormal * inwardThickness1;

                            vertPos[0] = new VertexPositionTexture(new Vector3(verts[0], 0.0f), new Vector2(point1UV, 0.0f));
                            vertPos[1] = new VertexPositionTexture(new Vector3(verts[1], 0.0f), new Vector2(point2UV, 0.0f));
                            vertPos[2] = new VertexPositionTexture(new Vector3(verts[2], 0.0f), new Vector2(point1UV, 0.5f));
                        }
                        else
                        {
                            verts[0] = edge.Point1 + leftNormal * inwardThickness1;
                            verts[1] = edge.Point2 - rightNormal * outWardThickness;
                            verts[2] = edge.Point2 + rightNormal * inwardThickness2;

                            vertPos[0] = new VertexPositionTexture(new Vector3(verts[0], 0.0f), new Vector2(point1UV, 0.5f));
                            vertPos[1] = new VertexPositionTexture(new Vector3(verts[1], 0.0f), new Vector2(point2UV, 0.0f));
                            vertPos[2] = new VertexPositionTexture(new Vector3(verts[2], 0.0f), new Vector2(point2UV, 0.5f));
                        }
                        verticeList.AddRange(vertPos);
                    }
                }
            }

            return(verticeList.ToArray());
        }
Example #7
0
        void UpdateSineAnim(float deltaTime)
        {
            if (CurrentSwimParams == null)
            {
                return;
            }
            movement = TargetMovement;

            if (movement.LengthSquared() > 0.00001f)
            {
                float t = 0.5f;
                if (CurrentSwimParams.RotateTowardsMovement && VectorExtensions.Angle(VectorExtensions.Forward(Collider.Rotation + MathHelper.PiOver2), movement) > MathHelper.PiOver2)
                {
                    // Reduce the linear movement speed when not facing the movement direction
                    t /= 5;
                }
                Collider.LinearVelocity = Vector2.Lerp(Collider.LinearVelocity, movement, t);
            }

            //limbs are disabled when simple physics is enabled, no need to move them
            if (SimplePhysicsEnabled)
            {
                return;
            }
            var mainLimb = MainLimb;

            mainLimb.PullJointEnabled = true;
            //mainLimb.PullJointWorldAnchorB = Collider.SimPosition;

            if (movement.LengthSquared() < 0.00001f)
            {
                WalkPos = MathHelper.SmoothStep(WalkPos, MathHelper.PiOver2, deltaTime * 5);
                mainLimb.PullJointWorldAnchorB = Collider.SimPosition;
                return;
            }

            Vector2 transformedMovement = reverse ? -movement : movement;
            float   movementAngle       = MathUtils.VectorToAngle(transformedMovement) - MathHelper.PiOver2;
            float   mainLimbAngle       = 0;

            if (mainLimb.type == LimbType.Torso && TorsoAngle.HasValue)
            {
                mainLimbAngle = TorsoAngle.Value;
            }
            else if (mainLimb.type == LimbType.Head && HeadAngle.HasValue)
            {
                mainLimbAngle = HeadAngle.Value;
            }
            mainLimbAngle *= Dir;
            while (mainLimb.Rotation - (movementAngle + mainLimbAngle) > MathHelper.Pi)
            {
                movementAngle += MathHelper.TwoPi;
            }
            while (mainLimb.Rotation - (movementAngle + mainLimbAngle) < -MathHelper.Pi)
            {
                movementAngle -= MathHelper.TwoPi;
            }

            if (CurrentSwimParams.RotateTowardsMovement)
            {
                Collider.SmoothRotate(movementAngle, CurrentSwimParams.SteerTorque * character.SpeedMultiplier);
                if (TorsoAngle.HasValue)
                {
                    Limb torso = GetLimb(LimbType.Torso);
                    if (torso != null)
                    {
                        SmoothRotateWithoutWrapping(torso, movementAngle + TorsoAngle.Value * Dir, mainLimb, TorsoTorque);
                    }
                }
                if (HeadAngle.HasValue)
                {
                    Limb head = GetLimb(LimbType.Head);
                    if (head != null)
                    {
                        SmoothRotateWithoutWrapping(head, movementAngle + HeadAngle.Value * Dir, mainLimb, HeadTorque);
                    }
                }
                if (TailAngle.HasValue)
                {
                    Limb tail = GetLimb(LimbType.Tail);
                    if (tail != null)
                    {
                        float?mainLimbTargetAngle = null;
                        if (mainLimb.type == LimbType.Torso)
                        {
                            mainLimbTargetAngle = TorsoAngle;
                        }
                        else if (mainLimb.type == LimbType.Head)
                        {
                            mainLimbTargetAngle = HeadAngle;
                        }
                        float torque        = TailTorque;
                        float maxMultiplier = CurrentSwimParams.TailTorqueMultiplier;
                        if (mainLimbTargetAngle.HasValue && maxMultiplier > 1)
                        {
                            float diff   = Math.Abs(mainLimb.Rotation - tail.Rotation);
                            float offset = Math.Abs(mainLimbTargetAngle.Value - TailAngle.Value);
                            torque *= MathHelper.Lerp(1, maxMultiplier, MathUtils.InverseLerp(0, MathHelper.PiOver2, diff - offset));
                        }
                        SmoothRotateWithoutWrapping(tail, movementAngle + TailAngle.Value * Dir, mainLimb, torque);
                    }
                }
            }
            else
            {
                movementAngle = Dir > 0 ? -MathHelper.PiOver2 : MathHelper.PiOver2;
                if (reverse)
                {
                    movementAngle = MathUtils.WrapAngleTwoPi(movementAngle - MathHelper.Pi);
                }
                if (mainLimb.type == LimbType.Head && HeadAngle.HasValue)
                {
                    Collider.SmoothRotate(HeadAngle.Value * Dir, CurrentSwimParams.SteerTorque * character.SpeedMultiplier);
                }
                else if (mainLimb.type == LimbType.Torso && TorsoAngle.HasValue)
                {
                    Collider.SmoothRotate(TorsoAngle.Value * Dir, CurrentSwimParams.SteerTorque * character.SpeedMultiplier);
                }
                if (TorsoAngle.HasValue)
                {
                    Limb torso = GetLimb(LimbType.Torso);
                    torso?.body.SmoothRotate(TorsoAngle.Value * Dir, TorsoTorque);
                }
                if (HeadAngle.HasValue)
                {
                    Limb head = GetLimb(LimbType.Head);
                    head?.body.SmoothRotate(HeadAngle.Value * Dir, HeadTorque);
                }
                if (TailAngle.HasValue)
                {
                    Limb tail = GetLimb(LimbType.Tail);
                    tail?.body.SmoothRotate(TailAngle.Value * Dir, TailTorque);
                }
            }

            var waveLength    = Math.Abs(CurrentSwimParams.WaveLength * RagdollParams.JointScale);
            var waveAmplitude = Math.Abs(CurrentSwimParams.WaveAmplitude * character.SpeedMultiplier);

            if (waveLength > 0 && waveAmplitude > 0)
            {
                WalkPos -= transformedMovement.Length() / Math.Abs(waveLength);
                WalkPos  = MathUtils.WrapAngleTwoPi(WalkPos);
            }

            foreach (var limb in Limbs)
            {
                if (limb.IsSevered)
                {
                    continue;
                }
                if (Math.Abs(limb.Params.ConstantTorque) > 0)
                {
                    limb.body.SmoothRotate(movementAngle + MathHelper.ToRadians(limb.Params.ConstantAngle) * Dir, limb.Params.ConstantTorque, wrapAngle: true);
                }
                switch (limb.type)
                {
                case LimbType.LeftFoot:
                case LimbType.RightFoot:
                    if (CurrentSwimParams.FootAnglesInRadians.ContainsKey(limb.Params.ID))
                    {
                        SmoothRotateWithoutWrapping(limb, movementAngle + CurrentSwimParams.FootAnglesInRadians[limb.Params.ID] * Dir, mainLimb, FootTorque);
                    }
                    break;

                case LimbType.Tail:
                    if (waveLength > 0 && waveAmplitude > 0)
                    {
                        float waveRotation = (float)Math.Sin(WalkPos);
                        limb.body.ApplyTorque(waveRotation * limb.Mass * waveAmplitude);
                    }
                    break;
                }
            }

            for (int i = 0; i < Limbs.Length; i++)
            {
                var limb = Limbs[i];
                if (limb.IsSevered)
                {
                    continue;
                }
                if (limb.SteerForce <= 0.0f)
                {
                    continue;
                }
                if (!Collider.PhysEnabled)
                {
                    continue;
                }
                Vector2 pullPos = limb.PullJointWorldAnchorA;
                limb.body.ApplyForce(movement * limb.SteerForce * limb.Mass * Math.Max(character.SpeedMultiplier, 1), pullPos);
            }

            Vector2 mainLimbDiff = mainLimb.PullJointWorldAnchorB - mainLimb.SimPosition;

            if (CurrentSwimParams.UseSineMovement)
            {
                mainLimb.PullJointWorldAnchorB = Vector2.SmoothStep(
                    mainLimb.PullJointWorldAnchorB,
                    Collider.SimPosition,
                    mainLimbDiff.LengthSquared() > 10.0f ? 1.0f : (float)Math.Abs(Math.Sin(WalkPos)));
            }
            else
            {
                //mainLimb.PullJointWorldAnchorB = Collider.SimPosition;
                mainLimb.PullJointWorldAnchorB = Vector2.Lerp(
                    mainLimb.PullJointWorldAnchorB,
                    Collider.SimPosition,
                    mainLimbDiff.LengthSquared() > 10.0f ? 1.0f : 0.5f);
            }

            floorY = Limbs[0].SimPosition.Y;
        }
Example #8
0
        private void SetDamage(int sectionIndex, float damage, Character attacker = null, bool createNetworkEvent = true)
        {
            if (Submarine != null && Submarine.GodMode || Indestructible)
            {
                return;
            }
            if (!Prefab.Body)
            {
                return;
            }
            if (!MathUtils.IsValid(damage))
            {
                return;
            }

            damage = MathHelper.Clamp(damage, 0.0f, Prefab.Health);

#if SERVER
            if (GameMain.Server != null && createNetworkEvent && damage != Sections[sectionIndex].damage)
            {
                GameMain.Server.CreateEntityEvent(this);
            }
            bool noGaps = true;
            for (int i = 0; i < Sections.Length; i++)
            {
                if (i != sectionIndex && SectionIsLeaking(i))
                {
                    noGaps = false;
                    break;
                }
            }
#endif


            if (damage < Prefab.Health * LeakThreshold)
            {
                if (Sections[sectionIndex].gap != null)
                {
#if SERVER
                    //the structure doesn't have any other gap, log the structure being fixed
                    if (noGaps && attacker != null)
                    {
                        GameServer.Log((Sections[sectionIndex].gap.IsRoomToRoom ? "Inner" : "Outer") + " wall repaired by " + attacker.Name, ServerLog.MessageType.ItemInteraction);
                    }
#endif
                    DebugConsole.Log("Removing gap (ID " + Sections[sectionIndex].gap.ID + ", section: " + sectionIndex + ") from wall " + ID);

                    //remove existing gap if damage is below leak threshold
                    Sections[sectionIndex].gap.Open = 0.0f;
                    Sections[sectionIndex].gap.Remove();
                    Sections[sectionIndex].gap = null;
                }
            }
            else
            {
                if (Sections[sectionIndex].gap == null)
                {
                    Rectangle gapRect = Sections[sectionIndex].rect;
                    float     diffFromCenter;
                    if (IsHorizontal)
                    {
                        diffFromCenter = (gapRect.Center.X - this.rect.Center.X) / (float)this.rect.Width * BodyWidth;
                        if (BodyWidth > 0.0f)
                        {
                            gapRect.Width = (int)(BodyWidth * (gapRect.Width / (float)this.rect.Width));
                        }
                        if (BodyHeight > 0.0f)
                        {
                            gapRect.Height = (int)BodyHeight;
                        }
                    }
                    else
                    {
                        diffFromCenter = ((gapRect.Y - gapRect.Height / 2) - (this.rect.Y - this.rect.Height / 2)) / (float)this.rect.Height * BodyHeight;
                        if (BodyWidth > 0.0f)
                        {
                            gapRect.Width = (int)BodyWidth;
                        }
                        if (BodyHeight > 0.0f)
                        {
                            gapRect.Height = (int)(BodyHeight * (gapRect.Height / (float)this.rect.Height));
                        }
                    }
                    if (FlippedX)
                    {
                        diffFromCenter = -diffFromCenter;
                    }

                    if (BodyRotation != 0.0f)
                    {
                        Vector2 structureCenter = Position;
                        Vector2 gapPos          = structureCenter + new Vector2(
                            (float)Math.Cos(IsHorizontal ? -BodyRotation : MathHelper.PiOver2 - BodyRotation),
                            (float)Math.Sin(IsHorizontal ? -BodyRotation : MathHelper.PiOver2 - BodyRotation)) * diffFromCenter;
                        gapRect = new Rectangle((int)(gapPos.X - gapRect.Width / 2), (int)(gapPos.Y + gapRect.Height / 2), gapRect.Width, gapRect.Height);
                    }

                    gapRect.X      -= 10;
                    gapRect.Y      += 10;
                    gapRect.Width  += 20;
                    gapRect.Height += 20;

                    bool horizontalGap = !IsHorizontal;
                    if (Prefab.BodyRotation != 0.0f)
                    {
                        //rotation within a 90 deg sector (e.g. 100 -> 10, 190 -> 10, -10 -> 80)
                        float sectorizedRotation = MathUtils.WrapAngleTwoPi(BodyRotation) % MathHelper.PiOver2;
                        //diagonal if 30 < angle < 60
                        bool diagonal = sectorizedRotation > MathHelper.Pi / 6 && sectorizedRotation < MathHelper.Pi / 3;
                        //gaps on the lower half of a diagonal wall are horizontal, ones on the upper half are vertical
                        if (diagonal)
                        {
                            horizontalGap = gapRect.Y - gapRect.Height / 2 < Position.Y;
                        }
                    }

                    Sections[sectionIndex].gap = new Gap(gapRect, horizontalGap, Submarine);

                    //free the ID, because if we give gaps IDs we have to make sure they always match between the clients and the server and
                    //that clients create them in the correct order along with every other entity created/removed during the round
                    //which COULD be done via entityspawner, but it's unnecessary because we never access these gaps by ID
                    Sections[sectionIndex].gap.FreeID();
                    Sections[sectionIndex].gap.ShouldBeSaved = false;
                    Sections[sectionIndex].gap.ConnectedWall = this;
                    DebugConsole.Log("Created gap (ID " + Sections[sectionIndex].gap.ID + ", section: " + sectionIndex + ") on wall " + ID);
                    //AdjustKarma(attacker, 300);

#if SERVER
                    //the structure didn't have any other gaps yet, log the breach
                    if (noGaps && attacker != null)
                    {
                        GameServer.Log((Sections[sectionIndex].gap.IsRoomToRoom ? "Inner" : "Outer") + " wall breached by " + attacker.Name, ServerLog.MessageType.ItemInteraction);
                    }
#endif
                }

                float gapOpen = (damage / Prefab.Health - LeakThreshold) * (1.0f / (1.0f - LeakThreshold));
                Sections[sectionIndex].gap.Open = gapOpen;
            }

            float damageDiff = damage - Sections[sectionIndex].damage;
            bool  hadHole    = SectionBodyDisabled(sectionIndex);
            Sections[sectionIndex].damage = MathHelper.Clamp(damage, 0.0f, Prefab.Health);

            //otherwise it's possible to infinitely gain karma by welding fixed things
            if (attacker != null && damageDiff != 0.0f)
            {
                AdjustKarma(attacker, damageDiff);
#if CLIENT
                if (GameMain.Client == null)
                {
#endif
                if (damageDiff < 0.0f)
                {
                    attacker.Info.IncreaseSkillLevel("mechanical",
                                                     -damageDiff * SkillIncreaseMultiplier / Math.Max(attacker.GetSkillLevel("mechanical"), 1.0f),
                                                     SectionPosition(sectionIndex, true));
                }
#if CLIENT
            }
#endif
            }

            bool hasHole = SectionBodyDisabled(sectionIndex);

            if (hadHole == hasHole)
            {
                return;
            }

            UpdateSections();
        }
        public override void UpdateAnim(float deltaTime)
        {
            if (Frozen)
            {
                return;
            }

            if (character.IsDead || character.IsUnconscious || character.Stun > 0.0f)
            {
                Collider.FarseerBody.FixedRotation = false;

                if (character.IsRemotePlayer)
                {
                    if (!SimplePhysicsEnabled)
                    {
                        MainLimb.PullJointWorldAnchorB = Collider.SimPosition;
                        MainLimb.PullJointEnabled      = true;
                    }
                }
                else
                {
                    Vector2 diff = (MainLimb.SimPosition - Collider.SimPosition);
                    if (diff.LengthSquared() > 10.0f * 10.0f)
                    {
                        Collider.SetTransform(MainLimb.SimPosition, MainLimb.Rotation);
                    }
                    else
                    {
                        Collider.LinearVelocity = diff * 60.0f;
                        Collider.SmoothRotate(MainLimb.Rotation);
                    }
                }

                if (character.IsDead && deathAnimTimer < deathAnimDuration)
                {
                    deathAnimTimer += deltaTime;
                    UpdateDying(deltaTime);
                }

                return;
            }

            //re-enable collider
            if (!Collider.Enabled)
            {
                var lowestLimb = FindLowestLimb();

                Collider.SetTransform(new Vector2(
                                          Collider.SimPosition.X,
                                          Math.Max(lowestLimb.SimPosition.Y + (Collider.radius + Collider.height / 2), Collider.SimPosition.Y)),
                                      0.0f);

                Collider.Enabled = true;
            }

            ResetPullJoints();

            if (strongestImpact > 0.0f)
            {
                character.Stun  = MathHelper.Clamp(strongestImpact * 0.5f, character.Stun, 5.0f);
                strongestImpact = 0.0f;
            }


            if (inWater)
            {
                Collider.FarseerBody.FixedRotation = false;
                UpdateSineAnim(deltaTime);
            }
            else if (currentHull != null && CanEnterSubmarine)
            {
                if (Math.Abs(MathUtils.GetShortestAngle(Collider.Rotation, 0.0f)) > 0.001f)
                {
                    //rotate collider back upright
                    Collider.AngularVelocity           = MathUtils.GetShortestAngle(Collider.Rotation, 0.0f) * 60.0f;
                    Collider.FarseerBody.FixedRotation = false;
                }
                else
                {
                    Collider.FarseerBody.FixedRotation = true;
                }

                UpdateWalkAnim(deltaTime);
            }

            //don't flip or drag when simply physics is enabled
            if (SimplePhysicsEnabled)
            {
                return;
            }

            if (!character.IsRemotePlayer)
            {
                if (mirror || !inWater)
                {
                    if (targetMovement.X > 0.1f && targetMovement.X > Math.Abs(targetMovement.Y) * 0.5f)
                    {
                        TargetDir = Direction.Right;
                    }
                    else if (targetMovement.X < -0.1f && targetMovement.X < -Math.Abs(targetMovement.Y) * 0.5f)
                    {
                        TargetDir = Direction.Left;
                    }
                }
                else
                {
                    Limb head = GetLimb(LimbType.Head);
                    if (head == null)
                    {
                        head = GetLimb(LimbType.Torso);
                    }

                    float rotation = MathUtils.WrapAngleTwoPi(head.Rotation);
                    rotation = MathHelper.ToDegrees(rotation);

                    if (rotation < 0.0f)
                    {
                        rotation += 360;
                    }

                    if (rotation > 20 && rotation < 160)
                    {
                        TargetDir = Direction.Left;
                    }
                    else if (rotation > 200 && rotation < 340)
                    {
                        TargetDir = Direction.Right;
                    }
                }
            }

            if (character.SelectedCharacter != null)
            {
                DragCharacter(character.SelectedCharacter);
            }

            if (!flip)
            {
                return;
            }

            flipTimer += deltaTime;

            if (TargetDir != Direction.None && TargetDir != dir)
            {
                if (flipTimer > 1.0f || character.IsRemotePlayer)
                {
                    Flip();
                    if (mirror || !inWater)
                    {
                        Mirror();
                    }
                    flipTimer = 0.0f;
                }
            }
        }
        public static List <VertexPositionTexture> GenerateWallEdgeVertices(List <VoronoiCell> cells, Level level, float zCoord)
        {
            float outWardThickness = level.GenerationParams.WallEdgeExpandOutwardsAmount;

            List <VertexPositionTexture> vertices = new List <VertexPositionTexture>();

            foreach (VoronoiCell cell in cells)
            {
                Vector2 minVert       = cell.Edges[0].Point1;
                Vector2 maxVert       = cell.Edges[0].Point1;
                float   circumference = 0.0f;
                foreach (GraphEdge edge in cell.Edges)
                {
                    circumference += Vector2.Distance(edge.Point1, edge.Point2);
                    minVert        = new Vector2(
                        Math.Min(minVert.X, edge.Point1.X),
                        Math.Min(minVert.Y, edge.Point1.Y));
                    maxVert = new Vector2(
                        Math.Max(maxVert.X, edge.Point1.X),
                        Math.Max(maxVert.Y, edge.Point1.Y));
                }
                Vector2 center = (minVert + maxVert) / 2;
                foreach (GraphEdge edge in cell.Edges)
                {
                    if (!edge.IsSolid)
                    {
                        continue;
                    }

                    GraphEdge leftEdge         = cell.Edges.Find(e => e != edge && (edge.Point1.NearlyEquals(e.Point1) || edge.Point1.NearlyEquals(e.Point2)));
                    var       leftAdjacentCell = leftEdge?.AdjacentCell(cell);
                    if (leftAdjacentCell != null)
                    {
                        var adjEdge = leftAdjacentCell.Edges.Find(e => e != leftEdge && e.IsSolid && (edge.Point1.NearlyEquals(e.Point1) || edge.Point1.NearlyEquals(e.Point2)));
                        if (adjEdge != null)
                        {
                            leftEdge = adjEdge;
                        }
                    }

                    GraphEdge rightEdge         = cell.Edges.Find(e => e != edge && (edge.Point2.NearlyEquals(e.Point1) || edge.Point2.NearlyEquals(e.Point2)));
                    var       rightAdjacentCell = rightEdge?.AdjacentCell(cell);
                    if (rightAdjacentCell != null)
                    {
                        var adjEdge = rightAdjacentCell.Edges.Find(e => e != rightEdge && e.IsSolid && (edge.Point2.NearlyEquals(e.Point1) || edge.Point2.NearlyEquals(e.Point2)));
                        if (adjEdge != null)
                        {
                            rightEdge = adjEdge;
                        }
                    }

                    Vector2 leftNormal = Vector2.Zero, rightNormal = Vector2.Zero;

                    float inwardThickness1 = level.GenerationParams.WallEdgeExpandInwardsAmount;
                    float inwardThickness2 = level.GenerationParams.WallEdgeExpandInwardsAmount;
                    if (leftEdge != null && !leftEdge.IsSolid)
                    {
                        leftNormal = edge.Point1.NearlyEquals(leftEdge.Point1) ?
                                     Vector2.Normalize(leftEdge.Point2 - leftEdge.Point1) :
                                     Vector2.Normalize(leftEdge.Point1 - leftEdge.Point2);
                    }
                    else if (leftEdge != null)
                    {
                        leftNormal = -Vector2.Normalize(edge.GetNormal(cell) + leftEdge.GetNormal(leftAdjacentCell ?? cell));
                        if (!MathUtils.IsValid(leftNormal))
                        {
                            leftNormal = -edge.GetNormal(cell);
                        }
                    }
                    else
                    {
                        leftNormal = Vector2.Normalize(cell.Center - edge.Point1);
                    }
                    inwardThickness1 = Math.Min(Vector2.Distance(edge.Point1, cell.Center), inwardThickness1);

                    if (!MathUtils.IsValid(leftNormal))
                    {
#if DEBUG
                        DebugConsole.ThrowError("Invalid left normal");
#endif
                        GameAnalyticsManager.AddErrorEventOnce("CaveGenerator.GenerateWallShapes:InvalidLeftNormal:" + level.Seed,
                                                               GameAnalyticsSDK.Net.EGAErrorSeverity.Warning,
                                                               "Invalid left normal (leftedge: " + leftEdge + ", rightedge: " + rightEdge + ", normal: " + leftNormal + ", seed: " + level.Seed + ")");

                        if (cell.Body != null)
                        {
                            if (GameMain.World.BodyList.Contains(cell.Body))
                            {
                                GameMain.World.Remove(cell.Body);
                            }
                            cell.Body = null;
                        }
                        leftNormal = Vector2.UnitX;
                        break;
                    }

                    if (rightEdge != null && !rightEdge.IsSolid)
                    {
                        rightNormal = edge.Point2.NearlyEquals(rightEdge.Point1) ?
                                      Vector2.Normalize(rightEdge.Point2 - rightEdge.Point1) :
                                      Vector2.Normalize(rightEdge.Point1 - rightEdge.Point2);
                    }
                    else if (rightEdge != null)
                    {
                        rightNormal = -Vector2.Normalize(edge.GetNormal(cell) + rightEdge.GetNormal(rightAdjacentCell ?? cell));
                        if (!MathUtils.IsValid(rightNormal))
                        {
                            rightNormal = -edge.GetNormal(cell);
                        }
                    }
                    else
                    {
                        rightNormal = Vector2.Normalize(cell.Center - edge.Point2);
                    }
                    inwardThickness2 = Math.Min(Vector2.Distance(edge.Point2, cell.Center), inwardThickness2);

                    if (!MathUtils.IsValid(rightNormal))
                    {
#if DEBUG
                        DebugConsole.ThrowError("Invalid right normal");
#endif
                        GameAnalyticsManager.AddErrorEventOnce("CaveGenerator.GenerateWallShapes:InvalidRightNormal:" + level.Seed,
                                                               GameAnalyticsSDK.Net.EGAErrorSeverity.Warning,
                                                               "Invalid right normal (leftedge: " + leftEdge + ", rightedge: " + rightEdge + ", normal: " + rightNormal + ", seed: " + level.Seed + ")");

                        if (cell.Body != null)
                        {
                            if (GameMain.World.BodyList.Contains(cell.Body))
                            {
                                GameMain.World.Remove(cell.Body);
                            }
                            cell.Body = null;
                        }
                        rightNormal = Vector2.UnitX;
                        break;
                    }

                    float point1UV = MathUtils.WrapAngleTwoPi(MathUtils.VectorToAngle(edge.Point1 - center));
                    float point2UV = MathUtils.WrapAngleTwoPi(MathUtils.VectorToAngle(edge.Point2 - center));
                    //handle wrapping around 0/360
                    if (point1UV - point2UV > MathHelper.Pi)
                    {
                        point1UV -= MathHelper.TwoPi;
                    }
                    int textureRepeatCount = (int)Math.Max(circumference / 2 / level.GenerationParams.WallEdgeTextureWidth, 1);
                    point1UV = point1UV / MathHelper.TwoPi * textureRepeatCount;
                    point2UV = point2UV / MathHelper.TwoPi * textureRepeatCount;

                    for (int i = 0; i < 2; i++)
                    {
                        Vector2[] verts = new Vector2[3];
                        VertexPositionTexture[] vertPos = new VertexPositionTexture[3];

                        if (i == 0)
                        {
                            verts[0] = edge.Point1 - leftNormal * outWardThickness;
                            verts[1] = edge.Point2 - rightNormal * outWardThickness;
                            verts[2] = edge.Point1 + leftNormal * inwardThickness1;

                            vertPos[0] = new VertexPositionTexture(new Vector3(verts[0], zCoord), new Vector2(point1UV, 0.0f));
                            vertPos[1] = new VertexPositionTexture(new Vector3(verts[1], zCoord), new Vector2(point2UV, 0.0f));
                            vertPos[2] = new VertexPositionTexture(new Vector3(verts[2], zCoord), new Vector2(point1UV, 1.0f));
                        }
                        else
                        {
                            verts[0] = edge.Point1 + leftNormal * inwardThickness1;
                            verts[1] = edge.Point2 - rightNormal * outWardThickness;
                            verts[2] = edge.Point2 + rightNormal * inwardThickness2;

                            vertPos[0] = new VertexPositionTexture(new Vector3(verts[0], zCoord), new Vector2(point1UV, 1.0f));
                            vertPos[1] = new VertexPositionTexture(new Vector3(verts[1], zCoord), new Vector2(point2UV, 0.0f));
                            vertPos[2] = new VertexPositionTexture(new Vector3(verts[2], zCoord), new Vector2(point2UV, 1.0f));
                        }
                        vertices.AddRange(vertPos);
                    }
                }
            }

            return(vertices);
        }
Example #11
0
        public override void Flip()
        {
            base.Flip();

            walkPos = -walkPos;

            Limb torso = GetLimb(LimbType.Torso);

            Vector2 difference;

            Matrix torsoTransform = Matrix.CreateRotationZ(torso.Rotation);

            for (int i = 0; i < character.SelectedItems.Length; i++)
            {
                if (character.SelectedItems[i] != null && character.SelectedItems[i].body != null)
                {
                    difference   = character.SelectedItems[i].body.SimPosition - torso.SimPosition;
                    difference   = Vector2.Transform(difference, torsoTransform);
                    difference.Y = -difference.Y;

                    character.SelectedItems[i].body.SetTransform(
                        torso.SimPosition + Vector2.Transform(difference, -torsoTransform),
                        MathUtils.WrapAngleTwoPi(-character.SelectedItems[i].body.Rotation));
                }
            }

            foreach (Limb limb in Limbs)
            {
                bool mirror    = false;
                bool flipAngle = false;
                bool wrapAngle = false;

                switch (limb.type)
                {
                case LimbType.LeftHand:
                case LimbType.LeftArm:
                case LimbType.RightHand:
                case LimbType.RightArm:
                    mirror    = true;
                    flipAngle = true;
                    break;

                case LimbType.LeftThigh:
                case LimbType.LeftLeg:
                case LimbType.LeftFoot:
                case LimbType.RightThigh:
                case LimbType.RightLeg:
                case LimbType.RightFoot:
                    mirror    = Crouching && !inWater;
                    flipAngle = (limb.DoesFlip || Crouching) && !inWater;
                    wrapAngle = !inWater;
                    break;

                default:
                    flipAngle = limb.DoesFlip && !inWater;
                    wrapAngle = !inWater;
                    break;
                }

                Vector2 position = limb.SimPosition;

                if ((limb.pullJoint == null || !limb.pullJoint.Enabled) && mirror)
                {
                    difference   = limb.body.SimPosition - torso.SimPosition;
                    difference   = Vector2.Transform(difference, torsoTransform);
                    difference.Y = -difference.Y;

                    position = torso.SimPosition + Vector2.Transform(difference, -torsoTransform);

                    //TrySetLimbPosition(limb, limb.SimPosition, );
                }

                float angle = flipAngle ? -limb.body.Rotation : limb.body.Rotation;
                if (wrapAngle)
                {
                    angle = MathUtils.WrapAnglePi(angle);
                }

                TrySetLimbPosition(limb, Collider.SimPosition, position);

                limb.body.SetTransform(limb.body.SimPosition, angle);
            }
        }