private void FindSpawnPosition(bool affectSubImmediately)
        {
            if (disallowed)
            {
                return;
            }

            if (Rand.Value(Rand.RandSync.Server) > prefab.SpawnProbability)
            {
                spawnPos = null;
                Finished();
                return;
            }

            spawnPos = Vector2.Zero;
            var  availablePositions = GetAvailableSpawnPositions();
            var  chosenPosition     = new Level.InterestingPosition(Point.Zero, Level.PositionType.MainPath, isValid: false);
            bool isSubOrWreck       = spawnPosType == Level.PositionType.Ruin || spawnPosType == Level.PositionType.Wreck;

            if (affectSubImmediately && !isSubOrWreck)
            {
                if (availablePositions.None())
                {
                    //no suitable position found, disable the event
                    spawnPos = null;
                    Finished();
                    return;
                }
                Submarine refSub = GetReferenceSub();
                if (Submarine.MainSubs.Length == 2 && Submarine.MainSubs[1] != null)
                {
                    refSub = Submarine.MainSubs.GetRandom(Rand.RandSync.Unsynced);
                }
                float closestDist = float.PositiveInfinity;
                //find the closest spawnposition that isn't too close to any of the subs
                foreach (var position in availablePositions)
                {
                    Vector2 pos  = position.Position.ToVector2();
                    float   dist = Vector2.DistanceSquared(pos, refSub.WorldPosition);
                    foreach (Submarine sub in Submarine.Loaded)
                    {
                        if (sub.Info.Type != SubmarineType.Player)
                        {
                            continue;
                        }

                        float minDistToSub = GetMinDistanceToSub(sub);
                        if (dist < minDistToSub * minDistToSub)
                        {
                            continue;
                        }

                        if (closestDist == float.PositiveInfinity)
                        {
                            closestDist    = dist;
                            chosenPosition = position;
                            continue;
                        }

                        //chosen position behind the sub -> override with anything that's closer or to the right
                        if (chosenPosition.Position.X < refSub.WorldPosition.X)
                        {
                            if (dist < closestDist || pos.X > refSub.WorldPosition.X)
                            {
                                closestDist    = dist;
                                chosenPosition = position;
                            }
                        }
                        //chosen position ahead of the sub -> only override with a position that's also ahead
                        else if (chosenPosition.Position.X > refSub.WorldPosition.X)
                        {
                            if (dist < closestDist && pos.X > refSub.WorldPosition.X)
                            {
                                closestDist    = dist;
                                chosenPosition = position;
                            }
                        }
                    }
                }
                //only found a spawnpos that's very far from the sub, pick one that's closer
                //and wait for the sub to move further before spawning
                if (closestDist > 15000.0f * 15000.0f)
                {
                    foreach (var position in availablePositions)
                    {
                        float dist = Vector2.DistanceSquared(position.Position.ToVector2(), refSub.WorldPosition);
                        if (dist < closestDist)
                        {
                            closestDist    = dist;
                            chosenPosition = position;
                        }
                    }
                }
            }
            else
            {
                if (!isSubOrWreck)
                {
                    float minDistance = 20000;
                    var   refSub      = GetReferenceSub();
                    availablePositions.RemoveAll(p => Vector2.DistanceSquared(refSub.WorldPosition, p.Position.ToVector2()) < minDistance * minDistance);
                    if (Submarine.MainSubs.Length > 1)
                    {
                        for (int i = 1; i < Submarine.MainSubs.Length; i++)
                        {
                            availablePositions.RemoveAll(p => Vector2.DistanceSquared(Submarine.MainSubs[i].WorldPosition, p.Position.ToVector2()) < minDistance * minDistance);
                        }
                    }
                }
                if (availablePositions.None())
                {
                    //no suitable position found, disable the event
                    spawnPos = null;
                    Finished();
                    return;
                }
                chosenPosition = availablePositions.GetRandom();
            }
            if (chosenPosition.IsValid)
            {
                spawnPos = chosenPosition.Position.ToVector2();
                if (chosenPosition.Submarine != null || chosenPosition.Ruin != null)
                {
                    var spawnPoint = WayPoint.GetRandom(SpawnType.Enemy, sub: chosenPosition.Submarine, ruin: chosenPosition.Ruin, useSyncedRand: false);
                    if (spawnPoint != null)
                    {
                        System.Diagnostics.Debug.Assert(spawnPoint.Submarine == chosenPosition.Submarine);
                        System.Diagnostics.Debug.Assert(spawnPoint.ParentRuin == chosenPosition.Ruin);
                        spawnPos = spawnPoint.WorldPosition;
                    }
                }
                else if ((chosenPosition.PositionType == Level.PositionType.MainPath || chosenPosition.PositionType == Level.PositionType.SidePath) &&
                         offset > 0)
                {
                    Vector2 dir;
                    var     waypoints       = WayPoint.WayPointList.FindAll(wp => wp.Submarine == null);
                    var     nearestWaypoint = waypoints.OrderBy(wp => Vector2.DistanceSquared(wp.WorldPosition, spawnPos.Value)).FirstOrDefault();
                    if (nearestWaypoint != null)
                    {
                        int currentIndex = waypoints.IndexOf(nearestWaypoint);
                        var nextWaypoint = waypoints[Math.Min(currentIndex + 20, waypoints.Count - 1)];
                        dir = Vector2.Normalize(nextWaypoint.WorldPosition - nearestWaypoint.WorldPosition);
                        // Ensure that the spawn position is not offset to the left.
                        if (dir.X < 0)
                        {
                            dir.X = 0;
                        }
                    }
                    else
                    {
                        dir = new Vector2(1, Rand.Range(-1, 1));
                    }
                    Vector2 targetPos      = spawnPos.Value + dir * offset;
                    var     targetWaypoint = waypoints.OrderBy(wp => Vector2.DistanceSquared(wp.WorldPosition, targetPos)).FirstOrDefault();
                    if (targetWaypoint != null)
                    {
                        spawnPos = targetWaypoint.WorldPosition;
                    }
                }
                spawnPending = true;
            }
        }
Ejemplo n.º 2
0
        public override void UpdateEditing(Camera cam)
        {
            if (editingHUD == null || editingHUD.UserData != this)
            {
                editingHUD = CreateEditingHUD();
            }

            if (IsSelected && PlayerInput.PrimaryMouseButtonClicked())
            {
                Vector2 position = cam.ScreenToWorld(PlayerInput.MousePosition);

                if (PlayerInput.KeyDown(Keys.Space))
                {
                    foreach (MapEntity e in mapEntityList)
                    {
                        if (e.GetType() != typeof(WayPoint))
                        {
                            continue;
                        }
                        if (e == this)
                        {
                            continue;
                        }

                        if (!Submarine.RectContains(e.Rect, position))
                        {
                            continue;
                        }

                        if (linkedTo.Contains(e))
                        {
                            linkedTo.Remove(e);
                            e.linkedTo.Remove(this);
                        }
                        else
                        {
                            linkedTo.Add(e);
                            e.linkedTo.Add(this);
                        }
                    }
                }
                else
                {
                    // Update gaps, ladders, and stairs
                    UpdateLinkedEntity(position, Gap.GapList, gap => ConnectedGap = gap, gap =>
                    {
                        if (ConnectedGap == gap)
                        {
                            ConnectedGap = null;
                        }
                    });
                    UpdateLinkedEntity(position, Item.ItemList, i =>
                    {
                        var ladder = i?.GetComponent <Ladder>();
                        if (ladder != null)
                        {
                            Ladders = ladder;
                        }
                    }, i =>
                    {
                        var ladder = i?.GetComponent <Ladder>();
                        if (ladder != null)
                        {
                            if (Ladders == ladder)
                            {
                                Ladders = null;
                            }
                        }
                    }, inflate: 5);
                    // TODO: Cannot check the rectangle, since the rectangle is not rotated -> Need to use the collider.
                    //var stairList = mapEntityList.Where(me => me is Structure s && s.StairDirection != Direction.None).Select(me => me as Structure);
                    //UpdateLinkedEntity(position, stairList, s =>
                    //{
                    //    Stairs = s;
                    //}, s =>
                    //{
                    //    if (Stairs == s)
                    //    {
                    //        Stairs = null;
                    //    }
                    //});
                }
            }
        }
