Beispiel #1
0
 public override void FlipX(bool relativeToSub)
 {
     if (DockingTarget != null)
     {
         if (IsHorizontal)
         {
             DockingDir = 0;
             DockingDir = GetDir(DockingTarget);
             DockingTarget.DockingDir = -DockingDir;
         }
         if (joint != null)
         {
             CreateJoint(joint is WeldJoint);
             LinkHullsToGaps();
         }
         else if (DockingTarget.joint != null)
         {
             if (!GameMain.World.BodyList.Contains(DockingTarget.joint.BodyA) ||
                 !GameMain.World.BodyList.Contains(DockingTarget.joint.BodyB))
             {
                 DockingTarget.CreateJoint(DockingTarget.joint is WeldJoint);
             }
             DockingTarget.LinkHullsToGaps();
         }
     }
 }
Beispiel #2
0
        public void Undock(bool applyEffects = true)
        {
            if (DockingTarget == null || !docked)
            {
                return;
            }

            forceLockTimer  = 0.0f;
            dockingCooldown = 0.1f;

            if (applyEffects)
            {
                ApplyStatusEffects(ActionType.OnSecondaryUse, 1.0f);
            }

            DockingTarget.item.Submarine.ConnectedDockingPorts.Remove(item.Submarine);
            item.Submarine.ConnectedDockingPorts.Remove(DockingTarget.item.Submarine);

            if (Door != null && DockingTarget.Door != null)
            {
                WayPoint myWayPoint     = WayPoint.WayPointList.Find(wp => Door.LinkedGap == wp.ConnectedGap);
                WayPoint targetWayPoint = WayPoint.WayPointList.Find(wp => DockingTarget.Door.LinkedGap == wp.ConnectedGap);

                if (myWayPoint != null && targetWayPoint != null)
                {
                    myWayPoint.FindHull();
                    myWayPoint.linkedTo.Remove(targetWayPoint);
                    targetWayPoint.FindHull();
                    targetWayPoint.linkedTo.Remove(myWayPoint);
                }
            }

            item.linkedTo.Clear();

            docked = false;

            Item.Submarine.EnableObstructedWaypoints(DockingTarget.Item.Submarine);
            obstructedWayPointsDisabled = false;
            Item.Submarine.RefreshOutdoorNodes();

            DockingTarget.Undock();
            DockingTarget = null;

            if (doorBody != null)
            {
                GameMain.World.Remove(doorBody);
                doorBody = null;
            }

            var wire = item.GetComponent <Wire>();

            wire?.Drop(null);

            if (joint != null)
            {
                GameMain.World.Remove(joint);
                joint = null;
            }

            hulls[0]?.Remove(); hulls[0] = null;
            hulls[1]?.Remove(); hulls[1] = null;

            if (gap != null)
            {
                gap.Remove();
                gap = null;
            }

            if (bodies != null)
            {
                foreach (Body body in bodies)
                {
                    if (body == null)
                    {
                        continue;
                    }
                    GameMain.World.Remove(body);
                }
                bodies = null;
            }

            outsideBlocker?.Body.Remove(outsideBlocker);
            outsideBlocker = null;

#if SERVER
            if (GameMain.Server != null && (!item.Submarine?.Loading ?? true))
            {
                item.CreateServerEvent(this);
            }
#endif
            OnUnDocked?.Invoke();
            OnUnDocked = null;
        }