Ejemplo n.º 3
0
        private static void InitProjectSpecific()
        {
            commands.Add(new Command("autohull", "", (string[] args) =>
            {
                if (Screen.Selected != GameMain.SubEditorScreen)
                {
                    return;
                }

                if (MapEntity.mapEntityList.Any(e => e is Hull || e is Gap))
                {
                    ShowQuestionPrompt("This submarine already has hulls and/or gaps. This command will delete them. Do you want to continue? Y/N",
                                       (option) => {
                        if (option.ToLower() == "y")
                        {
                            GameMain.SubEditorScreen.AutoHull();
                        }
                    });
                }
                else
                {
                    GameMain.SubEditorScreen.AutoHull();
                }
            }));

            commands.Add(new Command("startclient", "", (string[] args) =>
            {
                if (args.Length == 0)
                {
                    return;
                }

                if (GameMain.Client == null)
                {
                    GameMain.NetworkMember = new GameClient("Name");
                    GameMain.Client.ConnectToServer(args[0]);
                }
            }));

            commands.Add(new Command("mainmenuscreen|mainmenu|menu", "mainmenu/menu: Go to the main menu.", (string[] args) =>
            {
                GameMain.GameSession = null;

                List <Character> characters = new List <Character>(Character.CharacterList);
                foreach (Character c in characters)
                {
                    c.Remove();
                }

                GameMain.MainMenuScreen.Select();
            }));

            commands.Add(new Command("gamescreen|game", "gamescreen/game: Go to the \"in-game\" view.", (string[] args) =>
            {
                GameMain.GameScreen.Select();
            }));

            commands.Add(new Command("editsubscreen|editsub|subeditor", "editsub/subeditor: Switch to the submarine editor.", (string[] args) =>
            {
                if (args.Length > 0)
                {
                    Submarine.Load(string.Join(" ", args), true);
                }
                GameMain.SubEditorScreen.Select();
            }));

            commands.Add(new Command("editparticles|particleeditor", "", (string[] args) =>
            {
                GameMain.ParticleEditorScreen.Select();
            }));

            commands.Add(new Command("editlevels|editlevel|leveleditor", "", (string[] args) =>
            {
                GameMain.LevelEditorScreen.Select();
            }));

            commands.Add(new Command("editsprites|editsprite|spriteeditor|spriteedit", "", (string[] args) =>
            {
                GameMain.SpriteEditorScreen.Select();
            }));

            commands.Add(new Command("charactereditor|editcharacter|editcharacters|editanimation|editanimations|animedit|animationeditor|animeditor|animationedit", "charactereditor: Edit characters, animations, ragdolls....", (string[] args) =>
            {
                GameMain.CharacterEditorScreen.Select();
            }));

            commands.Add(new Command("control|controlcharacter", "control [character name]: Start controlling the specified character.", (string[] args) =>
            {
                if (args.Length < 1)
                {
                    return;
                }

                var character = FindMatchingCharacter(args, true);

                if (character != null)
                {
                    Character.Controlled = character;
                }
            },
                                     () =>
            {
                return(new string[][]
                {
                    Character.CharacterList.Select(c => c.Name).Distinct().ToArray()
                });
            }, isCheat: true));

            commands.Add(new Command("shake", "", (string[] args) =>
            {
                GameMain.GameScreen.Cam.Shake = 10.0f;
            }));

            commands.Add(new Command("los", "los: Toggle the line of sight effect on/off.", (string[] args) =>
            {
                GameMain.LightManager.LosEnabled = !GameMain.LightManager.LosEnabled;
                NewMessage("Line of sight effect " + (GameMain.LightManager.LosEnabled ? "enabled" : "disabled"), Color.White);
            }, isCheat: true));

            commands.Add(new Command("lighting|lights", "Toggle lighting on/off.", (string[] args) =>
            {
                GameMain.LightManager.LightingEnabled = !GameMain.LightManager.LightingEnabled;
                NewMessage("Lighting " + (GameMain.LightManager.LightingEnabled ? "enabled" : "disabled"), Color.White);
            }, isCheat: true));

            commands.Add(new Command("multiplylights [color]", "Multiplies the colors of all the static lights in the sub with the given color value.", (string[] args) =>
            {
                if (Screen.Selected != GameMain.SubEditorScreen || args.Length < 1)
                {
                    return;
                }

                Color color = XMLExtensions.ParseColor(args[0]);
                foreach (Item item in Item.ItemList)
                {
                    if (item.ParentInventory != null || item.body != null)
                    {
                        continue;
                    }
                    var lightComponent = item.GetComponent <LightComponent>();
                    if (lightComponent != null)
                    {
                        lightComponent.LightColor =
                            new Color(
                                (lightComponent.LightColor.R / 255.0f) * (color.R / 255.0f),
                                (lightComponent.LightColor.G / 255.0f) * (color.G / 255.0f),
                                (lightComponent.LightColor.B / 255.0f) * (color.B / 255.0f),
                                (lightComponent.LightColor.A / 255.0f) * (color.A / 255.0f));
                    }
                }
            }, isCheat: false));

            commands.Add(new Command("tutorial", "", (string[] args) =>
            {
                TutorialMode.StartTutorial(Tutorials.Tutorial.Tutorials[0]);
            }));

            commands.Add(new Command("lobby|lobbyscreen", "", (string[] args) =>
            {
                GameMain.LobbyScreen.Select();
            }));

            commands.Add(new Command("save|savesub", "save [submarine name]: Save the currently loaded submarine using the specified name.", (string[] args) =>
            {
                if (args.Length < 1)
                {
                    return;
                }

                if (GameMain.SubEditorScreen.CharacterMode)
                {
                    GameMain.SubEditorScreen.SetCharacterMode(false);
                }

                string fileName = string.Join(" ", args);
                if (fileName.Contains("../"))
                {
                    ThrowError("Illegal symbols in filename (../)");
                    return;
                }

                if (Submarine.SaveCurrent(System.IO.Path.Combine(Submarine.SavePath, fileName + ".sub")))
                {
                    NewMessage("Sub saved", Color.Green);
                }
            }));

            commands.Add(new Command("load|loadsub", "load [submarine name]: Load a submarine.", (string[] args) =>
            {
                if (args.Length == 0)
                {
                    return;
                }
                Submarine.Load(string.Join(" ", args), true);
            }));

            commands.Add(new Command("cleansub", "", (string[] args) =>
            {
                for (int i = MapEntity.mapEntityList.Count - 1; i >= 0; i--)
                {
                    MapEntity me = MapEntity.mapEntityList[i];

                    if (me.SimPosition.Length() > 2000.0f)
                    {
                        NewMessage("Removed " + me.Name + " (simposition " + me.SimPosition + ")", Color.Orange);
                        MapEntity.mapEntityList.RemoveAt(i);
                    }
                    else if (!me.ShouldBeSaved)
                    {
                        NewMessage("Removed " + me.Name + " (!ShouldBeSaved)", Color.Orange);
                        MapEntity.mapEntityList.RemoveAt(i);
                    }
                    else if (me is Item)
                    {
                        Item item = me as Item;
                        var wire  = item.GetComponent <Wire>();
                        if (wire == null)
                        {
                            continue;
                        }

                        if (wire.GetNodes().Count > 0 && !wire.Connections.Any(c => c != null))
                        {
                            wire.Item.Drop(null);
                            NewMessage("Dropped wire (ID: " + wire.Item.ID + ") - attached on wall but no connections found", Color.Orange);
                        }
                    }
                }
            }, isCheat: true));

            commands.Add(new Command("messagebox", "", (string[] args) =>
            {
                new GUIMessageBox("", string.Join(" ", args));
            }));

            commands.Add(new Command("debugdraw", "debugdraw: Toggle the debug drawing mode on/off.", (string[] args) =>
            {
                GameMain.DebugDraw = !GameMain.DebugDraw;
                NewMessage("Debug draw mode " + (GameMain.DebugDraw ? "enabled" : "disabled"), Color.White);
            }, isCheat: true));

            commands.Add(new Command("fpscounter", "fpscounter: Toggle the FPS counter.", (string[] args) =>
            {
                GameMain.ShowFPS = !GameMain.ShowFPS;
                NewMessage("FPS counter " + (GameMain.DebugDraw ? "enabled" : "disabled"), Color.White);
            }));
            commands.Add(new Command("showperf", "showperf: Toggle performance statistics on/off.", (string[] args) =>
            {
                GameMain.ShowPerf = !GameMain.ShowPerf;
                NewMessage("Performance statistics " + (GameMain.ShowPerf ? "enabled" : "disabled"), Color.White);
            }));

            commands.Add(new Command("hudlayoutdebugdraw|debugdrawhudlayout", "hudlayoutdebugdraw: Toggle the debug drawing mode of HUD layout areas on/off.", (string[] args) =>
            {
                HUDLayoutSettings.DebugDraw = !HUDLayoutSettings.DebugDraw;
                NewMessage("HUD layout debug draw mode " + (HUDLayoutSettings.DebugDraw ? "enabled" : "disabled"), Color.White);
            }));

            commands.Add(new Command("interactdebugdraw|debugdrawinteract", "interactdebugdraw: Toggle the debug drawing mode of item interaction ranges on/off.", (string[] args) =>
            {
                Character.DebugDrawInteract = !Character.DebugDrawInteract;
                NewMessage("Interact debug draw mode " + (Character.DebugDrawInteract ? "enabled" : "disabled"), Color.White);
            }, isCheat: true));

            commands.Add(new Command("togglehud|hud", "togglehud/hud: Toggle the character HUD (inventories, icons, buttons, etc) on/off.", (string[] args) =>
            {
                GUI.DisableHUD = !GUI.DisableHUD;
                GameMain.Instance.IsMouseVisible = !GameMain.Instance.IsMouseVisible;
                NewMessage(GUI.DisableHUD ? "Disabled HUD" : "Enabled HUD", Color.White);
            }));

            commands.Add(new Command("followsub", "followsub: Toggle whether the camera should follow the nearest submarine.", (string[] args) =>
            {
                Camera.FollowSub = !Camera.FollowSub;
                NewMessage(Camera.FollowSub ? "Set the camera to follow the closest submarine" : "Disabled submarine following.", Color.White);
            }));

            commands.Add(new Command("toggleaitargets|aitargets", "toggleaitargets/aitargets: Toggle the visibility of AI targets (= targets that enemies can detect and attack/escape from).", (string[] args) =>
            {
                AITarget.ShowAITargets = !AITarget.ShowAITargets;
                NewMessage(AITarget.ShowAITargets ? "Enabled AI target drawing" : "Disabled AI target drawing", Color.White);
            }, isCheat: true));
#if DEBUG
            commands.Add(new Command("spamchatmessages", "", (string[] args) =>
            {
                int msgCount = 1000;
                if (args.Length > 0)
                {
                    int.TryParse(args[0], out msgCount);
                }
                int msgLength = 50;
                if (args.Length > 1)
                {
                    int.TryParse(args[1], out msgLength);
                }

                for (int i = 0; i < msgCount; i++)
                {
                    if (GameMain.Server != null)
                    {
                        GameMain.Server.SendChatMessage(ToolBox.RandomSeed(msgLength), ChatMessageType.Default);
                    }
                    else if (GameMain.Client != null)
                    {
                        GameMain.Client.SendChatMessage(ToolBox.RandomSeed(msgLength));
                    }
                }
            }));

            commands.Add(new Command("camerasettings", "camerasettings [defaultzoom] [zoomsmoothness] [movesmoothness] [minzoom] [maxzoom]: debug command for testing camera settings. The values default to 1.1, 8.0, 8.0, 0.1 and 2.0.", (string[] args) =>
            {
                float defaultZoom = Screen.Selected.Cam.DefaultZoom;
                if (args.Length > 0)
                {
                    float.TryParse(args[0], NumberStyles.Number, CultureInfo.InvariantCulture, out defaultZoom);
                }

                float zoomSmoothness = Screen.Selected.Cam.ZoomSmoothness;
                if (args.Length > 1)
                {
                    float.TryParse(args[1], NumberStyles.Number, CultureInfo.InvariantCulture, out zoomSmoothness);
                }
                float moveSmoothness = Screen.Selected.Cam.MoveSmoothness;
                if (args.Length > 2)
                {
                    float.TryParse(args[2], NumberStyles.Number, CultureInfo.InvariantCulture, out moveSmoothness);
                }

                float minZoom = Screen.Selected.Cam.MinZoom;
                if (args.Length > 3)
                {
                    float.TryParse(args[3], NumberStyles.Number, CultureInfo.InvariantCulture, out minZoom);
                }
                float maxZoom = Screen.Selected.Cam.MaxZoom;
                if (args.Length > 4)
                {
                    float.TryParse(args[4], NumberStyles.Number, CultureInfo.InvariantCulture, out maxZoom);
                }

                Screen.Selected.Cam.DefaultZoom    = defaultZoom;
                Screen.Selected.Cam.ZoomSmoothness = zoomSmoothness;
                Screen.Selected.Cam.MoveSmoothness = moveSmoothness;
                Screen.Selected.Cam.MinZoom        = minZoom;
                Screen.Selected.Cam.MaxZoom        = maxZoom;
            }));
#endif

            commands.Add(new Command("dumptexts", "dumptexts [filepath]: Extracts all the texts from the given text xml and writes them into a file (using the same filename, but with the .txt extension). If the filepath is omitted, the EnglishVanilla.xml file is used.", (string[] args) =>
            {
                string filePath = args.Length > 0 ? args[0] : "Content/Texts/EnglishVanilla.xml";
                var doc         = XMLExtensions.TryLoadXml(filePath);
                if (doc?.Root == null)
                {
                    return;
                }
                List <string> lines = new List <string>();
                foreach (XElement element in doc.Root.Elements())
                {
                    lines.Add(element.ElementInnerText());
                }
                File.WriteAllLines(Path.GetFileNameWithoutExtension(filePath) + ".txt", lines);
            },
                                     () =>
            {
                var files = TextManager.GetTextFiles().Select(f => f.Replace("\\", "/"));
                return(new string[][]
                {
                    TextManager.GetTextFiles().Where(f => Path.GetExtension(f) == ".xml").ToArray()
                });
            }));

            commands.Add(new Command("loadtexts", "loadtexts [sourcefile] [destinationfile]: Loads all lines of text from a given .txt file and inserts them sequientially into the elements of an xml file. If the file paths are omitted, EnglishVanilla.txt and EnglishVanilla.xml are used.", (string[] args) =>
            {
                string sourcePath      = args.Length > 0 ? args[0] : "Content/Texts/EnglishVanilla.txt";
                string destinationPath = args.Length > 1 ? args[1] : "Content/Texts/EnglishVanilla.xml";

                string[] lines;
                try
                {
                    lines = File.ReadAllLines(sourcePath);
                }
                catch (Exception e)
                {
                    ThrowError("Reading the file \"" + sourcePath + "\" failed.", e);
                    return;
                }
                var doc = XMLExtensions.TryLoadXml(destinationPath);
                int i   = 0;
                foreach (XElement element in doc.Root.Elements())
                {
                    if (i >= lines.Length)
                    {
                        ThrowError("Error while loading texts to the xml file. The xml has more elements than the number of lines in the text file.");
                        return;
                    }
                    element.Value = lines[i];
                    i++;
                }
                doc.Save(destinationPath);
            },
                                     () =>
            {
                var files = TextManager.GetTextFiles().Select(f => f.Replace("\\", "/"));
                return(new string[][]
                {
                    files.Where(f => Path.GetExtension(f) == ".txt").ToArray(),
                    files.Where(f => Path.GetExtension(f) == ".xml").ToArray()
                });
            }));

            commands.Add(new Command("updatetextfile", "updatetextfile [sourcefile] [destinationfile]: Inserts all the xml elements that are only present in the source file into the destination file. Can be used to update outdated translation files more easily.", (string[] args) =>
            {
                if (args.Length < 2)
                {
                    return;
                }
                string sourcePath      = args[0];
                string destinationPath = args[1];

                var sourceDoc      = XMLExtensions.TryLoadXml(sourcePath);
                var destinationDoc = XMLExtensions.TryLoadXml(destinationPath);

                XElement destinationElement = destinationDoc.Root.Elements().First();
                foreach (XElement element in sourceDoc.Root.Elements())
                {
                    if (destinationDoc.Root.Element(element.Name) == null)
                    {
                        element.Value = "!!!!!!!!!!!!!" + element.Value;
                        destinationElement.AddAfterSelf(element);
                    }
                    XNode nextNode = destinationElement.NextNode;
                    while ((!(nextNode is XElement) || nextNode == element) && nextNode != null)
                    {
                        nextNode = nextNode.NextNode;
                    }
                    destinationElement = nextNode as XElement;
                }
                destinationDoc.Save(destinationPath);
            },
                                     () =>
            {
                var files = TextManager.GetTextFiles().Where(f => Path.GetExtension(f) == ".xml").Select(f => f.Replace("\\", "/")).ToArray();
                return(new string[][]
                {
                    files,
                    files
                });
            }));

            commands.Add(new Command("dumpentitytexts", "dumpentitytexts [filepath]: gets the names and descriptions of all entity prefabs and writes them into a file along with xml tags that can be used in translation files. If the filepath is omitted, the file is written to Content/Texts/EntityTexts.txt", (string[] args) =>
            {
                string filePath     = args.Length > 0 ? args[0] : "Content/Texts/EntityTexts.txt";
                List <string> lines = new List <string>();
                foreach (MapEntityPrefab me in MapEntityPrefab.List)
                {
                    lines.Add("<EntityName." + me.Identifier + ">" + me.Name + "</" + me.Identifier + ".Name>");
                    lines.Add("<EntityDescription." + me.Identifier + ">" + me.Description + "</" + me.Identifier + ".Description>");
                }
                File.WriteAllLines(filePath, lines);
            }));


            commands.Add(new Command("cleanbuild", "", (string[] args) =>
            {
                GameMain.Config.MusicVolume = 0.5f;
                GameMain.Config.SoundVolume = 0.5f;
                NewMessage("Music and sound volume set to 0.5", Color.Green);

                GameMain.Config.GraphicsWidth  = 0;
                GameMain.Config.GraphicsHeight = 0;
                GameMain.Config.WindowMode     = WindowMode.Fullscreen;
                NewMessage("Resolution set to 0 x 0 (screen resolution will be used)", Color.Green);
                NewMessage("Fullscreen enabled", Color.Green);

                GameSettings.ShowUserStatisticsPrompt = true;

                GameSettings.VerboseLogging = false;

                if (GameMain.Config.MasterServerUrl != "http://www.undertowgames.com/baromaster")
                {
                    ThrowError("MasterServerUrl \"" + GameMain.Config.MasterServerUrl + "\"!");
                }

                GameMain.Config.Save();

                var saveFiles = System.IO.Directory.GetFiles(SaveUtil.SaveFolder);

                foreach (string saveFile in saveFiles)
                {
                    System.IO.File.Delete(saveFile);
                    NewMessage("Deleted " + saveFile, Color.Green);
                }

                if (System.IO.Directory.Exists(System.IO.Path.Combine(SaveUtil.SaveFolder, "temp")))
                {
                    System.IO.Directory.Delete(System.IO.Path.Combine(SaveUtil.SaveFolder, "temp"), true);
                    NewMessage("Deleted temp save folder", Color.Green);
                }

                if (System.IO.Directory.Exists(ServerLog.SavePath))
                {
                    var logFiles = System.IO.Directory.GetFiles(ServerLog.SavePath);

                    foreach (string logFile in logFiles)
                    {
                        System.IO.File.Delete(logFile);
                        NewMessage("Deleted " + logFile, Color.Green);
                    }
                }

                if (System.IO.File.Exists("filelist.xml"))
                {
                    System.IO.File.Delete("filelist.xml");
                    NewMessage("Deleted filelist", Color.Green);
                }

                if (System.IO.File.Exists("Data/bannedplayers.txt"))
                {
                    System.IO.File.Delete("Data/bannedplayers.txt");
                    NewMessage("Deleted bannedplayers.txt", Color.Green);
                }

                if (System.IO.File.Exists("Submarines/TutorialSub.sub"))
                {
                    System.IO.File.Delete("Submarines/TutorialSub.sub");

                    NewMessage("Deleted TutorialSub from the submarine folder", Color.Green);
                }

                if (System.IO.File.Exists(GameServer.SettingsFile))
                {
                    System.IO.File.Delete(GameServer.SettingsFile);
                    NewMessage("Deleted server settings", Color.Green);
                }

                if (System.IO.File.Exists(GameServer.ClientPermissionsFile))
                {
                    System.IO.File.Delete(GameServer.ClientPermissionsFile);
                    NewMessage("Deleted client permission file", Color.Green);
                }

                if (System.IO.File.Exists("crashreport.log"))
                {
                    System.IO.File.Delete("crashreport.log");
                    NewMessage("Deleted crashreport.log", Color.Green);
                }

                if (!System.IO.File.Exists("Content/Map/TutorialSub.sub"))
                {
                    ThrowError("TutorialSub.sub not found!");
                }
            }));

            commands.Add(new Command("reloadtextures|reloadtexture", "", (string[] args) =>
            {
                var item      = Character.Controlled.FocusedItem;
                var character = Character.Controlled;
                if (item != null)
                {
                    item.Sprite.ReloadTexture();
                }
                else if (character != null)
                {
                    foreach (var limb in character.AnimController.Limbs)
                    {
                        limb.Sprite?.ReloadTexture();
                        limb.DamagedSprite?.ReloadTexture();
                        limb.DeformSprite?.Sprite.ReloadTexture();
                        // update specular
                        limb.WearingItems.ForEach(i => i.Sprite.ReloadTexture());
                    }
                }
                else
                {
                    ThrowError("Not controlling any character!");
                    return;
                }
            }, isCheat: true));

            commands.Add(new Command("limbscale", "Note: the changes are not saved!", (string[] args) =>
            {
                var character = Character.Controlled;
                if (character == null)
                {
                    ThrowError("Not controlling any character!");
                    return;
                }
                if (args.Length == 0)
                {
                    ThrowError("Please give the value after the command.");
                    return;
                }
                if (!float.TryParse(args[0], NumberStyles.Number, CultureInfo.InvariantCulture, out float value))
                {
                    ThrowError("Failed to parse float value from the arguments");
                    return;
                }
                RagdollParams ragdollParams = character.AnimController.RagdollParams;
                ragdollParams.LimbScale     = value;
                var pos = character.WorldPosition;
                character.AnimController.Recreate();
                character.TeleportTo(pos);
            }, isCheat: true));

            commands.Add(new Command("jointscale", "Note: the changes are not saved!", (string[] args) =>
            {
                var character = Character.Controlled;
                if (character == null)
                {
                    ThrowError("Not controlling any character!");
                    return;
                }
                if (args.Length == 0)
                {
                    ThrowError("Please give the value after the command.");
                    return;
                }
                if (!float.TryParse(args[0], NumberStyles.Number, CultureInfo.InvariantCulture, out float value))
                {
                    ThrowError("Failed to parse float value from the arguments");
                    return;
                }
                RagdollParams ragdollParams = character.AnimController.RagdollParams;
                ragdollParams.JointScale    = value;
                var pos = character.WorldPosition;
                character.AnimController.Recreate();
                character.TeleportTo(pos);
            }, isCheat: true));

            commands.Add(new Command("ragdollscale", "Note: the changes are not saved!", (string[] args) =>
            {
                var character = Character.Controlled;
                if (character == null)
                {
                    ThrowError("Not controlling any character!");
                    return;
                }
                if (args.Length == 0)
                {
                    ThrowError("Please give the value after the command.");
                    return;
                }
                if (!float.TryParse(args[0], NumberStyles.Number, CultureInfo.InvariantCulture, out float value))
                {
                    ThrowError("Failed to parse float value from the arguments");
                    return;
                }
                RagdollParams ragdollParams = character.AnimController.RagdollParams;
                ragdollParams.LimbScale     = value;
                ragdollParams.JointScale    = value;
                var pos = character.WorldPosition;
                character.AnimController.Recreate();
                character.TeleportTo(pos);
            }, isCheat: true));

            commands.Add(new Command("recreateragdoll", "", (string[] args) =>
            {
                var character = (args.Length == 0) ? Character.Controlled : FindMatchingCharacter(args, true);
                if (character == null)
                {
                    ThrowError("Not controlling any character!");
                    return;
                }
                var pos = character.WorldPosition;
                character.AnimController.Recreate();
                character.TeleportTo(pos);
            }, isCheat: true));

            commands.Add(new Command("resetragdoll", "", (string[] args) =>
            {
                var character = (args.Length == 0) ? Character.Controlled : FindMatchingCharacter(args, true);
                if (character == null)
                {
                    ThrowError("Not controlling any character!");
                    return;
                }
                character.AnimController.ResetRagdoll();
            }, isCheat: true));
        }
Ejemplo n.º 4
0
 public void LoadPrevious()
 {
     Submarine.Unload();
     SaveUtil.LoadGame(SavePath);
 }
Ejemplo n.º 5
0
        //returns the water block which contains the point (or null if it isn't inside any)
        public static Hull FindHull(Vector2 position, Hull guess = null, bool useWorldCoordinates = true, bool inclusive = true)
        {
            if (EntityGrids == null)
            {
                return(null);
            }

            if (guess != null)
            {
                if (Submarine.RectContains(useWorldCoordinates ? guess.WorldRect : guess.rect, position, inclusive))
                {
                    return(guess);
                }
            }

            foreach (EntityGrid entityGrid in EntityGrids)
            {
                if (entityGrid.Submarine != null && !entityGrid.Submarine.Loading)
                {
                    System.Diagnostics.Debug.Assert(!entityGrid.Submarine.Removed);
                    Rectangle borders = entityGrid.Submarine.Borders;
                    if (useWorldCoordinates)
                    {
                        Vector2 worldPos = entityGrid.Submarine.WorldPosition;
                        borders.Location += new Point((int)worldPos.X, (int)worldPos.Y);
                    }
                    else
                    {
                        borders.Location += new Point((int)entityGrid.Submarine.HiddenSubPosition.X, (int)entityGrid.Submarine.HiddenSubPosition.Y);
                    }

                    const float padding = 128.0f;
                    if (position.X < borders.X - padding || position.X > borders.Right + padding ||
                        position.Y > borders.Y + padding || position.Y < borders.Y - borders.Height - padding)
                    {
                        continue;
                    }
                }

                Vector2 transformedPosition = position;
                if (useWorldCoordinates && entityGrid.Submarine != null)
                {
                    transformedPosition -= entityGrid.Submarine.Position;
                }

                var entities = entityGrid.GetEntities(transformedPosition);
                if (entities == null)
                {
                    continue;
                }
                foreach (Hull hull in entities)
                {
                    if (Submarine.RectContains(hull.rect, transformedPosition, inclusive))
                    {
                        return(hull);
                    }
                }
            }

            return(null);
        }
Ejemplo n.º 6
0
        private IEnumerable <object> Load()
        {
            if (GameSettings.VerboseLogging)
            {
                DebugConsole.NewMessage("LOADING COROUTINE", Color.Lime);
            }
            GUI.GraphicsDevice = base.GraphicsDevice;
            GUI.Init(Content);

            GUIComponent.Init(Window);
            DebugConsole.Init(Window);
            DebugConsole.Log(SelectedPackage == null ? "No content package selected" : "Content package \"" + SelectedPackage.Name + "\" selected");
            yield return(CoroutineStatus.Running);

            LightManager = new Lights.LightManager(base.GraphicsDevice);

            Hull.renderer         = new WaterRenderer(base.GraphicsDevice, Content);
            TitleScreen.LoadState = 1.0f;
            yield return(CoroutineStatus.Running);

            GUI.LoadContent();
            TitleScreen.LoadState = 2.0f;
            yield return(CoroutineStatus.Running);

            Mission.Init();
            MapEntityPrefab.Init();
            LevelGenerationParams.LoadPresets();
            TitleScreen.LoadState = 10.0f;
            yield return(CoroutineStatus.Running);

            JobPrefab.LoadAll(SelectedPackage.GetFilesOfType(ContentType.Jobs));
            // Add any missing jobs from the prefab into Config.JobNamePreferences.
            foreach (JobPrefab job in JobPrefab.List)
            {
                if (!Config.JobNamePreferences.Contains(job.Name))
                {
                    Config.JobNamePreferences.Add(job.Name);
                }
            }
            StructurePrefab.LoadAll(SelectedPackage.GetFilesOfType(ContentType.Structure));
            TitleScreen.LoadState = 20.0f;
            yield return(CoroutineStatus.Running);

            ItemPrefab.LoadAll(SelectedPackage.GetFilesOfType(ContentType.Item));
            TitleScreen.LoadState = 30.0f;
            yield return(CoroutineStatus.Running);

            Debug.WriteLine("sounds");
            CoroutineManager.StartCoroutine(SoundPlayer.Init());

            int i = 0;

            while (!SoundPlayer.Initialized)
            {
                i++;
                TitleScreen.LoadState = SoundPlayer.SoundCount == 0 ?
                                        30.0f :
                                        Math.Min(30.0f + 40.0f * i / Math.Max(SoundPlayer.SoundCount, 1), 70.0f);
                yield return(CoroutineStatus.Running);
            }

            TitleScreen.LoadState = 70.0f;
            yield return(CoroutineStatus.Running);

            GameModePreset.Init();

            Submarine.RefreshSavedSubs();
            TitleScreen.LoadState = 80.0f;
            yield return(CoroutineStatus.Running);

            GameScreen            = new GameScreen(GraphicsDeviceManager.GraphicsDevice, Content);
            TitleScreen.LoadState = 90.0f;
            yield return(CoroutineStatus.Running);

            MainMenuScreen = new MainMenuScreen(this);
            LobbyScreen    = new LobbyScreen();

            ServerListScreen = new ServerListScreen();

            EditMapScreen       = new EditMapScreen();
            EditCharacterScreen = new EditCharacterScreen();

            yield return(CoroutineStatus.Running);

            ParticleManager = new ParticleManager("Content/Particles/ParticlePrefabs.xml", GameScreen.Cam);
            DecalManager    = new DecalManager("Content/Particles/DecalPrefabs.xml");
            yield return(CoroutineStatus.Running);

            LocationType.Init();
            MainMenuScreen.Select();

            TitleScreen.LoadState = 100.0f;
            hasLoaded             = true;
            if (GameSettings.VerboseLogging)
            {
                DebugConsole.NewMessage("LOADING COROUTINE FINISHED", Color.Lime);
            }
            yield return(CoroutineStatus.Success);
        }
Ejemplo n.º 7
0
        public void DrawMap(GraphicsDevice graphics, SpriteBatch spriteBatch, double deltaTime)
        {
            foreach (Submarine sub in Submarine.Loaded)
            {
                sub.UpdateTransform();
            }

            GameMain.ParticleManager.UpdateTransforms();

            GameMain.LightManager.ObstructVision =
                Character.Controlled != null &&
                Character.Controlled.ObstructVision &&
                (Character.Controlled.ViewTarget == Character.Controlled || Character.Controlled.ViewTarget == null);

            if (Character.Controlled != null)
            {
                GameMain.LightManager.UpdateObstructVision(graphics, spriteBatch, cam, Character.Controlled.CursorWorldPosition);
            }

            //------------------------------------------------------------------------
            graphics.SetRenderTarget(renderTarget);
            graphics.Clear(Color.Transparent);
            //Draw background structures and wall background sprites
            //(= the background texture that's revealed when a wall is destroyed) into the background render target
            //These will be visible through the LOS effect.
            spriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.NonPremultiplied, null, DepthStencilState.None, null, null, cam.Transform);
            Submarine.DrawBack(spriteBatch, false, e => e is Structure s && (e.SpriteDepth >= 0.9f || s.Prefab.BackgroundSprite != null));
            Submarine.DrawPaintedColors(spriteBatch, false);
            spriteBatch.End();

            graphics.SetRenderTarget(null);
            GameMain.LightManager.RenderLightMap(graphics, spriteBatch, cam, renderTarget);

            //------------------------------------------------------------------------
            graphics.SetRenderTarget(renderTargetBackground);
            if (Level.Loaded == null)
            {
                graphics.Clear(new Color(11, 18, 26, 255));
            }
            else
            {
                //graphics.Clear(new Color(255, 255, 255, 255));
                Level.Loaded.DrawBack(graphics, spriteBatch, cam);
            }

            //draw alpha blended particles that are in water and behind subs
#if LINUX || OSX
            spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied, null, DepthStencilState.None, null, null, cam.Transform);
#else
            spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied, null, DepthStencilState.None, null, null, cam.Transform);
#endif
            GameMain.ParticleManager.Draw(spriteBatch, true, false, Particles.ParticleBlendState.AlphaBlend);
            spriteBatch.End();

            //draw additive particles that are in water and behind subs
            spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.Additive, null, DepthStencilState.None, null, null, cam.Transform);
            GameMain.ParticleManager.Draw(spriteBatch, true, false, Particles.ParticleBlendState.Additive);
            spriteBatch.End();
            spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied, null, DepthStencilState.None);
            spriteBatch.Draw(renderTarget, new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight), Color.White);
            spriteBatch.End();

            //----------------------------------------------------------------------------

            //Start drawing to the normal render target (stuff that can't be seen through the LOS effect)
            graphics.SetRenderTarget(renderTarget);

            graphics.BlendState       = BlendState.NonPremultiplied;
            graphics.SamplerStates[0] = SamplerState.LinearWrap;
            Quad.UseBasicEffect(renderTargetBackground);
            Quad.Render();

            //Draw the rest of the structures, characters and front structures
            spriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.NonPremultiplied, null, DepthStencilState.None, null, null, cam.Transform);
            Submarine.DrawBack(spriteBatch, false, e => !(e is Structure) || e.SpriteDepth < 0.9f);
            foreach (Character c in Character.CharacterList)
            {
                if (!c.IsVisible || c.AnimController.Limbs.Any(l => l.DeformSprite != null))
                {
                    continue;
                }
                c.Draw(spriteBatch, Cam);
            }
            spriteBatch.End();

            //draw characters with deformable limbs last, because they can't be batched into SpriteBatch
            //pretty hacky way of preventing draw order issues between normal and deformable sprites
            spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied, null, DepthStencilState.None, null, null, cam.Transform);
            //backwards order to render the most recently spawned characters in front (characters spawned later have a larger sprite depth)
            for (int i = Character.CharacterList.Count - 1; i >= 0; i--)
            {
                Character c = Character.CharacterList[i];
                if (!c.IsVisible || c.AnimController.Limbs.All(l => l.DeformSprite == null))
                {
                    continue;
                }
                c.Draw(spriteBatch, Cam);
            }
            spriteBatch.End();

            //draw the rendertarget and particles that are only supposed to be drawn in water into renderTargetWater
            graphics.SetRenderTarget(renderTargetWater);

            graphics.BlendState       = BlendState.Opaque;
            graphics.SamplerStates[0] = SamplerState.LinearWrap;
            Quad.UseBasicEffect(renderTarget);
            Quad.Render();

            //draw alpha blended particles that are inside a sub
            spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied, null, DepthStencilState.DepthRead, null, null, cam.Transform);
            GameMain.ParticleManager.Draw(spriteBatch, true, true, Particles.ParticleBlendState.AlphaBlend);
            spriteBatch.End();

            graphics.SetRenderTarget(renderTarget);

            //draw alpha blended particles that are not in water
            spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied, null, DepthStencilState.DepthRead, null, null, cam.Transform);
            GameMain.ParticleManager.Draw(spriteBatch, false, null, Particles.ParticleBlendState.AlphaBlend);
            spriteBatch.End();

            //draw additive particles that are not in water
            spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.Additive, null, DepthStencilState.None, null, null, cam.Transform);
            GameMain.ParticleManager.Draw(spriteBatch, false, null, Particles.ParticleBlendState.Additive);
            spriteBatch.End();

            graphics.DepthStencilState = DepthStencilState.DepthRead;
            graphics.SetRenderTarget(renderTargetFinal);

            WaterRenderer.Instance.ResetBuffers();
            Hull.UpdateVertices(cam, WaterRenderer.Instance);
            WaterRenderer.Instance.RenderWater(spriteBatch, renderTargetWater, cam);
            WaterRenderer.Instance.RenderAir(graphics, cam, renderTarget, Cam.ShaderTransform);
            graphics.DepthStencilState = DepthStencilState.None;

            spriteBatch.Begin(SpriteSortMode.Immediate,
                              BlendState.NonPremultiplied, SamplerState.LinearWrap,
                              null, null,
                              damageEffect,
                              cam.Transform);
            Submarine.DrawDamageable(spriteBatch, damageEffect, false);
            spriteBatch.End();

            spriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.NonPremultiplied, null, DepthStencilState.None, null, null, cam.Transform);
            Submarine.DrawFront(spriteBatch, false, null);
            spriteBatch.End();

            //draw additive particles that are inside a sub
            spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.Additive, null, DepthStencilState.Default, null, null, cam.Transform);
            GameMain.ParticleManager.Draw(spriteBatch, true, true, Particles.ParticleBlendState.Additive);
            foreach (var discharger in Items.Components.ElectricalDischarger.List)
            {
                discharger.DrawElectricity(spriteBatch);
            }
            spriteBatch.End();
            if (GameMain.LightManager.LightingEnabled)
            {
                graphics.DepthStencilState = DepthStencilState.None;
                graphics.SamplerStates[0]  = SamplerState.LinearWrap;
                graphics.BlendState        = Lights.CustomBlendStates.Multiplicative;
                Quad.UseBasicEffect(GameMain.LightManager.LightMap);
                Quad.Render();
            }

            spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied, SamplerState.LinearWrap, DepthStencilState.None, null, null, cam.Transform);
            foreach (Character c in Character.CharacterList)
            {
                c.DrawFront(spriteBatch, cam);
            }
            if (Level.Loaded != null)
            {
                Level.Loaded.DrawFront(spriteBatch, cam);
            }
            if (GameMain.DebugDraw)
            {
                MapEntity.mapEntityList.ForEach(me => me.AiTarget?.Draw(spriteBatch));
                Character.CharacterList.ForEach(c => c.AiTarget?.Draw(spriteBatch));
                if (GameMain.GameSession?.EventManager != null)
                {
                    GameMain.GameSession.EventManager.DebugDraw(spriteBatch);
                }
            }
            spriteBatch.End();

            if (GameMain.LightManager.LosEnabled && GameMain.LightManager.LosMode != LosMode.None && Character.Controlled != null)
            {
                GameMain.LightManager.LosEffect.CurrentTechnique = GameMain.LightManager.LosEffect.Techniques["LosShader"];

                GameMain.LightManager.LosEffect.Parameters["xTexture"].SetValue(renderTargetBackground);
                GameMain.LightManager.LosEffect.Parameters["xLosTexture"].SetValue(GameMain.LightManager.LosTexture);

                Color losColor;
                if (GameMain.LightManager.LosMode == LosMode.Transparent)
                {
                    //convert the los color to HLS and make sure the luminance of the color is always the same
                    //as the luminance of the ambient light color
                    float r = Character.Controlled?.CharacterHealth == null ?
                              0.0f : Math.Min(Character.Controlled.CharacterHealth.DamageOverlayTimer * 0.5f, 0.5f);
                    Vector3 ambientLightHls = GameMain.LightManager.AmbientLight.RgbToHLS();
                    Vector3 losColorHls     = Color.Lerp(GameMain.LightManager.AmbientLight, Color.Red, r).RgbToHLS();
                    losColorHls.Y = ambientLightHls.Y;
                    losColor      = ToolBox.HLSToRGB(losColorHls);
                }
                else
                {
                    losColor = Color.Black;
                }

                GameMain.LightManager.LosEffect.Parameters["xColor"].SetValue(losColor.ToVector4());

                graphics.BlendState       = BlendState.NonPremultiplied;
                graphics.SamplerStates[0] = SamplerState.PointClamp;
                GameMain.LightManager.LosEffect.CurrentTechnique.Passes[0].Apply();
                Quad.Render();
            }
            graphics.SetRenderTarget(null);

            float   BlurStrength                = 0.0f;
            float   DistortStrength             = 0.0f;
            Vector3 chromaticAberrationStrength = GameMain.Config.ChromaticAberrationEnabled ?
                                                  new Vector3(-0.02f, -0.01f, 0.0f) : Vector3.Zero;

            if (Character.Controlled != null)
            {
                BlurStrength                 = Character.Controlled.BlurStrength * 0.005f;
                DistortStrength              = Character.Controlled.DistortStrength;
                chromaticAberrationStrength -= Vector3.One * Character.Controlled.RadialDistortStrength;
                chromaticAberrationStrength += new Vector3(-0.03f, -0.015f, 0.0f) * Character.Controlled.ChromaticAberrationStrength;
            }
            else
            {
                BlurStrength    = 0.0f;
                DistortStrength = 0.0f;
            }

            string postProcessTechnique = "";
            if (BlurStrength > 0.0f)
            {
                postProcessTechnique += "Blur";
                PostProcessEffect.Parameters["blurDistance"].SetValue(BlurStrength);
            }
            if (chromaticAberrationStrength != Vector3.Zero)
            {
                postProcessTechnique += "ChromaticAberration";
                PostProcessEffect.Parameters["chromaticAberrationStrength"].SetValue(chromaticAberrationStrength);
            }
            if (DistortStrength > 0.0f)
            {
                postProcessTechnique += "Distort";
                PostProcessEffect.Parameters["distortScale"].SetValue(Vector2.One * DistortStrength);
                PostProcessEffect.Parameters["distortUvOffset"].SetValue(WaterRenderer.Instance.WavePos * 0.001f);
            }

            graphics.BlendState        = BlendState.Opaque;
            graphics.SamplerStates[0]  = SamplerState.LinearClamp;
            graphics.DepthStencilState = DepthStencilState.None;
            if (string.IsNullOrEmpty(postProcessTechnique))
            {
                Quad.UseBasicEffect(renderTargetFinal);
            }
            else
            {
                PostProcessEffect.Parameters["MatrixTransform"].SetValue(Matrix.Identity);
                PostProcessEffect.Parameters["xTexture"].SetValue(renderTargetFinal);
                PostProcessEffect.CurrentTechnique = PostProcessEffect.Techniques[postProcessTechnique];
                PostProcessEffect.CurrentTechnique.Passes[0].Apply();
            }
            Quad.Render();

            if (fadeToBlackState > 0.0f)
            {
                spriteBatch.Begin(SpriteSortMode.Deferred);
                GUI.DrawRectangle(spriteBatch, new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight), Color.Lerp(Color.TransparentBlack, Color.Black, fadeToBlackState), isFilled: true);
                spriteBatch.End();
            }
        }