Beispiel #3
0
        private void CreateHulls()
        {
            var hullRects = new Rectangle[] { item.WorldRect, DockingTarget.item.WorldRect };
            var subs      = new Submarine[] { item.Submarine, DockingTarget.item.Submarine };

            bodies = new Body[4];

            if (DockingTarget.Door != null)
            {
                CreateDoorBody();
            }

            if (Door != null)
            {
                DockingTarget.CreateDoorBody();
            }

            if (IsHorizontal)
            {
                if (hullRects[0].Center.X > hullRects[1].Center.X)
                {
                    hullRects = new Rectangle[] { DockingTarget.item.WorldRect, item.WorldRect };
                    subs      = new Submarine[] { DockingTarget.item.Submarine, item.Submarine };
                }

                int scaledDockedDistance = (int)(DockedDistance / 2 * item.Scale);
                hullRects[0] = new Rectangle(hullRects[0].Center.X, hullRects[0].Y, scaledDockedDistance, hullRects[0].Height);
                hullRects[1] = new Rectangle(hullRects[1].Center.X - scaledDockedDistance, hullRects[1].Y, scaledDockedDistance, hullRects[1].Height);

                //expand hulls if needed, so there's no empty space between the sub's hulls and docking port hulls
                int leftSubRightSide = int.MinValue, rightSubLeftSide = int.MaxValue;
                foreach (Hull hull in Hull.hullList)
                {
                    for (int i = 0; i < 2; i++)
                    {
                        if (hull.Submarine != subs[i])
                        {
                            continue;
                        }
                        if (hull.WorldRect.Y - 5 < hullRects[i].Y - hullRects[i].Height)
                        {
                            continue;
                        }
                        if (hull.WorldRect.Y - hull.WorldRect.Height + 5 > hullRects[i].Y)
                        {
                            continue;
                        }

                        if (i == 0) //left hull
                        {
                            if (hull.WorldPosition.X > hullRects[0].Center.X)
                            {
                                continue;
                            }
                            leftSubRightSide = Math.Max(hull.WorldRect.Right, leftSubRightSide);
                        }
                        else //upper hull
                        {
                            if (hull.WorldPosition.X < hullRects[1].Center.X)
                            {
                                continue;
                            }
                            rightSubLeftSide = Math.Min(hull.WorldRect.X, rightSubLeftSide);
                        }
                    }
                }

                if (leftSubRightSide == int.MinValue || rightSubLeftSide == int.MaxValue)
                {
                    DebugConsole.NewMessage("Creating hulls between docking ports failed. Could not find a hull next to the docking port.");
                    return;
                }

                //expand left hull to the rightmost hull of the sub at the left side
                //(unless the difference is more than 100 units - if the distance is very large
                //there's something wrong with the positioning of the docking ports or submarine hulls)
                int leftHullDiff = (hullRects[0].X - leftSubRightSide) + 5;
                if (leftHullDiff > 0)
                {
                    if (leftHullDiff > 100)
                    {
                        DebugConsole.NewMessage("Creating hulls between docking ports failed. The leftmost docking port seems to be very far from any hulls in the left-side submarine.");
                        return;
                    }
                    else
                    {
                        hullRects[0].X     -= leftHullDiff;
                        hullRects[0].Width += leftHullDiff;
                    }
                }

                int rightHullDiff = (rightSubLeftSide - hullRects[1].Right) + 5;
                if (rightHullDiff > 0)
                {
                    if (rightHullDiff > 100)
                    {
                        DebugConsole.NewMessage("Creating hulls between docking ports failed. The rightmost docking port seems to be very far from any hulls in the right-side submarine.");
                        return;
                    }
                    else
                    {
                        hullRects[1].Width += rightHullDiff;
                    }
                }

                int expand = 5;
                for (int i = 0; i < 2; i++)
                {
                    hullRects[i].X        -= expand;
                    hullRects[i].Width    += expand * 2;
                    hullRects[i].Location -= MathUtils.ToPoint((subs[i].WorldPosition - subs[i].HiddenSubPosition));
                    hulls[i] = new Hull(MapEntityPrefab.Find(null, "hull"), hullRects[i], subs[i]);
                    hulls[i].AddToGrid(subs[i]);
                    hulls[i].FreeID();

                    for (int j = 0; j < 2; j++)
                    {
                        bodies[i + j * 2] = GameMain.World.CreateEdge(
                            ConvertUnits.ToSimUnits(new Vector2(hullRects[i].X, hullRects[i].Y - hullRects[i].Height * j)),
                            ConvertUnits.ToSimUnits(new Vector2(hullRects[i].Right, hullRects[i].Y - hullRects[i].Height * j)));
                    }
                }

                if (rightHullDiff <= 100 && hulls[0].Submarine != null)
                {
                    outsideBlocker = hulls[0].Submarine.PhysicsBody.FarseerBody.CreateRectangle(
                        ConvertUnits.ToSimUnits(hullRects[0].Width + hullRects[1].Width),
                        ConvertUnits.ToSimUnits(hullRects[0].Height),
                        density: 0.0f,
                        offset: ConvertUnits.ToSimUnits(new Vector2(hullRects[0].Right, hullRects[0].Y - hullRects[0].Height / 2) - hulls[0].Submarine.HiddenSubPosition));
                    outsideBlocker.UserData = this;
                }

                gap = new Gap(new Rectangle(hullRects[0].Right - 2, hullRects[0].Y, 4, hullRects[0].Height), true, subs[0]);
            }
            else
            {
                if (hullRects[0].Center.Y > hullRects[1].Center.Y)
                {
                    hullRects = new Rectangle[] { DockingTarget.item.WorldRect, item.WorldRect };
                    subs      = new Submarine[] { DockingTarget.item.Submarine, item.Submarine };
                }

                int scaledDockedDistance = (int)(DockedDistance / 2 * item.Scale);
                hullRects[0] = new Rectangle(hullRects[0].X, hullRects[0].Y - hullRects[0].Height / 2 + scaledDockedDistance, hullRects[0].Width, scaledDockedDistance);
                hullRects[1] = new Rectangle(hullRects[1].X, hullRects[1].Y - hullRects[1].Height / 2, hullRects[1].Width, scaledDockedDistance);

                //expand hulls if needed, so there's no empty space between the sub's hulls and docking port hulls
                int upperSubBottom = int.MaxValue, lowerSubTop = int.MinValue;
                foreach (Hull hull in Hull.hullList)
                {
                    for (int i = 0; i < 2; i++)
                    {
                        if (hull.Submarine != subs[i])
                        {
                            continue;
                        }
                        if (hull.WorldRect.Right - 5 < hullRects[i].X)
                        {
                            continue;
                        }
                        if (hull.WorldRect.X + 5 > hullRects[i].Right)
                        {
                            continue;
                        }

                        if (i == 0) //lower hull
                        {
                            if (hull.WorldPosition.Y > hullRects[i].Y - hullRects[i].Height / 2)
                            {
                                continue;
                            }
                            lowerSubTop = Math.Max(hull.WorldRect.Y, lowerSubTop);
                        }
                        else //upper hull
                        {
                            if (hull.WorldPosition.Y < hullRects[i].Y - hullRects[i].Height / 2)
                            {
                                continue;
                            }
                            upperSubBottom = Math.Min(hull.WorldRect.Y - hull.WorldRect.Height, upperSubBottom);
                        }
                    }
                }

                if (upperSubBottom == int.MaxValue || lowerSubTop == int.MinValue)
                {
                    DebugConsole.NewMessage("Creating hulls between docking ports failed. Could not find a hull next to the docking port.");
                    return;
                }

                //expand lower hull to the topmost hull of the lower sub
                //(unless the difference is more than 100 units - if the distance is very large
                //there's something wrong with the positioning of the docking ports or submarine hulls)
                int lowerHullDiff = ((hullRects[0].Y - hullRects[0].Height) - lowerSubTop) + 5;
                if (lowerHullDiff > 0)
                {
                    if (lowerHullDiff > 100)
                    {
                        DebugConsole.NewMessage("Creating hulls between docking ports failed. The lower docking port seems to be very far from any hulls in the lower submarine.");
                        return;
                    }
                    else
                    {
                        hullRects[0].Height += lowerHullDiff;
                    }
                }

                int upperHullDiff = (upperSubBottom - hullRects[1].Y) + 5;
                if (upperHullDiff > 0)
                {
                    if (upperHullDiff > 100)
                    {
                        DebugConsole.NewMessage("Creating hulls between docking ports failed. The upper docking port seems to be very far from any hulls in the upper submarine.");
                        return;
                    }
                    else
                    {
                        hullRects[1].Y      += upperHullDiff;
                        hullRects[1].Height += upperHullDiff;
                    }
                }

                //difference between the edges of the hulls (to avoid a gap between the hulls)
                //0 is lower
                int midHullDiff = ((hullRects[1].Y - hullRects[1].Height) - hullRects[0].Y) + 2;
                if (midHullDiff > 100)
                {
                    DebugConsole.NewMessage("Creating hulls between docking ports failed. The upper hull seems to be very far from the lower hull.");
                    return;
                }
                else if (midHullDiff > 0)
                {
                    hullRects[0].Height += midHullDiff / 2 + 1;
                    hullRects[1].Y      -= midHullDiff / 2 + 1;
                    hullRects[1].Height += midHullDiff / 2 + 1;
                }


                int expand = 5;
                for (int i = 0; i < 2; i++)
                {
                    hullRects[i].Y        += expand;
                    hullRects[i].Height   += expand * 2;
                    hullRects[i].Location -= MathUtils.ToPoint((subs[i].WorldPosition - subs[i].HiddenSubPosition));
                    hulls[i] = new Hull(MapEntityPrefab.Find(null, "hull"), hullRects[i], subs[i]);
                    hulls[i].AddToGrid(subs[i]);
                    hulls[i].FreeID();

                    for (int j = 0; j < 2; j++)
                    {
                        bodies[i + j * 2] = GameMain.World.CreateEdge(
                            ConvertUnits.ToSimUnits(new Vector2(hullRects[i].X + hullRects[i].Width * j, hullRects[i].Y)),
                            ConvertUnits.ToSimUnits(new Vector2(hullRects[i].X + hullRects[i].Width * j, hullRects[i].Y - hullRects[i].Height)));
                    }
                }

                if (midHullDiff <= 100 && hulls[0].Submarine != null)
                {
                    outsideBlocker = hulls[0].Submarine.PhysicsBody.FarseerBody.CreateRectangle(
                        ConvertUnits.ToSimUnits(hullRects[0].Width),
                        ConvertUnits.ToSimUnits(hullRects[0].Height + hullRects[1].Height),
                        density: 0.0f,
                        offset: ConvertUnits.ToSimUnits(new Vector2(hullRects[0].Center.X, hullRects[0].Y) - hulls[0].Submarine.HiddenSubPosition));
                    outsideBlocker.UserData = this;
                }

                gap = new Gap(new Rectangle(hullRects[0].X, hullRects[0].Y + 2, hullRects[0].Width, 4), false, subs[0]);
            }

            LinkHullsToGaps();

            hulls[0].ShouldBeSaved = false;
            hulls[1].ShouldBeSaved = false;
            item.linkedTo.Add(hulls[0]);
            item.linkedTo.Add(hulls[1]);

            gap.FreeID();
            gap.DisableHullRechecks = true;
            gap.ShouldBeSaved       = false;
            item.linkedTo.Add(gap);

            foreach (Body body in bodies)
            {
                if (body == null)
                {
                    continue;
                }
                body.BodyType = BodyType.Static;
                body.Friction = 0.5f;

                body.CollisionCategories = Physics.CollisionWall;
            }
        }