Ejemplo n.º 8
0
        private Vector2 CalculateSteeringSeek(Vector2 target, float weight, Func <PathNode, bool> startNodeFilter = null, Func <PathNode, bool> endNodeFilter = null, Func <PathNode, bool> nodeFilter = null, bool checkVisibility = true)
        {
            Vector2 targetDiff = target - currentTarget;

            if (currentPath != null && currentPath.Nodes.Any())
            {
                //current path calculated relative to a different sub than where the character is now
                //take that into account when calculating if the target has moved
                Submarine currentPathSub = currentPath?.Nodes.First().Submarine;
                if (currentPathSub != character.Submarine && character.Submarine != null)
                {
                    Vector2 subDiff = character.Submarine.SimPosition - currentPathSub.SimPosition;
                    targetDiff += subDiff;
                }
            }
            bool needsNewPath = character.Params.PathFinderPriority > 0.5f && (currentPath == null || currentPath.Unreachable || targetDiff.LengthSquared() > 1);

            //find a new path if one hasn't been found yet or the target is different from the current target
            if (needsNewPath || findPathTimer < -1.0f)
            {
                IsPathDirty = true;
                if (findPathTimer < 0)
                {
                    currentTarget = target;
                    Vector2 currentPos = host.SimPosition;
                    if (character != null && character.Submarine == null)
                    {
                        var targetHull = Hull.FindHull(ConvertUnits.ToDisplayUnits(target), null, false);
                        if (targetHull != null && targetHull.Submarine != null)
                        {
                            currentPos -= targetHull.Submarine.SimPosition;
                        }
                    }
                    pathFinder.InsideSubmarine = character.Submarine != null;
                    var  newPath    = pathFinder.FindPath(currentPos, target, character.Submarine, "(Character: " + character.Name + ")", startNodeFilter, endNodeFilter, nodeFilter, checkVisibility: checkVisibility);
                    bool useNewPath = needsNewPath || currentPath == null || currentPath.CurrentNode == null;
                    if (!useNewPath && currentPath != null && currentPath.CurrentNode != null && newPath.Nodes.Any() && !newPath.Unreachable)
                    {
                        // It's possible that the current path was calculated from a start point that is no longer valid.
                        // Therefore, let's accept also paths with a greater cost than the current, if the current node is much farther than the new start node.
                        useNewPath = newPath.Cost <currentPath.Cost ||
                                                   Vector2.DistanceSquared(character.WorldPosition, currentPath.CurrentNode.WorldPosition)> Math.Pow(Vector2.Distance(character.WorldPosition, newPath.Nodes.First().WorldPosition) * 3, 2);
                    }
                    if (useNewPath)
                    {
                        currentPath = newPath;
                    }
                    float priority = MathHelper.Lerp(3, 1, character.Params.PathFinderPriority);
                    findPathTimer = priority * Rand.Range(1.0f, 1.2f);
                    IsPathDirty   = false;
                    return(DiffToCurrentNode());
                }
            }

            Vector2 diff     = DiffToCurrentNode();
            var     collider = character.AnimController.Collider;
            // Only humanoids can climb ladders
            bool canClimb = character.AnimController is HumanoidAnimController;

            //if not in water and the waypoint is between the top and bottom of the collider, no need to move vertically
            if (canClimb && !character.AnimController.InWater && !character.IsClimbing && diff.Y < collider.height / 2 + collider.radius)
            {
                diff.Y = 0.0f;
            }
            if (diff == Vector2.Zero)
            {
                return(Vector2.Zero);
            }
            return(Vector2.Normalize(diff) * weight);
        }
Ejemplo n.º 9
0
        private void CheckDoorsInPath()
        {
            for (int i = 0; i < 2; i++)
            {
                WayPoint currentWaypoint = null;
                WayPoint nextWaypoint    = null;
                Door     door            = null;
                bool     shouldBeOpen    = false;

                if (currentPath.Nodes.Count == 1)
                {
                    door         = currentPath.Nodes.First().ConnectedDoor;
                    shouldBeOpen = door != null;
                }
                else
                {
                    if (i == 0)
                    {
                        currentWaypoint = currentPath.CurrentNode;
                        nextWaypoint    = currentPath.NextNode;
                    }
                    else
                    {
                        currentWaypoint = currentPath.PrevNode;
                        nextWaypoint    = currentPath.CurrentNode;
                    }
                    if (currentWaypoint?.ConnectedDoor == null)
                    {
                        continue;
                    }

                    if (nextWaypoint == null)
                    {
                        //the node we're heading towards is the last one in the path, and at a door
                        //the door needs to be open for the character to reach the node
                        if (currentWaypoint.ConnectedDoor.LinkedGap != null && currentWaypoint.ConnectedDoor.LinkedGap.IsRoomToRoom)
                        {
                            shouldBeOpen = true;
                            door         = currentWaypoint.ConnectedDoor;
                        }
                    }
                    else
                    {
                        door = currentWaypoint.ConnectedDoor;
                        if (door.LinkedGap.IsHorizontal)
                        {
                            int dir = Math.Sign(nextWaypoint.WorldPosition.X - door.Item.WorldPosition.X);
                            shouldBeOpen = (door.Item.WorldPosition.X - character.WorldPosition.X) * dir > -50.0f;
                        }
                        else
                        {
                            int dir = Math.Sign(nextWaypoint.WorldPosition.Y - door.Item.WorldPosition.Y);
                            shouldBeOpen = (door.Item.WorldPosition.Y - character.WorldPosition.Y) * dir > -80.0f;
                        }
                    }
                }

                if (door == null)
                {
                    return;
                }

                //toggle the door if it's the previous node and open, or if it's current node and closed
                if ((door.IsOpen || door.IsBroken) != shouldBeOpen)
                {
                    Controller closestButton = null;
                    float      closestDist   = 0;
                    bool       canAccess     = CanAccessDoor(door, button =>
                    {
                        if (currentWaypoint == null)
                        {
                            return(true);
                        }
                        // Check that the button is on the right side of the door.
                        if (door.LinkedGap.IsHorizontal)
                        {
                            int dir = Math.Sign((nextWaypoint ?? currentWaypoint).WorldPosition.X - door.Item.WorldPosition.X);
                            if (button.Item.WorldPosition.X * dir > door.Item.WorldPosition.X * dir)
                            {
                                return(false);
                            }
                        }
                        else
                        {
                            int dir = Math.Sign((nextWaypoint ?? currentWaypoint).WorldPosition.Y - door.Item.WorldPosition.Y);
                            if (button.Item.WorldPosition.Y * dir > door.Item.WorldPosition.Y * dir)
                            {
                                return(false);
                            }
                        }
                        float distance = Vector2.DistanceSquared(button.Item.WorldPosition, character.WorldPosition);
                        if (closestButton == null || distance < closestDist)
                        {
                            closestButton = button;
                            closestDist   = distance;
                        }
                        return(true);
                    });
                    if (canAccess)
                    {
                        if (door.HasIntegratedButtons)
                        {
                            door.Item.TryInteract(character, false, true);
                            buttonPressCooldown = ButtonPressInterval;
                            break;
                        }
                        else if (closestButton != null)
                        {
                            if (Vector2.DistanceSquared(closestButton.Item.WorldPosition, character.WorldPosition) < MathUtils.Pow(closestButton.Item.InteractDistance * 2, 2))
                            {
                                closestButton.Item.TryInteract(character, false, true);
                                buttonPressCooldown = ButtonPressInterval;
                                break;
                            }
                            else
                            {
                                // Can't reach the button closest to the character.
                                // It's possible that we could reach another buttons.
                                // If this becomes an issue, we could go through them here and check if any of them are reachable
                                // (would have to cache a collection of buttons instead of a single reference in the CanAccess filter method above)
                                var body = Submarine.PickBody(character.SimPosition, character.GetRelativeSimPosition(closestButton.Item), collisionCategory: Physics.CollisionWall | Physics.CollisionLevel);
                                if (body != null)
                                {
                                    if (body.UserData is Item item)
                                    {
                                        var d = item.GetComponent <Door>();
                                        if (d == null || d.IsOpen)
                                        {
                                            return;
                                        }
                                    }
                                    // The button is on the wrong side of the door or a wall
                                    currentPath.Unreachable = true;
                                }
                                return;
                            }
                        }
                    }
                    else if (shouldBeOpen)
                    {
#if DEBUG
                        DebugConsole.NewMessage($"{character.Name}: Pathfinding error: Cannot access the door", Color.Yellow);
#endif
                        currentPath.Unreachable = true;
                        return;
                    }
                }
            }
        }
Ejemplo n.º 10
0
        public override void OnMapLoaded()
        {
            if (!loadSub)
            {
                return;
            }

            SubmarineInfo info = new SubmarineInfo(Submarine.Info.FilePath, "", saveElement);

            sub = Submarine.Load(info, false);

            Vector2 worldPos = saveElement.GetAttributeVector2("worldpos", Vector2.Zero);

            if (worldPos != Vector2.Zero)
            {
                sub.SetPosition(worldPos);
            }
            else
            {
                sub.SetPosition(WorldPosition);
            }

            DockingPort linkedPort = null;
            DockingPort myPort     = null;

            MapEntity linkedItem = linkedTo.FirstOrDefault(lt => (lt is Item) && ((Item)lt).GetComponent <DockingPort>() != null);

            if (linkedItem == null)
            {
                linkedPort = DockingPort.List.FirstOrDefault(dp => dp.DockingTarget != null && dp.DockingTarget.Item.Submarine == sub);
            }
            else
            {
                linkedPort = ((Item)linkedItem).GetComponent <DockingPort>();
            }

            if (linkedPort == null)
            {
                if (purchasedLostShuttles)
                {
                    linkedPort = (FindEntityByID(originalLinkedToID) as Item)?.GetComponent <DockingPort>();
                }
                if (linkedPort == null)
                {
                    return;
                }
            }
            originalLinkedPort = linkedPort;

            myPort = (FindEntityByID(originalMyPortID) as Item)?.GetComponent <DockingPort>();
            if (myPort == null)
            {
                float closestDistance = 0.0f;
                foreach (DockingPort port in DockingPort.List)
                {
                    if (port.Item.Submarine != sub || port.IsHorizontal != linkedPort.IsHorizontal)
                    {
                        continue;
                    }
                    float dist = Vector2.Distance(port.Item.WorldPosition, linkedPort.Item.WorldPosition);
                    if (myPort == null || dist < closestDistance)
                    {
                        myPort          = port;
                        closestDistance = dist;
                    }
                }
            }

            if (myPort != null)
            {
                originalMyPortID = myPort.Item.ID;

                myPort.Undock();

                //something else is already docked to the port this sub should be docked to
                //may happen if a shuttle is lost, another vehicle docked to where the shuttle used to be,
                //and the shuttle is then restored in the campaign mode
                //or if the user connects multiple subs to the same docking ports in the sub editor
                if (linkedPort.Docked && linkedPort.DockingTarget != null && linkedPort.DockingTarget != myPort)
                {
                    //just spawn below the main sub
                    sub.SetPosition(
                        linkedPort.Item.Submarine.WorldPosition -
                        new Vector2(0, linkedPort.Item.Submarine.GetDockedBorders().Height / 2 + sub.GetDockedBorders().Height / 2));
                }
                else
                {
                    Vector2 portDiff = myPort.Item.WorldPosition - sub.WorldPosition;
                    Vector2 offset   = (myPort.IsHorizontal ?
                                        Vector2.UnitX * Math.Sign(linkedPort.Item.WorldPosition.X - myPort.Item.WorldPosition.X) :
                                        Vector2.UnitY * Math.Sign(linkedPort.Item.WorldPosition.Y - myPort.Item.WorldPosition.Y));
                    offset *= myPort.DockedDistance;

                    sub.SetPosition((linkedPort.Item.WorldPosition - portDiff) - offset);

                    myPort.Dock(linkedPort);
                    myPort.Lock(true);
                }
            }

            if (GameMain.GameSession?.GameMode is CampaignMode campaign && campaign.PurchasedLostShuttles)
            {
                foreach (Structure wall in Structure.WallList)
                {
                    if (wall.Submarine != sub)
                    {
                        continue;
                    }
                    for (int i = 0; i < wall.SectionCount; i++)
                    {
                        wall.AddDamage(i, -wall.MaxHealth);
                    }
                }
                foreach (Hull hull in Hull.hullList)
                {
                    if (hull.Submarine != sub)
                    {
                        continue;
                    }
                    hull.WaterVolume      = 0.0f;
                    hull.OxygenPercentage = 100.0f;
                }
            }

            sub.SetPosition(sub.WorldPosition - Submarine.WorldPosition);
            sub.Submarine = Submarine;
        }
Ejemplo n.º 11
0
        public override void Update(float deltaTime)
        {
            if (disallowed)
            {
                Finished();
                return;
            }

            if (repeat)
            {
                //clients aren't allowed to spawn more monsters mid-round
                if (GameMain.Client != null)
                {
                    return;
                }

                for (int i = 0; i < monsters.Length; i++)
                {
                    if (monsters[i] == null || monsters[i].Removed || monsters[i].IsDead)
                    {
                        monsters[i] = SpawnMonsters(1, true)[0];
                    }
                }
            }

            if (isFinished)
            {
                return;
            }

            isActive = false;

            Entity targetEntity = null;

            if (Character.Controlled != null)
            {
                targetEntity = Character.Controlled;
            }
            else
            {
                targetEntity = Submarine.FindClosest(GameMain.GameScreen.Cam.WorldViewCenter);
            }

            bool monstersDead = true;

            foreach (Character monster in monsters)
            {
                if (!monster.IsDead)
                {
                    monstersDead = false;

                    if (targetEntity != null && Vector2.DistanceSquared(monster.WorldPosition, targetEntity.WorldPosition) < 5000.0f * 5000.0f)
                    {
                        isActive = true;
                        break;
                    }
                }
            }

            if (monstersDead && !repeat)
            {
                Finished();
            }
        }
Ejemplo n.º 12
0
 public GoToMission(MissionPrefab prefab, Location[] locations, Submarine sub)
     : base(prefab, locations, sub)
 {
 }
        public override void Update(float deltaTime)
        {
            if (disallowed)
            {
                Finished();
                return;
            }

            if (isFinished)
            {
                return;
            }

            if (spawnPos == null)
            {
                FindSpawnPosition(affectSubImmediately: true);
                //the event gets marked as finished if a spawn point is not found
                if (isFinished)
                {
                    return;
                }
                spawnPending = true;
            }

            bool spawnReady = false;

            if (spawnPending)
            {
                //wait until there are no submarines at the spawnpos
                if (spawnPosType == Level.PositionType.MainPath)
                {
                    foreach (Submarine submarine in Submarine.Loaded)
                    {
                        if (submarine.Info.Type != SubmarineType.Player)
                        {
                            continue;
                        }
                        float minDist = GetMinDistanceToSub(submarine);
                        if (Vector2.DistanceSquared(submarine.WorldPosition, spawnPos.Value) < minDist * minDist)
                        {
                            return;
                        }
                    }
                }

                //if spawning in a ruin/cave, wait for someone to be close to it to spawning
                //unnecessary monsters in places the players might never visit during the round
                if (spawnPosType == Level.PositionType.Ruin || spawnPosType == Level.PositionType.Cave || spawnPosType == Level.PositionType.Wreck)
                {
                    bool  someoneNearby = false;
                    float minDist       = Sonar.DefaultSonarRange * 0.8f;
                    foreach (Submarine submarine in Submarine.Loaded)
                    {
                        if (submarine.Info.Type != SubmarineType.Player)
                        {
                            continue;
                        }
                        if (Vector2.DistanceSquared(submarine.WorldPosition, spawnPos.Value) < minDist * minDist)
                        {
                            someoneNearby = true;
                            break;
                        }
                    }
                    foreach (Character c in Character.CharacterList)
                    {
                        if (c == Character.Controlled || c.IsRemotePlayer)
                        {
                            if (Vector2.DistanceSquared(c.WorldPosition, spawnPos.Value) < minDist * minDist)
                            {
                                someoneNearby = true;
                                break;
                            }
                        }
                    }
                    if (!someoneNearby)
                    {
                        return;
                    }
                }

                spawnPending = false;

                //+1 because Range returns an integer less than the max value
                int amount = Rand.Range(minAmount, maxAmount + 1);
                monsters = new List <Character>();
                float offsetAmount = spawnPosType == Level.PositionType.MainPath || spawnPosType == Level.PositionType.SidePath ? scatter : 100;
                for (int i = 0; i < amount; i++)
                {
                    string seed = Level.Loaded.Seed + i.ToString();
                    CoroutineManager.InvokeAfter(() =>
                    {
                        //round ended before the coroutine finished
                        if (GameMain.GameSession == null || Level.Loaded == null)
                        {
                            return;
                        }

                        System.Diagnostics.Debug.Assert(GameMain.NetworkMember == null || GameMain.NetworkMember.IsServer, "Clients should not create monster events.");

                        Vector2 pos = spawnPos.Value + Rand.Vector(offsetAmount);
                        if (spawnPosType == Level.PositionType.MainPath || spawnPosType == Level.PositionType.SidePath)
                        {
                            if (Submarine.Loaded.Any(s => ToolBox.GetWorldBounds(s.Borders.Center, s.Borders.Size).ContainsWorld(pos)))
                            {
                                // Can't use the offset position, let's use the exact spawn position.
                                pos = spawnPos.Value;
                            }
                            else if (Level.Loaded.Ruins.Any(r => ToolBox.GetWorldBounds(r.Area.Center, r.Area.Size).ContainsWorld(pos)))
                            {
                                // Can't use the offset position, let's use the exact spawn position.
                                pos = spawnPos.Value;
                            }
                        }

                        monsters.Add(Character.Create(speciesName, pos, seed, characterInfo: null, isRemotePlayer: false, hasAi: true, createNetworkEvent: true));

                        if (monsters.Count == amount)
                        {
                            spawnReady = true;
                            //this will do nothing if the monsters have no swarm behavior defined,
                            //otherwise it'll make the spawned characters act as a swarm
                            SwarmBehavior.CreateSwarm(monsters.Cast <AICharacter>());
                        }
                    }, Rand.Range(0f, amount / 2));
                }
            }

            if (!spawnReady)
            {
                return;
            }

            Entity targetEntity = Submarine.FindClosest(GameMain.GameScreen.Cam.WorldViewCenter);

#if CLIENT
            if (Character.Controlled != null)
            {
                targetEntity = Character.Controlled;
            }
#endif

            bool monstersDead = true;
            foreach (Character monster in monsters)
            {
                if (!monster.IsDead)
                {
                    monstersDead = false;

                    if (targetEntity != null && Vector2.DistanceSquared(monster.WorldPosition, targetEntity.WorldPosition) < 5000.0f * 5000.0f)
                    {
                        break;
                    }
                }
            }

            if (monstersDead)
            {
                Finished();
            }
        }
 private float GetMinDistanceToSub(Submarine submarine)
 {
     return(Math.Max(Math.Max(submarine.Borders.Width, submarine.Borders.Height), Sonar.DefaultSonarRange * 0.9f));
 }
Ejemplo n.º 15
0
        public void DrawMap(GraphicsDevice graphics, SpriteBatch spriteBatch)
        {
            foreach (Submarine sub in Submarine.Loaded)
            {
                sub.UpdateTransform();
            }

            GameMain.ParticleManager.UpdateTransforms();

            GameMain.LightManager.ObstructVision = Character.Controlled != null && Character.Controlled.ObstructVision;

            GameMain.LightManager.UpdateLightMap(graphics, spriteBatch, cam, lightBlur.Effect);
            if (Character.Controlled != null)
            {
                GameMain.LightManager.UpdateObstructVision(graphics, spriteBatch, cam, Character.Controlled.CursorWorldPosition);
            }

            //----------------------------------------------------------------------------------------
            //1. draw the background, characters and the parts of the submarine that are behind them
            //----------------------------------------------------------------------------------------

            graphics.SetRenderTarget(renderTargetBackground);

            if (Level.Loaded == null)
            {
                graphics.Clear(new Color(11, 18, 26, 255));
            }
            else
            {
                Level.Loaded.DrawBack(graphics, spriteBatch, cam, BackgroundCreatureManager);
            }

            spriteBatch.Begin(SpriteSortMode.BackToFront,
                              BlendState.AlphaBlend,
                              null, null, null, null,
                              cam.Transform);

            Submarine.DrawBack(spriteBatch, false, s => s is Structure);

            spriteBatch.End();

            graphics.SetRenderTarget(renderTarget);

            spriteBatch.Begin(SpriteSortMode.Deferred,
                              BlendState.Opaque);
            spriteBatch.Draw(renderTargetBackground, new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight), Color.White);
            spriteBatch.End();

            spriteBatch.Begin(SpriteSortMode.BackToFront,
                              BlendState.AlphaBlend,
                              null, null, null, null,
                              cam.Transform);

            Submarine.DrawBack(spriteBatch, false, s => !(s is Structure));

            foreach (Character c in Character.CharacterList)
            {
                c.Draw(spriteBatch);
            }

            spriteBatch.End();

            //----------------------------------------------------------------------------------------
            //draw the rendertarget and particles that are only supposed to be drawn in water into renderTargetWater
            graphics.SetRenderTarget(renderTargetWater);

            spriteBatch.Begin(SpriteSortMode.Deferred,
                              BlendState.Opaque);
            spriteBatch.Draw(renderTarget, new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight), waterColor);
            spriteBatch.End();

#if LINUX
            spriteBatch.Begin(SpriteSortMode.Deferred,
                              BlendState.NonPremultiplied,
                              null, DepthStencilState.DepthRead, null, null,
                              cam.Transform);
#else
            spriteBatch.Begin(SpriteSortMode.Deferred,
                              BlendState.AlphaBlend,
                              null, DepthStencilState.DepthRead, null, null,
                              cam.Transform);
#endif
            GameMain.ParticleManager.Draw(spriteBatch, true, Particles.ParticleBlendState.AlphaBlend);
            spriteBatch.End();

            spriteBatch.Begin(SpriteSortMode.Deferred,
                              BlendState.Additive,
                              null, DepthStencilState.Default, null, null,
                              cam.Transform);
            GameMain.ParticleManager.Draw(spriteBatch, true, Particles.ParticleBlendState.Additive);
            spriteBatch.End();

            //----------------------------------------------------------------------------------------
            //draw the rendertarget and particles that are only supposed to be drawn in air into renderTargetAir

            graphics.SetRenderTarget(renderTargetAir);
            spriteBatch.Begin(SpriteSortMode.Deferred,
                              BlendState.Opaque);
            spriteBatch.Draw(renderTarget, new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight), Color.White);
            spriteBatch.End();
#if LINUX
            spriteBatch.Begin(SpriteSortMode.Deferred,
                              BlendState.NonPremultiplied,
                              null, DepthStencilState.DepthRead, null, null,
                              cam.Transform);
#else
            spriteBatch.Begin(SpriteSortMode.Deferred,
                              BlendState.AlphaBlend,
                              null, DepthStencilState.DepthRead, null, null,
                              cam.Transform);
#endif

            GameMain.ParticleManager.Draw(spriteBatch, false, Particles.ParticleBlendState.AlphaBlend);
            spriteBatch.End();

            spriteBatch.Begin(SpriteSortMode.Deferred,
                              BlendState.Additive,
                              null, DepthStencilState.DepthRead, null, null,
                              cam.Transform);
            GameMain.ParticleManager.Draw(spriteBatch, false, Particles.ParticleBlendState.Additive);
            spriteBatch.End();

            if (Character.Controlled != null && GameMain.LightManager.LosEnabled)
            {
                graphics.SetRenderTarget(renderTarget);
                spriteBatch.Begin(SpriteSortMode.Deferred,
                                  BlendState.Opaque, null, null, null, lightBlur.Effect);

                spriteBatch.Draw(renderTargetBackground, new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight), Color.White);

                spriteBatch.End();

                spriteBatch.Begin(SpriteSortMode.BackToFront,
                                  BlendState.AlphaBlend, SamplerState.LinearWrap,
                                  null, null, null,
                                  cam.Transform);

                Submarine.DrawDamageable(spriteBatch, null, false);
                Submarine.DrawFront(spriteBatch, false, s => s is Structure);

                spriteBatch.End();

                GameMain.LightManager.DrawLOS(spriteBatch, lightBlur.Effect, true);
            }

            graphics.SetRenderTarget(null);

            //----------------------------------------------------------------------------------------
            //2. pass the renderTarget to the water shader to do the water effect
            //----------------------------------------------------------------------------------------

            Hull.renderer.RenderBack(spriteBatch, renderTargetWater);

            Array.Clear(Hull.renderer.vertices, 0, Hull.renderer.vertices.Length);
            Hull.renderer.PositionInBuffer = 0;
            foreach (Hull hull in Hull.hullList)
            {
                hull.Render(graphics, cam);
            }

            Hull.renderer.Render(graphics, cam, renderTargetAir, Cam.ShaderTransform);

            //----------------------------------------------------------------------------------------
            //3. draw the sections of the map that are on top of the water
            //----------------------------------------------------------------------------------------

            spriteBatch.Begin(SpriteSortMode.BackToFront,
                              BlendState.AlphaBlend, SamplerState.LinearWrap,
                              null, null, null,
                              cam.Transform);

            Submarine.DrawFront(spriteBatch, false, null);

            spriteBatch.End();

            spriteBatch.Begin(SpriteSortMode.Immediate,
                              BlendState.NonPremultiplied, SamplerState.LinearWrap,
                              null, null,
                              damageEffect,
                              cam.Transform);

            Submarine.DrawDamageable(spriteBatch, damageEffect, false);

            spriteBatch.End();

            GameMain.LightManager.DrawLightMap(spriteBatch, lightBlur.Effect);

            spriteBatch.Begin(SpriteSortMode.BackToFront,
                              BlendState.AlphaBlend, SamplerState.LinearWrap,
                              null, null, null,
                              cam.Transform);

            if (Level.Loaded != null)
            {
                Level.Loaded.DrawFront(spriteBatch);
            }

            foreach (Character c in Character.CharacterList)
            {
                c.DrawFront(spriteBatch, cam);
            }

            spriteBatch.End();

            if (Character.Controlled != null && GameMain.LightManager.LosEnabled)
            {
                GameMain.LightManager.DrawLOS(spriteBatch, lightBlur.Effect, false);

                spriteBatch.Begin(SpriteSortMode.Immediate,
                                  BlendState.AlphaBlend, SamplerState.LinearWrap, DepthStencilState.None, RasterizerState.CullNone, null);

                float r = Math.Min(CharacterHUD.damageOverlayTimer * 0.5f, 0.5f);
                spriteBatch.Draw(renderTarget, new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight),
                                 Color.Lerp(GameMain.LightManager.AmbientLight * 0.5f, Color.Red, r));

                spriteBatch.End();
            }
        }