Beispiel #4
0
        public void Undock()
        {
            if (DockingTarget == null || !docked)
            {
                return;
            }

            forceLockTimer = 0.0f;

            ApplyStatusEffects(ActionType.OnSecondaryUse, 1.0f);

            DockingTarget.item.Submarine.DockedTo.Remove(item.Submarine);
            item.Submarine.DockedTo.Remove(DockingTarget.item.Submarine);

            if (door != null && DockingTarget.door != null)
            {
                WayPoint myWayPoint     = WayPoint.WayPointList.Find(wp => door.LinkedGap == wp.ConnectedGap);
                WayPoint targetWayPoint = WayPoint.WayPointList.Find(wp => DockingTarget.door.LinkedGap == wp.ConnectedGap);

                if (myWayPoint != null && targetWayPoint != null)
                {
                    myWayPoint.linkedTo.Remove(targetWayPoint);
                    targetWayPoint.linkedTo.Remove(myWayPoint);
                }
            }

            item.linkedTo.Clear();

            docked = false;

            DockingTarget.Undock();
            DockingTarget = null;

            if (doorBody != null)
            {
                GameMain.World.RemoveBody(doorBody);
                doorBody = null;
            }

            var wire = item.GetComponent <Wire>();

            if (wire != null)
            {
                wire.Drop(null);
            }

            if (joint != null)
            {
                GameMain.World.RemoveJoint(joint);
                joint = null;
            }

            hulls[0]?.Remove(); hulls[0] = null;
            hulls[1]?.Remove(); hulls[1] = null;

            if (gap != null)
            {
                gap.Remove();
                gap = null;
            }

            if (bodies != null)
            {
                foreach (Body body in bodies)
                {
                    if (body == null)
                    {
                        continue;
                    }
                    GameMain.World.RemoveBody(body);
                }
                bodies = null;
            }

            Item.Submarine.EnableObstructedWaypoints();
            obstructedWayPointsDisabled = false;

#if SERVER
            if (GameMain.Server != null)
            {
                item.CreateServerEvent(this);
            }
#endif
        }