Ejemplo n.º 16
0
 private static IEnumerable <T> GetThalamusEntities <T>(Submarine wreck, string tag) where T : MapEntity => GetThalamusEntities(wreck, tag).Where(e => e is T).Select(e => e as T);
Ejemplo n.º 17
0
        public override void UpdatePlacing(Camera cam)
        {
            Vector2 position = Submarine.MouseToWorldGrid(cam, Submarine.MainSub);

            if (PlayerInput.RightButtonClicked())
            {
                selected = null;
                return;
            }

            if (!ResizeHorizontal && !ResizeVertical)
            {
                if (PlayerInput.LeftButtonClicked())
                {
                    var item = new Item(new Rectangle((int)position.X, (int)position.Y, (int)(sprite.size.X * Scale), (int)(sprite.size.Y * Scale)), this, Submarine.MainSub)
                    {
                        Submarine = Submarine.MainSub
                    };
                    item.SetTransform(ConvertUnits.ToSimUnits(Submarine.MainSub == null ? item.Position : item.Position - Submarine.MainSub.Position), 0.0f);
                    item.FindHull();

                    placePosition = Vector2.Zero;
                    return;
                }
            }
            else
            {
                Vector2 placeSize = size;

                if (placePosition == Vector2.Zero)
                {
                    if (PlayerInput.LeftButtonHeld())
                    {
                        placePosition = position;
                    }
                }
                else
                {
                    if (ResizeHorizontal)
                    {
                        placeSize.X = Math.Max(position.X - placePosition.X, size.X);
                    }
                    if (ResizeVertical)
                    {
                        placeSize.Y = Math.Max(placePosition.Y - position.Y, size.Y);
                    }

                    if (PlayerInput.LeftButtonReleased())
                    {
                        var item = new Item(new Rectangle((int)placePosition.X, (int)placePosition.Y, (int)placeSize.X, (int)placeSize.Y), this, Submarine.MainSub);
                        placePosition = Vector2.Zero;

                        item.Submarine = Submarine.MainSub;
                        item.SetTransform(ConvertUnits.ToSimUnits(Submarine.MainSub == null ? item.Position : item.Position - Submarine.MainSub.Position), 0.0f);
                        item.FindHull();

                        //selected = null;
                        return;
                    }

                    position = placePosition;
                }
            }

            //if (PlayerInput.GetMouseState.RightButton == ButtonState.Pressed) selected = null;
        }
Ejemplo n.º 18
0
 private static IEnumerable <MapEntity> GetThalamusEntities(Submarine wreck, string tag) => MapEntity.mapEntityList.Where(e => e.Submarine == wreck && e.prefab != null && IsThalamus(e.prefab, tag));
Ejemplo n.º 19
0
        public override void Draw(double deltaTime, GraphicsDevice graphics, SpriteBatch spriteBatch)
        {
            cam.UpdateTransform(true);
            Submarine.CullEntities(cam);

            foreach (Character c in Character.CharacterList)
            {
                c.AnimController.Limbs.ForEach(l => l.body.UpdateDrawPosition());
                bool wasVisible = c.IsVisible;
                c.DoVisibilityCheck(cam);
                if (c.IsVisible != wasVisible)
                {
                    c.AnimController.Limbs.ForEach(l =>
                    {
                        if (l.LightSource != null)
                        {
                            l.LightSource.Enabled = c.IsVisible;
                        }
                    });
                }
            }

            Stopwatch sw = new Stopwatch();

            sw.Start();

            DrawMap(graphics, spriteBatch, deltaTime);

            sw.Stop();
            GameMain.PerformanceCounter.AddElapsedTicks("DrawMap", sw.ElapsedTicks);
            sw.Restart();

            spriteBatch.Begin(SpriteSortMode.Deferred, null, GUI.SamplerState, null, GameMain.ScissorTestEnable);

            if (Character.Controlled != null && cam != null)
            {
                Character.Controlled.DrawHUD(spriteBatch, cam);
            }

            if (GameMain.GameSession != null)
            {
                GameMain.GameSession.Draw(spriteBatch);
            }

            if (Character.Controlled == null && !GUI.DisableHUD)
            {
                for (int i = 0; i < Submarine.MainSubs.Length; i++)
                {
                    if (Submarine.MainSubs[i] == null)
                    {
                        continue;
                    }
                    if (Level.Loaded != null && Submarine.MainSubs[i].WorldPosition.Y < Level.MaxEntityDepth)
                    {
                        continue;
                    }

                    Vector2 position = Submarine.MainSubs[i].SubBody != null ? Submarine.MainSubs[i].WorldPosition : Submarine.MainSubs[i].HiddenSubPosition;

                    Color indicatorColor = i == 0 ? Color.LightBlue * 0.5f : GUI.Style.Red * 0.5f;
                    GUI.DrawIndicator(
                        spriteBatch, position, cam,
                        Math.Max(Submarine.MainSub.Borders.Width, Submarine.MainSub.Borders.Height),
                        GUI.SubmarineIcon, indicatorColor);
                }
            }

            GUI.Draw(cam, spriteBatch);

            spriteBatch.End();

            sw.Stop();
            GameMain.PerformanceCounter.AddElapsedTicks("DrawHUD", sw.ElapsedTicks);
            sw.Restart();
        }
Ejemplo n.º 20
0
        public WreckAI(Submarine wreck)
        {
            Wreck  = wreck;
            Config = WreckAIConfig.GetRandom();
            if (Config == null)
            {
                DebugConsole.ThrowError("WreckAI: No wreck AI config found!");
                return;
            }
            var thalamusPrefabs = ItemPrefab.Prefabs.Where(p => IsThalamus(p));
            var brainPrefab     = thalamusPrefabs.GetRandom(i => i.Tags.Contains(Config.Brain), Rand.RandSync.Server);

            if (brainPrefab == null)
            {
                DebugConsole.ThrowError($"WreckAI: Could not find any brain prefab with the tag {Config.Brain}! Cannot continue. Failed to create wreck AI.");
                return;
            }
            allItems      = Wreck.GetItems(false);
            thalamusItems = allItems.FindAll(i => IsThalamus(i.prefab));
            var hulls = Wreck.GetHulls(false);

            brain = new Item(brainPrefab, Vector2.Zero, Wreck);
            thalamusItems.Add(brain);
            Vector2 negativeMargin = new Vector2(40, 20);
            Vector2 minSize        = brain.Rect.Size.ToVector2() - negativeMargin;
            Vector2 maxSize        = new Vector2(brain.Rect.Width * 3, brain.Rect.Height * 3);
            // First try to get a room that is not too big and not in the edges of the sub.
            // Also try not to create the brain in a room that already have carrier items inside.
            // Ignore hulls that have any linked hulls to keep the calculations simple.
            // Shrink the horizontal axis so that the brain is not placed in the left or right side, where we often have curved walls.
            // Also ignore hulls that have open gaps, because we'll want the room to be full of water. The room will be filled with water when the brain is inserted in the room.
            Rectangle shrinkedBounds = ToolBox.GetWorldBounds(Wreck.WorldPosition.ToPoint(), new Point(Wreck.Borders.Width - 500, Wreck.Borders.Height));

            bool BaseCondition(Hull h) => h.RectWidth > minSize.X && h.RectHeight > minSize.Y && h.GetLinkedEntities <Hull>().None() && h.ConnectedGaps.None(g => g.Open > 0);
            bool IsNotTooBig(Hull h) => h.RectWidth < maxSize.X && h.RectHeight < maxSize.Y;
            bool IsNotInFringes(Hull h) => shrinkedBounds.ContainsWorld(h.WorldRect);
            bool DoesNotContainOtherItems(Hull h) => thalamusItems.None(i => i.CurrentHull == h);

            Hull brainHull = hulls.GetRandom(h => BaseCondition(h) && IsNotTooBig(h) && IsNotInFringes(h) && DoesNotContainOtherItems(h), Rand.RandSync.Server);

            if (brainHull == null)
            {
                brainHull = hulls.GetRandom(h => BaseCondition(h) && IsNotInFringes(h) && DoesNotContainOtherItems(h), Rand.RandSync.Server);
            }
            if (brainHull == null)
            {
                brainHull = hulls.GetRandom(h => BaseCondition(h) && (IsNotInFringes(h) || DoesNotContainOtherItems(h)), Rand.RandSync.Server);
            }
            if (brainHull == null)
            {
                brainHull = hulls.GetRandom(BaseCondition, Rand.RandSync.Server);
            }
            var thalamusStructurePrefabs = StructurePrefab.Prefabs.Where(p => IsThalamus(p));

            if (brainHull == null)
            {
                return;
            }
            brainHull.WaterVolume = brainHull.Volume;
            brain.SetTransform(brainHull.SimPosition, rotation: 0, findNewHull: false);
            brain.CurrentHull = brainHull;
            var backgroundPrefab = thalamusStructurePrefabs.GetRandom(i => i.Tags.Contains(Config.BrainRoomBackground), Rand.RandSync.Server);

            if (backgroundPrefab != null)
            {
                new Structure(brainHull.Rect, backgroundPrefab, Wreck);
            }
            var horizontalWallPrefab = thalamusStructurePrefabs.GetRandom(p => p.Tags.Contains(Config.BrainRoomHorizontalWall), Rand.RandSync.Server);

            if (horizontalWallPrefab != null)
            {
                int height        = (int)horizontalWallPrefab.Size.Y;
                int halfHeight    = height / 2;
                int quarterHeight = halfHeight / 2;
                new Structure(new Rectangle(brainHull.Rect.Left, brainHull.Rect.Top + quarterHeight, brainHull.Rect.Width, height), horizontalWallPrefab, Wreck);
                new Structure(new Rectangle(brainHull.Rect.Left, brainHull.Rect.Top - brainHull.Rect.Height + halfHeight + quarterHeight, brainHull.Rect.Width, height), horizontalWallPrefab, Wreck);
            }
            var verticalWallPrefab = thalamusStructurePrefabs.GetRandom(p => p.Tags.Contains(Config.BrainRoomVerticalWall), Rand.RandSync.Server);

            if (verticalWallPrefab != null)
            {
                int width        = (int)verticalWallPrefab.Size.X;
                int halfWidth    = width / 2;
                int quarterWidth = halfWidth / 2;
                new Structure(new Rectangle(brainHull.Rect.Left - quarterWidth, brainHull.Rect.Top, width, brainHull.Rect.Height), verticalWallPrefab, Wreck);
                new Structure(new Rectangle(brainHull.Rect.Right - halfWidth - quarterWidth, brainHull.Rect.Top, width, brainHull.Rect.Height), verticalWallPrefab, Wreck);
            }
            foreach (Item item in allItems)
            {
                if (thalamusItems.Contains(item))
                {
                    // Ensure that thalamus items are visible
                    item.HiddenInGame = false;
                }
                else
                {
                    // Load regular turrets
                    var turret = item.GetComponent <Turret>();
                    if (turret != null)
                    {
                        foreach (var linkedItem in item.GetLinkedEntities <Item>())
                        {
                            var container = linkedItem.GetComponent <ItemContainer>();
                            if (container == null)
                            {
                                continue;
                            }
                            for (int i = 0; i < container.Inventory.Capacity; i++)
                            {
                                if (container.Inventory.Items[i] != null)
                                {
                                    continue;
                                }
                                if (MapEntityPrefab.List.GetRandom(e => e is ItemPrefab i && container.CanBeContained(i) &&
                                                                   Config.ForbiddenAmmunition.None(id => id.Equals(i.Identifier, StringComparison.OrdinalIgnoreCase)), Rand.RandSync.Server) is ItemPrefab ammoPrefab)
                                {
                                    Item ammo = new Item(ammoPrefab, container.Item.WorldPosition, Wreck);
                                    if (!container.Inventory.TryPutItem(ammo, i, allowSwapping: false, allowCombine: false, user: null, createNetworkEvent: false))
                                    {
                                        item.Remove();
                                    }
                                }
                            }
                        }
                    }
                }
            }
            foreach (var item in allItems)
            {
                var turret = item.GetComponent <Turret>();
                if (turret != null)
                {
                    turrets.Add(turret);
                }
                if (item.HasTag(Config.Spawner))
                {
                    if (!spawnOrgans.Contains(item))
                    {
                        spawnOrgans.Add(item);
                    }
                }
            }
            wayPoints.AddRange(Wreck.GetWaypoints(false));
            hulls.AddRange(Wreck.GetHulls(false));
            IsAlive            = true;
            thalamusStructures = GetThalamusEntities <Structure>(Wreck, Config.Entity).ToList();
        }
Ejemplo n.º 21
0
        public override void End(string endMessage = "")
        {
            isRunning = false;

            bool success = CrewManager.GetCharacters().Any(c => !c.IsDead);

            crewDead = false;

            if (success)
            {
                if (subsToLeaveBehind == null || leavingSub == null)
                {
                    DebugConsole.ThrowError("Leaving submarine not selected -> selecting the closest one");

                    leavingSub = GetLeavingSub();

                    subsToLeaveBehind = GetSubsToLeaveBehind(leavingSub);
                }
            }

            GameMain.GameSession.EndRound("");

            if (success)
            {
                if (leavingSub != Submarine.MainSub && !leavingSub.DockedTo.Contains(Submarine.MainSub))
                {
                    Submarine.MainSub = leavingSub;

                    GameMain.GameSession.Submarine = leavingSub;

                    foreach (Submarine sub in subsToLeaveBehind)
                    {
                        MapEntity.mapEntityList.RemoveAll(e => e.Submarine == sub && e is LinkedSubmarine);
                        LinkedSubmarine.CreateDummy(leavingSub, sub);
                    }
                }

                if (atEndPosition)
                {
                    Map.MoveToNextLocation();
                }
                else
                {
                    Map.SelectLocation(-1);
                }
                Map.ProgressWorld();

                //save and remove all items that are in someone's inventory
                foreach (Character c in Character.CharacterList)
                {
                    if (c.Info == null || c.Inventory == null)
                    {
                        continue;
                    }
                    var inventoryElement = new XElement("inventory");
                    c.SaveInventory(c.Inventory, inventoryElement);
                    c.Info.InventoryData = inventoryElement;
                    c.Inventory?.DeleteAllItems();
                }
                SaveUtil.SaveGame(GameMain.GameSession.SavePath);
            }

            if (!success)
            {
                var summaryScreen = GUIMessageBox.VisibleBox;

                if (summaryScreen != null)
                {
                    summaryScreen = summaryScreen.Children.First();
                    var buttonArea = summaryScreen.Children.First().FindChild("buttonarea");
                    buttonArea.ClearChildren();


                    summaryScreen.RemoveChild(summaryScreen.Children.FirstOrDefault(c => c is GUIButton));

                    var okButton = new GUIButton(new RectTransform(new Vector2(0.2f, 1.0f), buttonArea.RectTransform),
                                                 TextManager.Get("LoadGameButton"))
                    {
                        OnClicked = (GUIButton button, object obj) =>
                        {
                            GameMain.GameSession.LoadPrevious();
                            GameMain.LobbyScreen.Select();
                            GUIMessageBox.MessageBoxes.Remove(GUIMessageBox.VisibleBox);
                            return(true);
                        }
                    };

                    var quitButton = new GUIButton(new RectTransform(new Vector2(0.2f, 1.0f), buttonArea.RectTransform),
                                                   TextManager.Get("QuitButton"));
                    quitButton.OnClicked += GameMain.LobbyScreen.QuitToMainMenu;
                    quitButton.OnClicked += (GUIButton button, object obj) => { GUIMessageBox.MessageBoxes.Remove(GUIMessageBox.VisibleBox); return(true); };
                    quitButton.OnClicked += (GUIButton button, object obj) => { if (ContextualTutorial.Initialized)
                                                                                {
                                                                                    ContextualTutorial.Stop();
                                                                                }
                                                                                return(true); };
                }
            }

            CrewManager.EndRound();
            for (int i = Character.CharacterList.Count - 1; i >= 0; i--)
            {
                Character.CharacterList[i].Remove();
            }

            Submarine.Unload();

            GameMain.LobbyScreen.Select();
        }
Ejemplo n.º 22
0
        private static string GetCurrentMusicType()
        {
            if (OverrideMusicType != null)
            {
                return(OverrideMusicType);
            }

            if (Screen.Selected != GameMain.GameScreen)
            {
                return("menu");
            }

            if (Character.Controlled != null &&
                Level.Loaded != null && Level.Loaded.Ruins != null &&
                Level.Loaded.Ruins.Any(r => r.Area.Contains(Character.Controlled.WorldPosition)))
            {
                return("ruins");
            }

            Submarine targetSubmarine = Character.Controlled?.Submarine;

            if ((targetSubmarine != null && targetSubmarine.AtDamageDepth) ||
                (Screen.Selected == GameMain.GameScreen && GameMain.GameScreen.Cam.Position.Y < SubmarineBody.DamageDepth))
            {
                return("deep");
            }

            if (targetSubmarine != null)
            {
                float floodedArea = 0.0f;
                float totalArea   = 0.0f;
                foreach (Hull hull in Hull.hullList)
                {
                    if (hull.Submarine != targetSubmarine)
                    {
                        continue;
                    }
                    floodedArea += hull.WaterVolume;
                    totalArea   += hull.Volume;
                }

                if (totalArea > 0.0f && floodedArea / totalArea > 0.25f)
                {
                    return("flooded");
                }
            }

            float enemyDistThreshold = 5000.0f;

            if (targetSubmarine != null)
            {
                enemyDistThreshold = Math.Max(enemyDistThreshold, Math.Max(targetSubmarine.Borders.Width, targetSubmarine.Borders.Height) * 2.0f);
            }

            foreach (Character character in Character.CharacterList)
            {
                if (character.IsDead || !character.Enabled)
                {
                    continue;
                }
                if (!(character.AIController is EnemyAIController enemyAI) || (!enemyAI.AttackHumans && !enemyAI.AttackRooms))
                {
                    continue;
                }

                if (targetSubmarine != null)
                {
                    if (Vector2.DistanceSquared(character.WorldPosition, targetSubmarine.WorldPosition) < enemyDistThreshold * enemyDistThreshold)
                    {
                        return("monster");
                    }
                }
                else if (Character.Controlled != null)
                {
                    if (Vector2.DistanceSquared(character.WorldPosition, Character.Controlled.WorldPosition) < enemyDistThreshold * enemyDistThreshold)
                    {
                        return("monster");
                    }
                }
            }

            if (GameMain.GameSession != null)
            {
                if (Submarine.Loaded != null && Level.Loaded != null && Submarine.MainSub.AtEndPosition)
                {
                    return("levelend");
                }
                if (Timing.TotalTime < GameMain.GameSession.RoundStartTime + 120.0)
                {
                    return("start");
                }
            }

            return("default");
        }
Ejemplo n.º 23
0
        public void StartRound(Level level, bool mirrorLevel = false)
        {
            //make sure no status effects have been carried on from the next round
            //(they should be stopped in EndRound, this is a safeguard against cases where the round is ended ungracefully)
            StatusEffect.StopAll();

#if CLIENT
            GameMain.LightManager.LosEnabled = GameMain.Client == null || GameMain.Client.CharacterInfo != null;
            if (GameMain.Client == null)
            {
                GameMain.LightManager.LosMode = GameMain.Config.LosMode;
            }
#endif
            this.Level = level;

            if (SubmarineInfo == null)
            {
                DebugConsole.ThrowError("Couldn't start game session, submarine not selected.");
                return;
            }

            if (SubmarineInfo.IsFileCorrupted)
            {
                DebugConsole.ThrowError("Couldn't start game session, submarine file corrupted.");
                return;
            }

            Submarine.Unload();
            Submarine         = Submarine.MainSub = new Submarine(SubmarineInfo);
            Submarine.MainSub = Submarine;
            if (GameMode.Mission != null && GameMode.Mission.TeamCount > 1 && Submarine.MainSubs[1] == null)
            {
                Submarine.MainSubs[1] = new Submarine(SubmarineInfo, true);
            }

            if (level != null)
            {
                level.Generate(mirrorLevel);
                if (level.StartOutpost != null)
                {
                    //start by placing the sub below the outpost
                    Rectangle outpostBorders = Level.Loaded.StartOutpost.GetDockedBorders();
                    Rectangle subBorders     = Submarine.GetDockedBorders();

                    Vector2 startOutpostSize = Vector2.Zero;
                    if (Level.Loaded.StartOutpost != null)
                    {
                        startOutpostSize = Level.Loaded.StartOutpost.Borders.Size.ToVector2();
                    }
                    Submarine.SetPosition(
                        Level.Loaded.StartOutpost.WorldPosition -
                        new Vector2(0.0f, outpostBorders.Height / 2 + subBorders.Height / 2));

                    //find the port that's the nearest to the outpost and dock if one is found
                    float       closestDistance = 0.0f;
                    DockingPort myPort = null, outPostPort = null;
                    foreach (DockingPort port in DockingPort.List)
                    {
                        if (port.IsHorizontal || port.Docked)
                        {
                            continue;
                        }
                        if (port.Item.Submarine == level.StartOutpost)
                        {
                            outPostPort = port;
                            continue;
                        }
                        if (port.Item.Submarine != Submarine)
                        {
                            continue;
                        }

                        //the submarine port has to be at the top of the sub
                        if (port.Item.WorldPosition.Y < Submarine.WorldPosition.Y)
                        {
                            continue;
                        }

                        float dist = Vector2.DistanceSquared(port.Item.WorldPosition, level.StartOutpost.WorldPosition);
                        if ((myPort == null || dist < closestDistance || port.MainDockingPort) && !(myPort?.MainDockingPort ?? false))
                        {
                            myPort          = port;
                            closestDistance = dist;
                        }
                    }

                    if (myPort != null && outPostPort != null)
                    {
                        Vector2 portDiff = myPort.Item.WorldPosition - Submarine.WorldPosition;
                        Submarine.SetPosition((outPostPort.Item.WorldPosition - portDiff) - Vector2.UnitY * outPostPort.DockedDistance);
                        myPort.Dock(outPostPort);
                        myPort.Lock(true);
                    }
                }
                else
                {
                    Submarine.SetPosition(Submarine.FindSpawnPos(level.StartPosition));
                }
            }

            foreach (var sub in Submarine.Loaded)
            {
                if (sub.Info.IsOutpost)
                {
                    sub.DisableObstructedWayPoints();
                }
            }

            Entity.Spawner = new EntitySpawner();

            if (GameMode.Mission != null)
            {
                Mission = GameMode.Mission;
            }
            if (GameMode != null)
            {
                GameMode.Start();
            }
            if (GameMode.Mission != null)
            {
                int prevEntityCount = Entity.GetEntityList().Count;
                Mission.Start(Level.Loaded);
                if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient && Entity.GetEntityList().Count != prevEntityCount)
                {
                    DebugConsole.ThrowError(
                        "Entity count has changed after starting a mission as a client. " +
                        "The clients should not instantiate entities themselves when starting the mission," +
                        " but instead the server should inform the client of the spawned entities using Mission.ServerWriteInitial.");
                }
            }

            EventManager?.StartRound(level);
            SteamAchievementManager.OnStartRound();

            if (GameMode != null)
            {
                GameMode.ShowStartMessage();

                if (GameMain.NetworkMember == null)
                {
                    //only place items and corpses here in single player
                    //the server does this after loading the respawn shuttle
                    Level?.SpawnCorpses();
                    AutoItemPlacer.PlaceIfNeeded(GameMode);
                }
                if (GameMode is MultiPlayerCampaign mpCampaign && GameMain.NetworkMember != null && GameMain.NetworkMember.IsServer)
                {
                    mpCampaign.CargoManager.CreateItems();
                }
            }

            GameAnalyticsManager.AddDesignEvent("Submarine:" + Submarine.Info.Name);
            GameAnalyticsManager.AddDesignEvent("Level", ToolBox.StringToInt(level?.Seed ?? "[NO_LEVEL]"));
            GameAnalyticsManager.AddProgressionEvent(GameAnalyticsSDK.Net.EGAProgressionStatus.Start,
                                                     GameMode.Preset.Identifier, (Mission == null ? "None" : Mission.GetType().ToString()));

#if CLIENT
            if (GameMode is SinglePlayerCampaign)
            {
                SteamAchievementManager.OnBiomeDiscovered(level.Biome);
            }
            if (!(GameMode is SubTestMode))
            {
                RoundSummary = new RoundSummary(this);
            }

            GameMain.GameScreen.ColorFade(Color.Black, Color.TransparentBlack, 5.0f);

            if (!(GameMode is TutorialMode) && !(GameMode is SubTestMode))
            {
                GUI.AddMessage("", Color.Transparent, 3.0f, playSound: false);
                GUI.AddMessage(level.Biome.DisplayName, Color.Lerp(Color.CadetBlue, Color.DarkRed, level.Difficulty / 100.0f), 5.0f, playSound: false);
                GUI.AddMessage(TextManager.AddPunctuation(':', TextManager.Get("Destination"), EndLocation.Name), Color.CadetBlue, playSound: false);
                GUI.AddMessage(TextManager.AddPunctuation(':', TextManager.Get("Mission"), (Mission == null ? TextManager.Get("None") : Mission.Name)), Color.CadetBlue, playSound: false);
            }
#endif

            RoundStartTime = Timing.TotalTime;
            GameMain.ResetFrameTime();
        }
Ejemplo n.º 24
0
        public void PreloadContent(IEnumerable <ContentFile> contentFiles)
        {
            var filesToPreload = new List <ContentFile>(contentFiles);

            foreach (Submarine sub in Submarine.Loaded)
            {
                if (sub.WreckAI == null)
                {
                    continue;
                }

                if (!string.IsNullOrEmpty(sub.WreckAI.Config.DefensiveAgent))
                {
                    var prefab = CharacterPrefab.FindBySpeciesName(sub.WreckAI.Config.DefensiveAgent);
                    if (prefab != null && !filesToPreload.Any(f => f.Path == prefab.FilePath))
                    {
                        filesToPreload.Add(new ContentFile(prefab.FilePath, ContentType.Character));
                    }
                }
                foreach (Item item in Item.ItemList)
                {
                    if (item.Submarine != sub)
                    {
                        continue;
                    }
                    foreach (Items.Components.ItemComponent component in item.Components)
                    {
                        if (component.statusEffectLists == null)
                        {
                            continue;
                        }
                        foreach (var statusEffectList in component.statusEffectLists.Values)
                        {
                            foreach (StatusEffect statusEffect in statusEffectList)
                            {
                                foreach (var spawnInfo in statusEffect.SpawnCharacters)
                                {
                                    var prefab = CharacterPrefab.FindBySpeciesName(spawnInfo.SpeciesName);
                                    if (prefab != null && !filesToPreload.Any(f => f.Path == prefab.FilePath))
                                    {
                                        filesToPreload.Add(new ContentFile(prefab.FilePath, ContentType.Character));
                                    }
                                }
                            }
                        }
                    }
                }
            }

            foreach (ContentFile file in filesToPreload)
            {
                switch (file.Type)
                {
                case ContentType.Character:
#if CLIENT
                    CharacterPrefab characterPrefab = CharacterPrefab.FindByFilePath(file.Path);
                    if (characterPrefab?.XDocument == null)
                    {
                        throw new Exception($"Failed to load the character config file from {file.Path}!");
                    }
                    var doc         = characterPrefab.XDocument;
                    var rootElement = doc.Root;
                    var mainElement = rootElement.IsOverride() ? rootElement.FirstElement() : rootElement;
                    mainElement.GetChildElements("sound").ForEach(e => Submarine.LoadRoundSound(e));
                    if (!CharacterPrefab.CheckSpeciesName(mainElement, file.Path, out string speciesName))
                    {
                        continue;
                    }
                    bool            humanoid = mainElement.GetAttributeBool("humanoid", false);
                    CharacterPrefab originalCharacter;
                    if (characterPrefab.VariantOf != null)
                    {
                        originalCharacter = CharacterPrefab.FindBySpeciesName(characterPrefab.VariantOf);
                        var originalRoot        = originalCharacter.XDocument.Root;
                        var originalMainElement = originalRoot.IsOverride() ? originalRoot.FirstElement() : originalRoot;
                        originalMainElement.GetChildElements("sound").ForEach(e => Submarine.LoadRoundSound(e));
                        if (!CharacterPrefab.CheckSpeciesName(mainElement, file.Path, out string name))
                        {
                            continue;
                        }
                        speciesName = name;
                        if (mainElement.Attribute("humanoid") == null)
                        {
                            humanoid = originalMainElement.GetAttributeBool("humanoid", false);
                        }
                    }
                    RagdollParams ragdollParams;
                    try
                    {
                        if (humanoid)
                        {
                            ragdollParams = RagdollParams.GetRagdollParams <HumanRagdollParams>(characterPrefab.VariantOf ?? speciesName);
                        }
                        else
                        {
                            ragdollParams = RagdollParams.GetRagdollParams <FishRagdollParams>(characterPrefab.VariantOf ?? speciesName);
                        }
                    }
                    catch (Exception e)
                    {
                        DebugConsole.ThrowError($"Failed to preload a ragdoll file for the character \"{characterPrefab.Name}\"", e);
                        continue;
                    }

                    if (ragdollParams != null)
                    {
                        HashSet <string> texturePaths = new HashSet <string>
                        {
                            ragdollParams.Texture
                        };
                        foreach (RagdollParams.LimbParams limb in ragdollParams.Limbs)
                        {
                            if (!string.IsNullOrEmpty(limb.normalSpriteParams?.Texture))
                            {
                                texturePaths.Add(limb.normalSpriteParams.Texture);
                            }
                            if (!string.IsNullOrEmpty(limb.deformSpriteParams?.Texture))
                            {
                                texturePaths.Add(limb.deformSpriteParams.Texture);
                            }
                            if (!string.IsNullOrEmpty(limb.damagedSpriteParams?.Texture))
                            {
                                texturePaths.Add(limb.damagedSpriteParams.Texture);
                            }
                            foreach (var decorativeSprite in limb.decorativeSpriteParams)
                            {
                                if (!string.IsNullOrEmpty(decorativeSprite.Texture))
                                {
                                    texturePaths.Add(decorativeSprite.Texture);
                                }
                            }
                        }
                        foreach (string texturePath in texturePaths)
                        {
                            preloadedSprites.Add(new Sprite(texturePath, Vector2.Zero));
                        }
                    }
#endif
                    break;
                }
            }
        }