Beispiel #5
0
        public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
        {
            bool isDocked = msg.ReadBoolean();

            for (int i = 0; i < 2; i++)
            {
                if (hulls[i] == null)
                {
                    continue;
                }
                item.linkedTo.Remove(hulls[i]);
                hulls[i].Remove();
                hulls[i] = null;
            }

            if (gap != null)
            {
                item.linkedTo.Remove(gap);
                gap.Remove();
                gap = null;
            }

            if (isDocked)
            {
                ushort dockingTargetID = msg.ReadUInt16();

                bool isLocked = msg.ReadBoolean();

                Entity targetEntity = Entity.FindEntityByID(dockingTargetID);
                if (targetEntity == null || !(targetEntity is Item))
                {
                    DebugConsole.ThrowError("Invalid docking port network event (can't dock to " + (targetEntity?.ToString() ?? "null") + ")");
                    return;
                }

                DockingTarget = (targetEntity as Item).GetComponent <DockingPort>();
                if (DockingTarget == null)
                {
                    DebugConsole.ThrowError("Invalid docking port network event (" + targetEntity + " doesn't have a docking port component)");
                    return;
                }

                Dock(DockingTarget);
                if (joint == null)
                {
                    string errorMsg = "Error while reading a docking port network event (Dock method did not create a joint between the ports)." +
                                      " Submarine: " + (item.Submarine?.Info.Name ?? "null") +
                                      ", target submarine: " + (DockingTarget.item.Submarine?.Info.Name ?? "null");
                    if (item.Submarine?.ConnectedDockingPorts.ContainsKey(DockingTarget.item.Submarine) ?? false)
                    {
                        errorMsg += "\nAlready docked.";
                    }
                    if (item.Submarine == DockingTarget.item.Submarine)
                    {
                        errorMsg += "\nTrying to dock the submarine to itself.";
                    }
                    GameAnalyticsManager.AddErrorEventOnce("DockingPort.ClientRead:JointNotCreated", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
                }

                if (isLocked)
                {
                    if (DockingTarget.joint != null)
                    {
                        DockingTarget.Lock(isNetworkMessage: true);
                    }
                    else
                    {
                        Lock(isNetworkMessage: true);
                    }
                }
            }
            else
            {
                Undock();
            }
        }