Ejemplo n.º 25
0
        public string CreateRoomName()
        {
            List <string> roomItems = new List <string>();

            foreach (Item item in Item.ItemList)
            {
                if (item.CurrentHull != this)
                {
                    continue;
                }
                if (item.GetComponent <Items.Components.Reactor>() != null)
                {
                    roomItems.Add("reactor");
                }
                if (item.GetComponent <Items.Components.Engine>() != null)
                {
                    roomItems.Add("engine");
                }
                if (item.GetComponent <Items.Components.Steering>() != null)
                {
                    roomItems.Add("steering");
                }
                if (item.GetComponent <Items.Components.Sonar>() != null)
                {
                    roomItems.Add("sonar");
                }
                if (item.HasTag("ballast"))
                {
                    roomItems.Add("ballast");
                }
            }

            if (roomItems.Contains("reactor"))
            {
                return("RoomName.ReactorRoom");
            }
            else if (roomItems.Contains("engine"))
            {
                return("RoomName.EngineRoom");
            }
            else if (roomItems.Contains("steering") && roomItems.Contains("sonar"))
            {
                return("RoomName.CommandRoom");
            }
            else if (roomItems.Contains("ballast"))
            {
                return("RoomName.Ballast");
            }

            if (ConnectedGaps.Any(g => !g.IsRoomToRoom && g.ConnectedDoor != null))
            {
                return("RoomName.Airlock");
            }

            Rectangle subRect = Submarine.CalculateDimensions();

            Alignment roomPos;

            if (rect.Y - rect.Height / 2 > subRect.Y + subRect.Height * 0.66f)
            {
                roomPos = Alignment.Top;
            }
            else if (rect.Y - rect.Height / 2 > subRect.Y + subRect.Height * 0.33f)
            {
                roomPos = Alignment.CenterY;
            }
            else
            {
                roomPos = Alignment.Bottom;
            }

            if (rect.Center.X < subRect.X + subRect.Width * 0.33f)
            {
                roomPos |= Alignment.Left;
            }
            else if (rect.Center.X < subRect.X + subRect.Width * 0.66f)
            {
                roomPos |= Alignment.CenterX;
            }
            else
            {
                roomPos |= Alignment.Right;
            }

            return("RoomName.Sub" + roomPos.ToString());
        }
Ejemplo n.º 26
0
        public SteeringPath FindPath(Vector2 start, Vector2 end, string errorMsgStr = null)
        {
            float    closestDist = 0.0f;
            PathNode startNode   = null;

            foreach (PathNode node in nodes)
            {
                Vector2 nodePos = node.Position;

                float xDiff = System.Math.Abs(start.X - nodePos.X);
                float yDiff = System.Math.Abs(start.Y - nodePos.Y);

                if (yDiff > 1.0f && node.Waypoint.Ladders == null && node.Waypoint.Stairs == null)
                {
                    yDiff += 10.0f;
                }

                float dist = xDiff + (insideSubmarine ? yDiff * 10.0f : yDiff); //higher cost for vertical movement when inside the sub

                //prefer nodes that are closer to the end position
                dist += (Math.Abs(end.X - nodePos.X) + Math.Abs(end.Y - nodePos.Y)) / 2.0f;
                //much higher cost to waypoints that are outside
                if (node.Waypoint.CurrentHull == null && insideSubmarine)
                {
                    dist *= 10.0f;
                }
                if (dist < closestDist || startNode == null)
                {
                    //if searching for a path inside the sub, make sure the waypoint is visible
                    if (insideSubmarine)
                    {
                        var body = Submarine.PickBody(
                            start, node.Waypoint.SimPosition, null,
                            Physics.CollisionWall | Physics.CollisionLevel | Physics.CollisionStairs | Physics.CollisionPlatform);

                        if (body != null)
                        {
                            if (body.UserData is Submarine)
                            {
                                continue;
                            }
                            if (body.UserData is Structure && !((Structure)body.UserData).IsPlatform)
                            {
                                continue;
                            }
                            if (body.UserData is Item && body.FixtureList[0].CollisionCategories.HasFlag(Physics.CollisionWall))
                            {
                                continue;
                            }
                        }
                    }

                    closestDist = dist;
                    startNode   = node;
                }
            }

            if (startNode == null)
            {
                DebugConsole.NewMessage("Pathfinding error, couldn't find a start node. " + errorMsgStr, Color.DarkRed);

                return(new SteeringPath(true));
            }

            closestDist = 0.0f;
            PathNode endNode = null;

            foreach (PathNode node in nodes)
            {
                Vector2 nodePos = node.Position;

                float dist = Vector2.Distance(end, nodePos);
                if (insideSubmarine)
                {
                    //much higher cost to waypoints that are outside
                    if (node.Waypoint.CurrentHull == null)
                    {
                        dist *= 10.0f;
                    }
                    //avoid stopping at a doorway
                    if (node.Waypoint.ConnectedDoor != null)
                    {
                        dist *= 10.0f;
                    }
                }
                if (dist < closestDist || endNode == null)
                {
                    //if searching for a path inside the sub, make sure the waypoint is visible
                    if (insideSubmarine)
                    {
                        // TODO: for some reason fails to find the path when the sub is flooding. Disabling this check helps fixes it, but we can't disable it
                        var body = Submarine.CheckVisibility(end, node.Waypoint.SimPosition);
                        if (body != null && body.UserData is Structure)
                        {
                            continue;
                        }
                    }

                    closestDist = dist;
                    endNode     = node;
                }
            }

            if (endNode == null)
            {
                DebugConsole.NewMessage("Pathfinding error, couldn't find an end node. " + errorMsgStr, Color.DarkRed);
                return(new SteeringPath(true));
            }

            var path = FindPath(startNode, endNode);

            return(path);
        }
        partial void UpdateProjSpecific(float deltaTime, Camera cam)
        {
            serverUpdateDelay -= deltaTime;
            if (serverUpdateDelay <= 0.0f)
            {
                ApplyRemoteState();
            }

            if (networkUpdatePending)
            {
                networkUpdateTimer += deltaTime;
                if (networkUpdateTimer > 0.2f)
                {
                    if (!pendingSectionUpdates.Any() && !pendingDecalUpdates.Any())
                    {
                        GameMain.NetworkMember?.CreateEntityEvent(this);
                    }
                    foreach (Decal decal in pendingDecalUpdates)
                    {
                        GameMain.NetworkMember?.CreateEntityEvent(this, new object[] { decal });
                    }
                    foreach (int pendingSectionUpdate in pendingSectionUpdates)
                    {
                        GameMain.NetworkMember?.CreateEntityEvent(this, new object[] { pendingSectionUpdate });
                    }
                    pendingSectionUpdates.Clear();
                    networkUpdatePending = false;
                    networkUpdateTimer   = 0.0f;
                }
            }

            if (EditWater)
            {
                Vector2 position = cam.ScreenToWorld(PlayerInput.MousePosition);
                if (Submarine.RectContains(WorldRect, position))
                {
                    if (PlayerInput.PrimaryMouseButtonHeld())
                    {
                        WaterVolume         += 1500.0f;
                        networkUpdatePending = true;
                        serverUpdateDelay    = 0.5f;
                    }
                    else if (PlayerInput.SecondaryMouseButtonHeld())
                    {
                        WaterVolume         -= 1500.0f;
                        networkUpdatePending = true;
                        serverUpdateDelay    = 0.5f;
                    }
                }
            }
            else if (EditFire)
            {
                Vector2 position = cam.ScreenToWorld(PlayerInput.MousePosition);
                if (Submarine.RectContains(WorldRect, position))
                {
                    if (PlayerInput.PrimaryMouseButtonClicked())
                    {
                        new FireSource(position, this, isNetworkMessage: true);
                        networkUpdatePending = true;
                        serverUpdateDelay    = 0.5f;
                    }
                }
            }

            if (waterVolume < 1.0f)
            {
                return;
            }
            for (int i = 1; i < waveY.Length - 1; i++)
            {
                float maxDelta = Math.Max(Math.Abs(rightDelta[i]), Math.Abs(leftDelta[i]));
                if (maxDelta > 1.0f && maxDelta > Rand.Range(1.0f, 10.0f))
                {
                    var particlePos = new Vector2(rect.X + WaveWidth * i, surface + waveY[i]);
                    if (Submarine != null)
                    {
                        particlePos += Submarine.Position;
                    }

                    GameMain.ParticleManager.CreateParticle("mist",
                                                            particlePos,
                                                            new Vector2(0.0f, -50.0f), 0.0f, this);
                }
            }
        }
Ejemplo n.º 28
0
 public void TransformOutToInside(Submarine submarine)
 {
     //transform outside coordinates to in-sub coordinates
     Position -= ConvertUnits.ToSimUnits(submarine.Position);
 }
Ejemplo n.º 29
0
        public static void Update(float deltaTime, Character character, Camera cam)
        {
            if (GUI.DisableHUD)
            {
                return;
            }

            if (!character.IsIncapacitated && character.Stun <= 0.0f)
            {
                if (character.Info != null && !character.ShouldLockHud() && character.SelectedCharacter == null)
                {
                    bool mouseOnPortrait = HUDLayoutSettings.BottomRightInfoArea.Contains(PlayerInput.MousePosition) && GUI.MouseOn == null;
                    if (mouseOnPortrait && PlayerInput.PrimaryMouseButtonClicked())
                    {
                        CharacterHealth.OpenHealthWindow = character.CharacterHealth;
                    }
                }

                if (character.Inventory != null)
                {
                    if (!LockInventory(character))
                    {
                        character.Inventory.Update(deltaTime, cam);
                    }
                    for (int i = 0; i < character.Inventory.Items.Length - 1; i++)
                    {
                        var item = character.Inventory.Items[i];
                        if (item == null || character.Inventory.SlotTypes[i] == InvSlotType.Any)
                        {
                            continue;
                        }

                        foreach (ItemComponent ic in item.Components)
                        {
                            if (ic.DrawHudWhenEquipped)
                            {
                                ic.UpdateHUD(character, deltaTime, cam);
                            }
                        }
                    }
                }

                if (character.IsHumanoid && character.SelectedCharacter != null && character.SelectedCharacter.Inventory != null)
                {
                    if (character.SelectedCharacter.CanInventoryBeAccessed)
                    {
                        character.SelectedCharacter.Inventory.Update(deltaTime, cam);
                    }
                    character.SelectedCharacter.CharacterHealth.UpdateHUD(deltaTime);
                }

                Inventory.UpdateDragging();
            }

            if (focusedItem != null)
            {
                if (character.FocusedItem != null)
                {
                    focusedItemOverlayTimer = Math.Min(focusedItemOverlayTimer + deltaTime, ItemOverlayDelay + 1.0f);
                }
                else
                {
                    focusedItemOverlayTimer = Math.Max(focusedItemOverlayTimer - deltaTime, 0.0f);
                    if (focusedItemOverlayTimer <= 0.0f)
                    {
                        focusedItem            = null;
                        shouldRecreateHudTexts = true;
                    }
                }
            }

            if (brokenItemsCheckTimer > 0.0f)
            {
                brokenItemsCheckTimer -= deltaTime;
            }
            else
            {
                brokenItems.Clear();
                brokenItemsCheckTimer = 1.0f;
                foreach (Item item in Item.ItemList)
                {
                    if (item.Submarine == null || item.Submarine.TeamID != character.TeamID || item.Submarine.Info.IsWreck)
                    {
                        continue;
                    }
                    if (!item.Repairables.Any(r => item.ConditionPercentage <= r.AIRepairThreshold))
                    {
                        continue;
                    }
                    if (Submarine.VisibleEntities != null && !Submarine.VisibleEntities.Contains(item))
                    {
                        continue;
                    }

                    Vector2 diff = item.WorldPosition - character.WorldPosition;
                    if (Submarine.CheckVisibility(character.SimPosition, character.SimPosition + ConvertUnits.ToSimUnits(diff)) == null)
                    {
                        brokenItems.Add(item);
                    }
                }
            }
        }
        //goes through all the AItargets, evaluates how preferable it is to attack the target,
        //whether the Character can see/hear the target and chooses the most preferable target within
        //sight/hearing range
        public void UpdateTargets(Character character)
        {
            var prevAiTarget = selectedAiTarget;

            selectedAiTarget     = null;
            selectedTargetMemory = null;
            targetValue          = 0.0f;

            UpdateTargetMemories();

            foreach (AITarget target in AITarget.List)
            {
                if (Level.Loaded != null && target.WorldPosition.Y > Level.Loaded.Size.Y)
                {
                    continue;
                }

                float valueModifier = 0.0f;
                float dist          = 0.0f;


                Character targetCharacter = target.Entity as Character;

                //ignore the aitarget if it is the Character itself
                if (targetCharacter == character)
                {
                    continue;
                }

                if (targetCharacter != null)
                {
                    if (targetCharacter.IsDead)
                    {
                        if (eatDeadPriority == 0.0f)
                        {
                            continue;
                        }
                        valueModifier = eatDeadPriority;
                    }
                    else if (targetCharacter.SpeciesName == "human")
                    {
                        if (attackHumans == 0.0f)
                        {
                            continue;
                        }
                        valueModifier = attackHumans;
                    }
                    else
                    {
                        EnemyAIController enemy = targetCharacter.AIController as EnemyAIController;
                        if (enemy != null)
                        {
                            if (enemy.combatStrength > combatStrength)
                            {
                                valueModifier = attackStronger;
                            }
                            else if (enemy.combatStrength < combatStrength)
                            {
                                valueModifier = attackWeaker;
                            }
                            else
                            {
                                continue;
                            }
                        }
                    }
                }
                else if (target.Entity != null && attackRooms != 0.0f)
                {
                    IDamageable targetDamageable = target.Entity as IDamageable;
                    if (targetDamageable != null && targetDamageable.Health <= 0.0f)
                    {
                        continue;
                    }

                    //skip the target if it's a room and the character is already inside a sub
                    if (character.AnimController.CurrentHull != null && target.Entity is Hull)
                    {
                        continue;
                    }

                    valueModifier = attackRooms;
                }

                if (valueModifier == 0.0f)
                {
                    continue;
                }

                dist = Vector2.Distance(character.WorldPosition, target.WorldPosition);

                //if the target has been within range earlier, the character will notice it more easily
                //(i.e. remember where the target was)
                if (targetMemories.ContainsKey(target))
                {
                    dist *= 0.5f;
                }

                //ignore target if it's too far to see or hear
                if (dist > target.SightRange * sight && dist > target.SoundRange * hearing)
                {
                    continue;
                }

                AITargetMemory targetMemory = FindTargetMemory(target);
                valueModifier = valueModifier * targetMemory.Priority / dist;

                if (Math.Abs(valueModifier) > Math.Abs(targetValue))
                {
                    Vector2 rayStart = character.AnimController.Limbs[0].SimPosition;
                    Vector2 rayEnd   = target.SimPosition;

                    if (target.Entity.Submarine != null && character.Submarine == null)
                    {
                        rayStart -= ConvertUnits.ToSimUnits(target.Entity.Submarine.Position);
                    }

                    Body      closestBody      = Submarine.CheckVisibility(rayStart, rayEnd);
                    Structure closestStructure = (closestBody == null) ? null : closestBody.UserData as Structure;

                    if (selectedAiTarget == null || Math.Abs(valueModifier) > Math.Abs(targetValue))
                    {
                        selectedAiTarget     = target;
                        selectedTargetMemory = targetMemory;

                        targetValue = valueModifier;
                    }
                }
            }

            if (selectedAiTarget != prevAiTarget)
            {
                wallAttackPos = Vector2.Zero;
            }
        }