private bool ToggleCharacterMode(GUIButton button, object obj) { selectedTab = -1; characterMode = !characterMode; //button.Color = (characterMode) ? Color.Gold : Color.White; wiringMode = false; if (characterMode) { CreateDummyCharacter(); } else if (dummyCharacter != null) { RemoveDummyCharacter(); } foreach (MapEntity me in MapEntity.mapEntityList) { me.IsHighlighted = false; } MapEntity.DeselectAll(); return(true); }
public override void Deselect() { base.Deselect(); GUIComponent.ForceMouseOn(null); MapEntityPrefab.Selected = null; MapEntity.DeselectAll(); if (characterMode) { ToggleCharacterMode(); } if (wiringMode) { ToggleWiringMode(); } SoundPlayer.OverrideMusicType = null; for (int i = 0; i < Sounds.SoundManager.DefaultSourceCount; i++) { Sounds.SoundManager.Resume(i); } if (dummyCharacter != null) { dummyCharacter.Remove(); dummyCharacter = null; GameMain.World.ProcessChanges(); } }
public static void RemoveSelection(MapEntity entity) { selectedList.Remove(entity); HandleDoorGapLinks(entity, onGapFound: (door, gap) => selectedList.Remove(gap), onDoorFound: (door, gap) => selectedList.Remove(door.Item)); }
private bool ToggleWiringMode(GUIButton button, object obj) { wiringMode = !wiringMode; characterMode = false; if (wiringMode) { CreateDummyCharacter(); var screwdriverPrefab = ItemPrefab.list.Find(ip => ip.Name == "Screwdriver") as ItemPrefab; var item = new Item(screwdriverPrefab, Vector2.Zero, null); dummyCharacter.Inventory.TryPutItem(item, null, new List <InvSlotType>() { InvSlotType.RightHand }); wiringToolPanel = CreateWiringPanel(); } else { RemoveDummyCharacter(); } MapEntity.DeselectAll(); return(true); }
private static void UpdateHighlightedListBox(List <MapEntity> highlightedEntities) { if (highlightedEntities == null || highlightedEntities.Count < 2) { highlightedListBox = null; return; } if (highlightedListBox != null) { if (GUI.MouseOn == highlightedListBox || highlightedListBox.IsParentOf(GUI.MouseOn)) { return; } if (highlightedEntities.SequenceEqual(highlightedList)) { return; } } highlightedList = highlightedEntities; highlightedListBox = new GUIListBox(new RectTransform(new Point(180, highlightedEntities.Count * 18 + 5), GUI.Canvas) { ScreenSpaceOffset = PlayerInput.MousePosition.ToPoint() + new Point(15) }, style: "GUIToolTip"); foreach (MapEntity entity in highlightedEntities) { var textBlock = new GUITextBlock(new RectTransform(new Point(highlightedListBox.Content.Rect.Width, 15), highlightedListBox.Content.RectTransform), ToolBox.LimitString(entity.Name, GUI.SmallFont, 140), font: GUI.SmallFont) { UserData = entity }; } highlightedListBox.OnSelected = (GUIComponent component, object obj) => { MapEntity entity = obj as MapEntity; if (PlayerInput.KeyDown(Keys.LeftControl) || PlayerInput.KeyDown(Keys.RightControl)) { if (selectedList.Contains(entity)) { selectedList.Remove(entity); } else { selectedList.Add(entity); } } else { SelectEntity(entity); } return(true); }; }
private static void UpdateHighlightedListBox(List <MapEntity> highlightedEntities) { if (highlightedEntities == null || highlightedEntities.Count < 2) { highlightedListBox = null; return; } if (highlightedListBox != null) { if (GUIComponent.MouseOn == highlightedListBox || highlightedListBox.IsParentOf(GUIComponent.MouseOn)) { return; } if (highlightedEntities.SequenceEqual(highlightedList)) { return; } } highlightedList = highlightedEntities; highlightedListBox = new GUIListBox( new Rectangle((int)PlayerInput.MousePosition.X + 15, (int)PlayerInput.MousePosition.Y + 15, 150, highlightedEntities.Count * 18 + 5), null, Alignment.TopLeft, "GUIToolTip", null, false); foreach (MapEntity entity in highlightedEntities) { var textBlock = new GUITextBlock( new Rectangle(0, 0, highlightedListBox.Rect.Width, 18), ToolBox.LimitString(entity.Name, GUI.SmallFont, 140), "", Alignment.TopLeft, Alignment.CenterLeft, highlightedListBox, false, GUI.SmallFont); textBlock.UserData = entity; } highlightedListBox.OnSelected = (GUIComponent component, object obj) => { MapEntity entity = obj as MapEntity; if (PlayerInput.KeyDown(Keys.LeftControl) || PlayerInput.KeyDown(Keys.RightControl)) { if (selectedList.Contains(entity)) { selectedList.Remove(entity); } else { selectedList.Add(entity); } } else { SelectEntity(entity); } return(true); }; }
/// <summary> /// Update the linkedTo-lists of the entities based on the linkedToID-lists /// Has to be done after all the entities have been loaded (an entity can't /// be linked to some other entity that hasn't been loaded yet) /// </summary> public static void MapLoaded(Submarine sub) { foreach (MapEntity e in mapEntityList) { if (e.Submarine != sub) { continue; } if (e.linkedToID == null) { continue; } if (e.linkedToID.Count == 0) { continue; } e.linkedTo.Clear(); foreach (ushort i in e.linkedToID) { MapEntity linked = FindEntityByID(i) as MapEntity; if (linked != null) { e.linkedTo.Add(linked); } } } List <LinkedSubmarine> linkedSubs = new List <LinkedSubmarine>(); for (int i = 0; i < mapEntityList.Count; i++) { if (mapEntityList[i].Submarine != sub) { continue; } if (mapEntityList[i] is LinkedSubmarine) { linkedSubs.Add((LinkedSubmarine)mapEntityList[i]); continue; } mapEntityList[i].OnMapLoaded(); } Item.UpdateHulls(); Gap.UpdateHulls(); foreach (LinkedSubmarine linkedSub in linkedSubs) { linkedSub.OnMapLoaded(); } }
public void RemoveLinked(MapEntity e) { if (linkedTo == null) { return; } if (linkedTo.Contains(e)) { linkedTo.Remove(e); } }
public void RemoveEntity(MapEntity entity) { for (int x = 0; x < entities.GetLength(0); x++) { for (int y = 0; y < entities.GetLength(1); y++) { if (entities[x, y].Contains(entity)) { entities[x, y].Remove(entity); } } } }
public static List <MapEntity> PasteEntities(Vector2 position, Submarine sub, XElement configElement, string filePath = null, bool selectInstance = false) { int idOffset = Entity.FindFreeID(1); if (MapEntity.mapEntityList.Any()) { idOffset = MapEntity.mapEntityList.Max(e => e.ID); } List <MapEntity> entities = MapEntity.LoadAll(sub, configElement, filePath, idOffset); if (entities.Count == 0) { return(entities); } Vector2 offset = sub?.HiddenSubPosition ?? Vector2.Zero; foreach (MapEntity me in entities) { me.Move(position); me.Submarine = sub; if (!(me is Item item)) { continue; } Wire wire = item.GetComponent <Wire>(); //Vector2 subPosition = Submarine == null ? Vector2.Zero : Submarine.HiddenSubPosition; if (wire != null) { //fix wires that have been erroneously saved at the "hidden position" if (sub != null && Vector2.Distance(me.Position, sub.HiddenSubPosition) > sub.HiddenSubPosition.Length() / 2) { me.Move(position); } wire.MoveNodes(position - offset); } } MapEntity.MapLoaded(entities, true); #if CLIENT if (Screen.Selected == GameMain.SubEditorScreen && selectInstance) { MapEntity.SelectedList.Clear(); entities.ForEach(MapEntity.AddSelection); } #endif return(entities); }
private void SetRects(IReadOnlyList <Rectangle> rects) { if (Receivers.Count != rects.Count) { DebugConsole.ThrowError($"Receivers.Count did not match Rects.Count ({Receivers.Count} vs {rects.Count})."); return; } for (int i = 0; i < rects.Count; i++) { MapEntity entity = Receivers[i].GetReplacementOrThis(); Rectangle Rect = rects[i]; Vector2 diff = Rect.Location.ToVector2() - entity.Rect.Location.ToVector2(); entity.Move(diff); entity.Rect = Rect; } }
/// <summary> /// Gets all linked entities of specific type. /// </summary> private static void GetLinkedEntitiesRecursive <T>(MapEntity mapEntity, HashSet <T> linkedTargets, ref int depth, int?maxDepth = null, Func <T, bool> filter = null) where T : MapEntity { if (depth > maxDepth) { return; } foreach (var linkedEntity in mapEntity.linkedTo) { if (linkedEntity is T linkedTarget) { if (!linkedTargets.Contains(linkedTarget) && (filter == null || filter(linkedTarget))) { linkedTargets.Add(linkedTarget); depth++; GetLinkedEntitiesRecursive(linkedEntity, linkedTargets, ref depth, maxDepth, filter); } } } }
public void InsertEntity(MapEntity entity) { Rectangle rect = entity.Rect; //if (Submarine.Loaded != null) rect.Offset(-Submarine.HiddenSubPosition); Rectangle indices = GetIndices(rect); if (indices.Width < 0 || indices.X >= entities.GetLength(0) || indices.Height < 0 || indices.Y >= entities.GetLength(1)) { DebugConsole.ThrowError("Error in EntityGrid.InsertEntity: " + entity + " is outside the grid"); return; } for (int x = Math.Max(indices.X, 0); x <= Math.Min(indices.Width, entities.GetLength(0) - 1); x++) { for (int y = Math.Max(indices.Y, 0); y <= Math.Min(indices.Height, entities.GetLength(1) - 1); y++) { entities[x, y].Add(entity); } } }
private static void HandleDoorGapLinks(MapEntity entity, Action <Door, Gap> onGapFound, Action <Door, Gap> onDoorFound) { if (entity is Item i) { var door = i.GetComponent <Door>(); if (door != null) { var gap = door.LinkedGap; if (gap != null) { onGapFound(door, gap); } } } else if (entity is Gap gap) { var door = gap.ConnectedDoor; if (door != null) { onDoorFound(door, gap); } } }
public List <MapEntity> CreateInstance(Vector2 position, Submarine sub) { List <MapEntity> entities = MapEntity.LoadAll(sub, configElement, configPath); if (entities.Count == 0) { return(entities); } Vector2 offset = sub == null ? Vector2.Zero : sub.HiddenSubPosition; foreach (MapEntity me in entities) { me.Move(position); Item item = me as Item; if (item == null) { continue; } Wire wire = item.GetComponent <Wire>(); if (wire != null) { wire.MoveNodes(position - offset); } } MapEntity.MapLoaded(entities, true); #if CLIENT if (Screen.Selected == GameMain.SubEditorScreen) { MapEntity.SelectedList.Clear(); entities.ForEach(e => MapEntity.AddSelection(e)); } #endif return(entities); }
public static void AddSelection(MapEntity entity) { if (selectedList.Contains(entity)) { return; } selectedList.Add(entity); HandleDoorGapLinks(entity, onGapFound: (door, gap) => { door.RefreshLinkedGap(); if (!selectedList.Contains(gap)) { selectedList.Add(gap); } }, onDoorFound: (door, gap) => { if (!selectedList.Contains(door.Item)) { selectedList.Add(door.Item); } }); }
/// <summary> /// Update the selection logic in submarine editor /// </summary> public static void UpdateSelecting(Camera cam) { if (resizing) { if (selectedList.Count == 0) { resizing = false; } return; } foreach (MapEntity e in mapEntityList) { e.isHighlighted = false; } if (DisableSelect) { DisableSelect = false; return; } if (GUI.MouseOn != null || !PlayerInput.MouseInsideWindow) { if (highlightedListBox == null || (GUI.MouseOn != highlightedListBox && !highlightedListBox.IsParentOf(GUI.MouseOn))) { UpdateHighlightedListBox(null); return; } } if (MapEntityPrefab.Selected != null) { selectionPos = Vector2.Zero; selectedList.Clear(); return; } if (PlayerInput.KeyDown(Keys.Delete)) { selectedList.ForEach(e => e.Remove()); selectedList.Clear(); } if (PlayerInput.KeyDown(Keys.LeftControl) || PlayerInput.KeyDown(Keys.RightControl)) { if (PlayerInput.KeyHit(Keys.C)) { CopyEntities(selectedList); } else if (PlayerInput.KeyHit(Keys.X)) { CopyEntities(selectedList); selectedList.ForEach(e => e.Remove()); selectedList.Clear(); } else if (copiedList.Count > 0 && PlayerInput.KeyHit(Keys.V)) { List <MapEntity> prevEntities = new List <MapEntity>(mapEntityList); Clone(copiedList); var clones = mapEntityList.Except(prevEntities).ToList(); Vector2 center = Vector2.Zero; clones.ForEach(c => center += c.WorldPosition); center = Submarine.VectorToWorldGrid(center / clones.Count); Vector2 moveAmount = Submarine.VectorToWorldGrid(cam.WorldViewCenter - center); selectedList = new List <MapEntity>(clones); foreach (MapEntity clone in selectedList) { clone.Move(moveAmount); clone.Submarine = Submarine.MainSub; } } else if (PlayerInput.KeyHit(Keys.G)) { if (selectedList.Any()) { if (SelectionGroups.ContainsKey(selectedList.Last())) { // Ungroup all selected selectedList.ForEach(e => SelectionGroups.Remove(e)); } else { foreach (var entity in selectedList) { // Remove the old group, if any SelectionGroups.Remove(entity); // Create a group that can be accessed with any member SelectionGroups.Add(entity, selectedList); } } } } else if (PlayerInput.KeyHit(Keys.Z)) { SetPreviousRects(e => e.rectMemento.Undo()); } else if (PlayerInput.KeyHit(Keys.R)) { SetPreviousRects(e => e.rectMemento.Redo()); } void SetPreviousRects(Func <MapEntity, Rectangle> memoryMethod) { foreach (var e in SelectedList) { if (e.rectMemento != null) { Point diff = memoryMethod(e).Location - e.Rect.Location; // We have to call the move method, because there's a lot more than just storing the rect (in some cases) // We also have to reassign the rect, because the move method does not set the width and height. They might have changed too. // The Rect property is virtual and it's overridden for structs. Setting the rect via the property should automatically recreate the sections for resizable structures. e.Move(diff.ToVector2()); e.Rect = e.rectMemento.Current; } } } } Vector2 position = cam.ScreenToWorld(PlayerInput.MousePosition); MapEntity highLightedEntity = null; if (startMovingPos == Vector2.Zero) { List <MapEntity> highlightedEntities = new List <MapEntity>(); if (highlightedListBox != null && highlightedListBox.IsParentOf(GUI.MouseOn)) { highLightedEntity = GUI.MouseOn.UserData as MapEntity; } else { foreach (MapEntity e in mapEntityList) { if (!e.SelectableInEditor) { continue; } if (e.IsMouseOn(position)) { int i = 0; while (i < highlightedEntities.Count && e.Sprite != null && (highlightedEntities[i].Sprite == null || highlightedEntities[i].SpriteDepth < e.SpriteDepth)) { i++; } highlightedEntities.Insert(i, e); if (i == 0) { highLightedEntity = e; } } } if (PlayerInput.MouseSpeed.LengthSquared() > 10) { highlightTimer = 0.0f; } else { bool mouseNearHighlightBox = false; if (highlightedListBox != null) { Rectangle expandedRect = highlightedListBox.Rect; expandedRect.Inflate(20, 20); mouseNearHighlightBox = expandedRect.Contains(PlayerInput.MousePosition); if (!mouseNearHighlightBox) { highlightedListBox = null; } } highlightTimer += (float)Timing.Step; if (highlightTimer > 1.0f) { if (!mouseNearHighlightBox) { UpdateHighlightedListBox(highlightedEntities); highlightTimer = 0.0f; } } } } if (highLightedEntity != null) { highLightedEntity.isHighlighted = true; } } Vector2 nudgeAmount = Vector2.Zero; if (PlayerInput.KeyHit(Keys.Up)) { nudgeAmount.Y = 1f; } if (PlayerInput.KeyHit(Keys.Down)) { nudgeAmount.Y = -1f; } if (PlayerInput.KeyHit(Keys.Left)) { nudgeAmount.X = -1f; } if (PlayerInput.KeyHit(Keys.Right)) { nudgeAmount.X = 1f; } if (nudgeAmount != Vector2.Zero) { foreach (MapEntity entityToNudge in selectedList) { entityToNudge.Move(nudgeAmount); } } //started moving selected entities if (startMovingPos != Vector2.Zero) { if (PlayerInput.LeftButtonReleased()) { //mouse released -> move the entities to the new position of the mouse Vector2 moveAmount = position - startMovingPos; moveAmount.X = (float)(moveAmount.X > 0.0f ? Math.Floor(moveAmount.X / Submarine.GridSize.X) : Math.Ceiling(moveAmount.X / Submarine.GridSize.X)) * Submarine.GridSize.X; moveAmount.Y = (float)(moveAmount.Y > 0.0f ? Math.Floor(moveAmount.Y / Submarine.GridSize.Y) : Math.Ceiling(moveAmount.Y / Submarine.GridSize.Y)) * Submarine.GridSize.Y; if (Math.Abs(moveAmount.X) >= Submarine.GridSize.X || Math.Abs(moveAmount.Y) >= Submarine.GridSize.Y) { moveAmount = Submarine.VectorToWorldGrid(moveAmount); //clone if (PlayerInput.KeyDown(Keys.LeftControl) || PlayerInput.KeyDown(Keys.RightControl)) { var clones = Clone(selectedList); selectedList = clones; selectedList.ForEach(c => c.Move(moveAmount)); } else // move { foreach (MapEntity e in selectedList) { if (e.rectMemento == null) { e.rectMemento = new Memento <Rectangle>(); e.rectMemento.Store(e.Rect); } e.Move(moveAmount); e.rectMemento.Store(e.Rect); } } } startMovingPos = Vector2.Zero; } } //started dragging a "selection rectangle" else if (selectionPos != Vector2.Zero) { selectionSize.X = position.X - selectionPos.X; selectionSize.Y = selectionPos.Y - position.Y; List <MapEntity> newSelection = new List <MapEntity>();// FindSelectedEntities(selectionPos, selectionSize); if (Math.Abs(selectionSize.X) > Submarine.GridSize.X || Math.Abs(selectionSize.Y) > Submarine.GridSize.Y) { newSelection = FindSelectedEntities(selectionPos, selectionSize); } else { if (highLightedEntity != null) { if (SelectionGroups.TryGetValue(highLightedEntity, out List <MapEntity> group)) { newSelection.AddRange(group); } else { newSelection.Add(highLightedEntity); } } } if (PlayerInput.LeftButtonReleased()) { if (PlayerInput.KeyDown(Keys.LeftControl) || PlayerInput.KeyDown(Keys.RightControl)) { foreach (MapEntity e in newSelection) { if (selectedList.Contains(e)) { selectedList.Remove(e); } else { selectedList.Add(e); } } } else { selectedList = newSelection; } //select wire if both items it's connected to are selected var selectedItems = selectedList.Where(e => e is Item).Cast <Item>().ToList(); foreach (Item item in selectedItems) { if (item.Connections == null) { continue; } foreach (Connection c in item.Connections) { foreach (Wire w in c.Wires) { if (w == null || selectedList.Contains(w.Item)) { continue; } if (w.OtherConnection(c) != null && selectedList.Contains(w.OtherConnection(c).Item)) { selectedList.Add(w.Item); } } } } selectionPos = Vector2.Zero; selectionSize = Vector2.Zero; } } //default, not doing anything specific yet else { if (PlayerInput.LeftButtonHeld() && PlayerInput.KeyUp(Keys.Space) && (highlightedListBox == null || (GUI.MouseOn != highlightedListBox && !highlightedListBox.IsParentOf(GUI.MouseOn)))) { //if clicking a selected entity, start moving it foreach (MapEntity e in selectedList) { if (e.IsMouseOn(position)) { startMovingPos = position; } } selectionPos = position; //stop camera movement to prevent accidental dragging or rect selection Screen.Selected.Cam.StopMovement(); } } }
/// <summary> /// Allows the game to run logic such as updating the world, /// checking for collisions, gathering input, and playing audio. /// </summary> public override void Update(double deltaTime) { #if DEBUG if (GameMain.GameSession != null && GameMain.GameSession.Level != null && GameMain.GameSession.Submarine != null && !DebugConsole.IsOpen) { var closestSub = Submarine.FindClosest(cam.WorldViewCenter); if (closestSub == null) { closestSub = GameMain.GameSession.Submarine; } Vector2 targetMovement = Vector2.Zero; if (PlayerInput.KeyDown(Keys.I)) { targetMovement.Y += 1.0f; } if (PlayerInput.KeyDown(Keys.K)) { targetMovement.Y -= 1.0f; } if (PlayerInput.KeyDown(Keys.J)) { targetMovement.X -= 1.0f; } if (PlayerInput.KeyDown(Keys.L)) { targetMovement.X += 1.0f; } if (targetMovement != Vector2.Zero) { closestSub.ApplyForce(targetMovement * closestSub.SubBody.Body.Mass * 100.0f); } } #endif foreach (MapEntity e in MapEntity.mapEntityList) { e.IsHighlighted = false; } if (GameMain.GameSession != null) { GameMain.GameSession.Update((float)deltaTime); } if (Level.Loaded != null) { Level.Loaded.Update((float)deltaTime); } if (Character.Controlled != null && Character.Controlled.SelectedConstruction != null) { if (Character.Controlled.SelectedConstruction == Character.Controlled.ClosestItem) { Character.Controlled.SelectedConstruction.UpdateHUD(cam, Character.Controlled); } } Character.UpdateAll(cam, (float)deltaTime); BackgroundCreatureManager.Update(cam, (float)deltaTime); GameMain.ParticleManager.Update((float)deltaTime); StatusEffect.UpdateAll((float)deltaTime); if (Character.Controlled != null && Lights.LightManager.ViewTarget != null) { cam.TargetPos = Lights.LightManager.ViewTarget.WorldPosition; } GameMain.LightManager.Update((float)deltaTime); cam.MoveCamera((float)deltaTime); foreach (Submarine sub in Submarine.Loaded) { sub.SetPrevTransform(sub.Position); } foreach (PhysicsBody pb in PhysicsBody.list) { pb.SetPrevTransform(pb.SimPosition, pb.Rotation); } MapEntity.UpdateAll(cam, (float)deltaTime); Character.UpdateAnimAll((float)deltaTime); Ragdoll.UpdateAll(cam, (float)deltaTime); foreach (Submarine sub in Submarine.Loaded) { sub.Update((float)deltaTime); } GameMain.World.Step((float)deltaTime); if (!PlayerInput.LeftButtonHeld()) { Inventory.draggingSlot = null; Inventory.draggingItem = null; } }
/// <summary> /// Allows the game to run logic such as updating the world, /// checking for collisions, gathering input, and playing audio. /// </summary> public override void Update(double deltaTime) { #if RUN_PHYSICS_IN_SEPARATE_THREAD physicsTime += deltaTime; lock (updateLock) { #endif #if DEBUG && CLIENT if (GameMain.GameSession != null && GameMain.GameSession.Level != null && GameMain.GameSession.Submarine != null && !DebugConsole.IsOpen && GUI.KeyboardDispatcher.Subscriber == null) { var closestSub = Submarine.FindClosest(cam.WorldViewCenter); if (closestSub == null) { closestSub = GameMain.GameSession.Submarine; } Vector2 targetMovement = Vector2.Zero; if (PlayerInput.KeyDown(Keys.I)) { targetMovement.Y += 1.0f; } if (PlayerInput.KeyDown(Keys.K)) { targetMovement.Y -= 1.0f; } if (PlayerInput.KeyDown(Keys.J)) { targetMovement.X -= 1.0f; } if (PlayerInput.KeyDown(Keys.L)) { targetMovement.X += 1.0f; } if (targetMovement != Vector2.Zero) { closestSub.ApplyForce(targetMovement * closestSub.SubBody.Body.Mass * 100.0f); } } #endif GameTime += deltaTime; foreach (PhysicsBody body in PhysicsBody.List) { if (body.Enabled) { body.Update(); } } foreach (MapEntity e in MapEntity.mapEntityList) { e.IsHighlighted = false; } if (GameMain.GameSession != null) { GameMain.GameSession.Update((float)deltaTime); } #if CLIENT var sw = new System.Diagnostics.Stopwatch(); sw.Start(); GameMain.ParticleManager.Update((float)deltaTime); sw.Stop(); GameMain.PerformanceCounter.AddElapsedTicks("ParticleUpdate", sw.ElapsedTicks); sw.Restart(); if (Level.Loaded != null) { Level.Loaded.Update((float)deltaTime, cam); } sw.Stop(); GameMain.PerformanceCounter.AddElapsedTicks("LevelUpdate", sw.ElapsedTicks); if (Character.Controlled != null) { if (Character.Controlled.SelectedConstruction != null && Character.Controlled.CanInteractWith(Character.Controlled.SelectedConstruction)) { Character.Controlled.SelectedConstruction.UpdateHUD(cam, Character.Controlled, (float)deltaTime); } if (Character.Controlled.Inventory != null) { foreach (Item item in Character.Controlled.Inventory.Items) { if (item == null) { continue; } if (Character.Controlled.HasEquippedItem(item)) { item.UpdateHUD(cam, Character.Controlled, (float)deltaTime); } } } } sw.Restart(); Character.UpdateAll((float)deltaTime, cam); #elif SERVER if (Level.Loaded != null) { Level.Loaded.Update((float)deltaTime, Camera.Instance); } Character.UpdateAll((float)deltaTime, Camera.Instance); #endif #if CLIENT sw.Stop(); GameMain.PerformanceCounter.AddElapsedTicks("CharacterUpdate", sw.ElapsedTicks); sw.Restart(); #endif StatusEffect.UpdateAll((float)deltaTime); #if CLIENT sw.Stop(); GameMain.PerformanceCounter.AddElapsedTicks("StatusEffectUpdate", sw.ElapsedTicks); sw.Restart(); if (Character.Controlled != null && Lights.LightManager.ViewTarget != null) { Vector2 targetPos = Lights.LightManager.ViewTarget.DrawPosition; if (Lights.LightManager.ViewTarget == Character.Controlled && (CharacterHealth.OpenHealthWindow != null || CrewManager.IsCommandInterfaceOpen)) { Vector2 screenTargetPos = new Vector2(0.0f, GameMain.GraphicsHeight * 0.5f); if (CrewManager.IsCommandInterfaceOpen) { screenTargetPos.X = GameMain.GraphicsWidth * 0.5f; } else { screenTargetPos = CharacterHealth.OpenHealthWindow.Alignment == Alignment.Left ? new Vector2(GameMain.GraphicsWidth * 0.75f, GameMain.GraphicsHeight * 0.5f) : new Vector2(GameMain.GraphicsWidth * 0.25f, GameMain.GraphicsHeight * 0.5f); } Vector2 screenOffset = screenTargetPos - new Vector2(GameMain.GraphicsWidth / 2, GameMain.GraphicsHeight / 2); screenOffset.Y = -screenOffset.Y; targetPos -= screenOffset / cam.Zoom; } cam.TargetPos = targetPos; } cam.MoveCamera((float)deltaTime); #endif foreach (Submarine sub in Submarine.Loaded) { sub.SetPrevTransform(sub.Position); } foreach (PhysicsBody body in PhysicsBody.List) { if (body.Enabled) { body.SetPrevTransform(body.SimPosition, body.Rotation); } } #if CLIENT MapEntity.UpdateAll((float)deltaTime, cam); #elif SERVER MapEntity.UpdateAll((float)deltaTime, Camera.Instance); #endif #if CLIENT sw.Stop(); GameMain.PerformanceCounter.AddElapsedTicks("MapEntityUpdate", sw.ElapsedTicks); sw.Restart(); #endif Character.UpdateAnimAll((float)deltaTime); #if CLIENT Ragdoll.UpdateAll((float)deltaTime, cam); #elif SERVER Ragdoll.UpdateAll((float)deltaTime, Camera.Instance); #endif #if CLIENT sw.Stop(); GameMain.PerformanceCounter.AddElapsedTicks("AnimUpdate", sw.ElapsedTicks); sw.Restart(); #endif foreach (Submarine sub in Submarine.Loaded) { sub.Update((float)deltaTime); } #if CLIENT sw.Stop(); GameMain.PerformanceCounter.AddElapsedTicks("SubmarineUpdate", sw.ElapsedTicks); sw.Restart(); #endif #if !RUN_PHYSICS_IN_SEPARATE_THREAD try { GameMain.World.Step((float)Timing.Step); } catch (WorldLockedException e) { string errorMsg = "Attempted to modify the state of the physics simulation while a time step was running."; DebugConsole.ThrowError(errorMsg, e); GameAnalyticsManager.AddErrorEventOnce("GameScreen.Update:WorldLockedException" + e.Message, GameAnalyticsSDK.Net.EGAErrorSeverity.Critical, errorMsg); } #endif #if CLIENT sw.Stop(); GameMain.PerformanceCounter.AddElapsedTicks("Physics", sw.ElapsedTicks); #endif #if CLIENT if (!PlayerInput.PrimaryMouseButtonHeld()) { Inventory.draggingSlot = null; Inventory.draggingItem = null; } #endif #if RUN_PHYSICS_IN_SEPARATE_THREAD } #endif }
public void Generate(bool mirror = false) { if (backgroundSpriteManager == null) { var files = GameMain.SelectedPackage.GetFilesOfType(ContentType.BackgroundSpritePrefabs); if (files.Count > 0) { backgroundSpriteManager = new BackgroundSpriteManager(files); } else { backgroundSpriteManager = new BackgroundSpriteManager("Content/BackgroundSprites/BackgroundSpritePrefabs.xml"); } } #if CLIENT if (backgroundCreatureManager == null) { var files = GameMain.SelectedPackage.GetFilesOfType(ContentType.BackgroundCreaturePrefabs); if (files.Count > 0) { backgroundCreatureManager = new BackgroundCreatureManager(files); } else { backgroundCreatureManager = new BackgroundCreatureManager("Content/BackgroundSprites/BackgroundCreaturePrefabs.xml"); } } #endif Stopwatch sw = new Stopwatch(); sw.Start(); if (loaded != null) { loaded.Unload(); } loaded = this; positionsOfInterest = new List <InterestingPosition>(); Voronoi voronoi = new Voronoi(1.0); List <Vector2> sites = new List <Vector2>(); bodies = new List <Body>(); Rand.SetSyncedSeed(ToolBox.StringToInt(seed)); #if CLIENT renderer = new LevelRenderer(this); backgroundColor = generationParams.BackgroundColor; float avgValue = (backgroundColor.R + backgroundColor.G + backgroundColor.G) / 3; GameMain.LightManager.AmbientLight = new Color(backgroundColor * (10.0f / avgValue), 1.0f); #endif SeaFloorTopPos = generationParams.SeaFloorDepth + generationParams.MountainHeightMax + generationParams.SeaFloorVariance; float minWidth = 6500.0f; if (Submarine.MainSub != null) { Rectangle dockedSubBorders = Submarine.MainSub.GetDockedBorders(); minWidth = Math.Max(minWidth, Math.Max(dockedSubBorders.Width, dockedSubBorders.Height)); } Rectangle pathBorders = borders; pathBorders.Inflate(-minWidth * 2, -minWidth * 2); startPosition = new Vector2( Rand.Range(minWidth, minWidth * 2, Rand.RandSync.Server), Rand.Range(borders.Height * 0.5f, borders.Height - minWidth * 2, Rand.RandSync.Server)); endPosition = new Vector2( borders.Width - Rand.Range(minWidth, minWidth * 2, Rand.RandSync.Server), Rand.Range(borders.Height * 0.5f, borders.Height - minWidth * 2, Rand.RandSync.Server)); //---------------------------------------------------------------------------------- //generate the initial nodes for the main path and smaller tunnels //---------------------------------------------------------------------------------- List <Vector2> pathNodes = new List <Vector2>(); pathNodes.Add(new Vector2(startPosition.X, borders.Height)); Vector2 nodeInterval = generationParams.MainPathNodeIntervalRange; for (float x = startPosition.X + nodeInterval.X; x < endPosition.X - nodeInterval.X; x += Rand.Range(nodeInterval.X, nodeInterval.Y, Rand.RandSync.Server)) { pathNodes.Add(new Vector2(x, Rand.Range(pathBorders.Y, pathBorders.Bottom, Rand.RandSync.Server))); } pathNodes.Add(new Vector2(endPosition.X, borders.Height)); if (pathNodes.Count <= 2) { pathNodes.Insert(1, borders.Center.ToVector2()); } GenerateTunnels(pathNodes, minWidth); //---------------------------------------------------------------------------------- //generate voronoi sites //---------------------------------------------------------------------------------- Vector2 siteInterval = generationParams.VoronoiSiteInterval; Vector2 siteVariance = generationParams.VoronoiSiteVariance; for (float x = siteInterval.X / 2; x < borders.Width; x += siteInterval.X) { for (float y = siteInterval.Y / 2; y < borders.Height; y += siteInterval.Y) { Vector2 site = new Vector2( x + Rand.Range(-siteVariance.X, siteVariance.X, Rand.RandSync.Server), y + Rand.Range(-siteVariance.Y, siteVariance.Y, Rand.RandSync.Server)); if (smallTunnels.Any(t => t.Any(node => Vector2.Distance(node, site) < siteInterval.Length()))) { //add some more sites around the small tunnels to generate more small voronoi cells if (x < borders.Width - siteInterval.X) { sites.Add(new Vector2(x, y) + Vector2.UnitX * siteInterval * 0.5f); } if (y < borders.Height - siteInterval.Y) { sites.Add(new Vector2(x, y) + Vector2.UnitY * siteInterval * 0.5f); } if (x < borders.Width - siteInterval.X && y < borders.Height - siteInterval.Y) { sites.Add(new Vector2(x, y) + Vector2.One * siteInterval * 0.5f); } } if (mirror) { site.X = borders.Width - site.X; } sites.Add(site); } } //---------------------------------------------------------------------------------- // construct the voronoi graph and cells //---------------------------------------------------------------------------------- Stopwatch sw2 = new Stopwatch(); sw2.Start(); List <GraphEdge> graphEdges = voronoi.MakeVoronoiGraph(sites, borders.Width, borders.Height); Debug.WriteLine("MakeVoronoiGraph: " + sw2.ElapsedMilliseconds + " ms"); sw2.Restart(); //construct voronoi cells based on the graph edges cells = CaveGenerator.GraphEdgesToCells(graphEdges, borders, GridCellSize, out cellGrid); Debug.WriteLine("find cells: " + sw2.ElapsedMilliseconds + " ms"); sw2.Restart(); //---------------------------------------------------------------------------------- // generate a path through the initial path nodes //---------------------------------------------------------------------------------- List <VoronoiCell> mainPath = CaveGenerator.GeneratePath(pathNodes, cells, cellGrid, GridCellSize, new Rectangle(pathBorders.X, pathBorders.Y, pathBorders.Width, borders.Height), 0.5f, mirror); for (int i = 2; i < mainPath.Count; i += 3) { positionsOfInterest.Add(new InterestingPosition(mainPath[i].Center, PositionType.MainPath)); } List <VoronoiCell> pathCells = new List <VoronoiCell>(mainPath); //make sure the path is wide enough to pass through EnlargeMainPath(pathCells, minWidth); foreach (InterestingPosition positionOfInterest in positionsOfInterest) { WayPoint wayPoint = new WayPoint(positionOfInterest.Position, SpawnType.Enemy, null); wayPoint.MoveWithLevel = true; } startPosition.X = pathCells[0].Center.X; //---------------------------------------------------------------------------------- // tunnels through the tunnel nodes //---------------------------------------------------------------------------------- foreach (List <Vector2> tunnel in smallTunnels) { if (tunnel.Count < 2) { continue; } //find the cell which the path starts from int startCellIndex = CaveGenerator.FindCellIndex(tunnel[0], cells, cellGrid, GridCellSize, 1); if (startCellIndex < 0) { continue; } //if it wasn't one of the cells in the main path, don't create a tunnel if (cells[startCellIndex].CellType != CellType.Path) { continue; } var newPathCells = CaveGenerator.GeneratePath(tunnel, cells, cellGrid, GridCellSize, pathBorders); positionsOfInterest.Add(new InterestingPosition(tunnel.Last(), PositionType.Cave)); if (tunnel.Count > 4) { positionsOfInterest.Add(new InterestingPosition(tunnel[tunnel.Count / 2], PositionType.Cave)); } pathCells.AddRange(newPathCells); } Debug.WriteLine("path: " + sw2.ElapsedMilliseconds + " ms"); sw2.Restart(); //---------------------------------------------------------------------------------- // remove unnecessary cells and create some holes at the bottom of the level //---------------------------------------------------------------------------------- cells = CleanCells(pathCells); pathCells.AddRange(CreateBottomHoles(generationParams.BottomHoleProbability, new Rectangle( (int)(borders.Width * 0.2f), 0, (int)(borders.Width * 0.6f), (int)(borders.Height * 0.8f)))); foreach (VoronoiCell cell in cells) { if (cell.Center.Y < borders.Height / 2) { continue; } cell.edges.ForEach(e => e.OutsideLevel = true); } //---------------------------------------------------------------------------------- // initialize the cells that are still left and insert them into the cell grid //---------------------------------------------------------------------------------- foreach (VoronoiCell cell in pathCells) { cell.edges.ForEach(e => e.OutsideLevel = false); cell.CellType = CellType.Path; cells.Remove(cell); } for (int x = 0; x < cellGrid.GetLength(0); x++) { for (int y = 0; y < cellGrid.GetLength(1); y++) { cellGrid[x, y].Clear(); } } foreach (VoronoiCell cell in cells) { int x = (int)Math.Floor(cell.Center.X / GridCellSize); int y = (int)Math.Floor(cell.Center.Y / GridCellSize); if (x < 0 || y < 0 || x >= cellGrid.GetLength(0) || y >= cellGrid.GetLength(1)) { continue; } cellGrid[x, y].Add(cell); } //---------------------------------------------------------------------------------- // create some ruins //---------------------------------------------------------------------------------- ruins = new List <Ruin>(); for (int i = 0; i < generationParams.RuinCount; i++) { GenerateRuin(mainPath); } //---------------------------------------------------------------------------------- // generate the bodies and rendered triangles of the cells //---------------------------------------------------------------------------------- startPosition.Y = borders.Height; endPosition.Y = borders.Height; List <VoronoiCell> cellsWithBody = new List <VoronoiCell>(cells); List <Vector2[]> triangles; bodies = CaveGenerator.GeneratePolygons(cellsWithBody, out triangles); #if CLIENT renderer.SetBodyVertices(CaveGenerator.GenerateRenderVerticeList(triangles).ToArray(), generationParams.WallColor); renderer.SetWallVertices(CaveGenerator.GenerateWallShapes(cells), generationParams.WallColor); #endif TopBarrier = BodyFactory.CreateEdge(GameMain.World, ConvertUnits.ToSimUnits(new Vector2(borders.X, 0)), ConvertUnits.ToSimUnits(new Vector2(borders.Right, 0))); TopBarrier.SetTransform(ConvertUnits.ToSimUnits(new Vector2(0.0f, borders.Height)), 0.0f); TopBarrier.BodyType = BodyType.Static; TopBarrier.CollisionCategories = Physics.CollisionLevel; bodies.Add(TopBarrier); GenerateSeaFloor(); backgroundSpriteManager.PlaceSprites(this, generationParams.BackgroundSpriteAmount); #if CLIENT backgroundCreatureManager.SpawnSprites(80); #endif foreach (VoronoiCell cell in cells) { foreach (GraphEdge edge in cell.edges) { edge.cell1 = null; edge.cell2 = null; edge.site1 = null; edge.site2 = null; } } //initialize MapEntities that aren't in any sub (e.g. items inside ruins) MapEntity.MapLoaded(null); Debug.WriteLine("Generatelevel: " + sw2.ElapsedMilliseconds + " ms"); sw2.Restart(); if (mirror) { Vector2 temp = startPosition; startPosition = endPosition; endPosition = temp; } Debug.WriteLine("**********************************************************************************"); Debug.WriteLine("Generated a map with " + sites.Count + " sites in " + sw.ElapsedMilliseconds + " ms"); Debug.WriteLine("Seed: " + seed); Debug.WriteLine("**********************************************************************************"); if (GameSettings.VerboseLogging) { DebugConsole.NewMessage("Generated level with the seed " + seed + " (type: " + generationParams.Name + ")", Color.White); } }
public override void UpdatePlacing(Camera cam) { Vector2 position = Submarine.MouseToWorldGrid(cam, Submarine.MainSub); if (PlayerInput.SecondaryMouseButtonClicked()) { selected = null; return; } var potentialContainer = MapEntity.GetPotentialContainer(position); if (!ResizeHorizontal && !ResizeVertical) { if (PlayerInput.PrimaryMouseButtonClicked()) { 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(); item.Submarine = Submarine.MainSub; if (PlayerInput.IsShiftDown()) { if (potentialContainer?.OwnInventory?.TryPutItem(item, Character.Controlled) ?? false) { SoundPlayer.PlayUISound(GUISoundType.PickItem); } } SubEditorScreen.StoreCommand(new AddOrDeleteCommand(new List <MapEntity> { item }, false)); placePosition = Vector2.Zero; return; } } else { Vector2 placeSize = size * Scale; if (placePosition == Vector2.Zero) { if (PlayerInput.PrimaryMouseButtonHeld()) { 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.PrimaryMouseButtonReleased()) { 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 (potentialContainer != null) { potentialContainer.IsHighlighted = true; } //if (PlayerInput.GetMouseState.RightButton == ButtonState.Pressed) selected = null; }
public override void OnMapLoaded() { if (!loadSub) { return; } SubmarineInfo info = new SubmarineInfo(Submarine.Info.FilePath, "", saveElement); if (!info.SubmarineElement.HasElements) { DebugConsole.ThrowError("Failed to load a linked submarine (empty XML element). The save file may be corrupted."); return; } if (!info.SubmarineElement.Elements().Any(e => e.Name.ToString().Equals("hull", StringComparison.OrdinalIgnoreCase))) { DebugConsole.ThrowError("Failed to load a linked submarine (the submarine contains no hulls)."); return; } IdRemap parentRemap = new IdRemap(Submarine.Info.SubmarineElement, Submarine.IdOffset); sub = Submarine.Load(info, false, parentRemap); sub.Info.SubmarineClass = Submarine.Info.SubmarineClass; IdRemap childRemap = new IdRemap(saveElement, sub.IdOffset); Vector2 worldPos = saveElement.GetAttributeVector2("worldpos", Vector2.Zero); if (worldPos != Vector2.Zero) { if (GameMain.GameSession != null && GameMain.GameSession.MirrorLevel) { worldPos.X = GameMain.GameSession.LevelData.Size.X - worldPos.X; } 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; ushort originalMyId = childRemap.GetOffsetId(originalMyPortID); myPort = (FindEntityByID(originalMyId) 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(applyEffects: false); myPort.DockingDir = 0; //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 * myPort.GetDir(linkedPort) : Vector2.UnitY * myPort.GetDir(linkedPort); offset *= myPort.DockedDistance; sub.SetPosition((linkedPort.Item.WorldPosition - portDiff) - offset); myPort.Dock(linkedPort); myPort.Lock(isNetworkMessage: true, applyEffects: false); } } 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.SetDamage(i, 0, createNetworkEvent: false); } } 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, forceUndockFromStaticSubmarines: false); sub.Submarine = Submarine; }
public static XElement Save(List <MapEntity> entities, string name, string description, bool hideInMenus = false) { XElement element = new XElement("ItemAssembly", new XAttribute("name", name), new XAttribute("description", description), new XAttribute("hideinmenus", hideInMenus)); //move the entities so that their "center of mass" is at {0,0} var assemblyEntities = MapEntity.CopyEntities(entities); //find wires and items that are contained inside another item //place them at {0,0} to prevent them from messing up the origin of the prefab and to hide them in preview List <MapEntity> disabledEntities = new List <MapEntity>(); foreach (MapEntity mapEntity in assemblyEntities) { if (mapEntity is Item item) { var wire = item.GetComponent <Wire>(); if (item.ParentInventory != null || (wire != null && wire.Connections.Any(c => c != null))) { item.SetTransform(Vector2.Zero, 0.0f); disabledEntities.Add(mapEntity); } } } float minX = int.MaxValue, maxX = int.MinValue; float minY = int.MaxValue, maxY = int.MinValue; foreach (MapEntity mapEntity in assemblyEntities) { if (disabledEntities.Contains(mapEntity)) { continue; } minX = Math.Min(minX, mapEntity.WorldRect.X); maxX = Math.Max(maxX, mapEntity.WorldRect.Right); minY = Math.Min(minY, mapEntity.WorldRect.Y - mapEntity.WorldRect.Height); maxY = Math.Max(maxY, mapEntity.WorldRect.Y); } Vector2 center = new Vector2((minX + maxX) / 2.0f, (minY + maxY) / 2.0f); if (Submarine.MainSub != null) { center -= Submarine.MainSub.HiddenSubPosition; } center.X -= center.X % Submarine.GridSize.X; center.Y -= center.Y % Submarine.GridSize.Y; MapEntity.SelectedList.Clear(); MapEntity.SelectedList.AddRange(assemblyEntities); foreach (MapEntity mapEntity in assemblyEntities) { mapEntity.Move(-center); mapEntity.Submarine = Submarine.MainSub; var entityElement = mapEntity.Save(element); if (disabledEntities.Contains(mapEntity)) { entityElement.Add(new XAttribute("hideinassemblypreview", "true")); } } return(element); }
public override void OnMapLoaded() { if (!loadSub) { return; } SubmarineInfo info = new SubmarineInfo(Submarine.Info.FilePath, "", saveElement); if (!info.SubmarineElement.HasElements) { DebugConsole.ThrowError("Failed to load a linked submarine (empty XML element). The save file may be corrupted."); return; } 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 * myPort.GetDir(linkedPort) : Vector2.UnitY * myPort.GetDir(linkedPort); 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; }
public static void SelectEntity(MapEntity entity) { DeselectAll(); selectedList.Add(entity); }
public override void OnMapLoaded() { if (!loadSub) { return; } sub = Submarine.Load(saveElement, 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) { return; } 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) { myPort.Undock(); 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); } sub.SetPosition(sub.WorldPosition - Submarine.WorldPosition); sub.Submarine = Submarine; }
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("editcharacter", "", (string[] args) => { GameMain.CharacterEditorScreen.Select(); })); commands.Add(new Command("editparticles", "", (string[] args) => { GameMain.ParticleEditorScreen.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() }); })); 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); })); 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); })); commands.Add(new Command("tutorial", "", (string[] args) => { TutorialMode.StartTutorial(Tutorials.TutorialType.TutorialTypes[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.ToggleCharacterMode(); } 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); } } } })); 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); })); 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("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); })); #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)); } } })); #endif 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("config.xml"); 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.txt")) { System.IO.File.Delete("crashreport.txt"); NewMessage("Deleted crashreport.txt", Color.Green); } if (!System.IO.File.Exists("Content/Map/TutorialSub.sub")) { ThrowError("TutorialSub.sub not found!"); } })); }
/// <summary> /// Update the selection logic in submarine editor /// </summary> public static void UpdateSelecting(Camera cam) { if (resizing) { if (selectedList.Count == 0) { resizing = false; } return; } foreach (MapEntity e in mapEntityList) { e.isHighlighted = false; } if (DisableSelect) { DisableSelect = false; return; } if (GUIComponent.MouseOn != null || !PlayerInput.MouseInsideWindow) { if (highlightedListBox == null || (GUIComponent.MouseOn != highlightedListBox && !highlightedListBox.IsParentOf(GUIComponent.MouseOn))) { UpdateHighlightedListBox(null); return; } } if (MapEntityPrefab.Selected != null) { selectionPos = Vector2.Zero; selectedList.Clear(); return; } if (PlayerInput.KeyDown(Keys.Delete)) { selectedList.ForEach(e => e.Remove()); selectedList.Clear(); } if (PlayerInput.KeyDown(Keys.LeftControl) || PlayerInput.KeyDown(Keys.RightControl)) { if (PlayerInput.GetKeyboardState.IsKeyDown(Keys.C) && PlayerInput.GetOldKeyboardState.IsKeyUp(Keys.C)) { CopyEntities(selectedList); } else if (PlayerInput.GetKeyboardState.IsKeyDown(Keys.X) && PlayerInput.GetOldKeyboardState.IsKeyUp(Keys.X)) { CopyEntities(selectedList); selectedList.ForEach(e => e.Remove()); selectedList.Clear(); } else if (copiedList.Count > 0 && PlayerInput.GetKeyboardState.IsKeyDown(Keys.V) && PlayerInput.GetOldKeyboardState.IsKeyUp(Keys.V)) { var clones = Clone(copiedList); Vector2 center = Vector2.Zero; clones.ForEach(c => center += c.WorldPosition); center = Submarine.VectorToWorldGrid(center / clones.Count); Vector2 moveAmount = Submarine.VectorToWorldGrid(cam.WorldViewCenter - center); selectedList = new List <MapEntity>(clones); foreach (MapEntity clone in selectedList) { clone.Move(moveAmount); clone.Submarine = Submarine.MainSub; } } } Vector2 position = cam.ScreenToWorld(PlayerInput.MousePosition); MapEntity highLightedEntity = null; if (startMovingPos == Vector2.Zero) { List <MapEntity> highlightedEntities = new List <MapEntity>(); if (highlightedListBox != null && highlightedListBox.IsParentOf(GUIComponent.MouseOn)) { highLightedEntity = GUIComponent.MouseOn.UserData as MapEntity; } else { foreach (MapEntity e in mapEntityList) { if (!e.SelectableInEditor) { continue; } if (e.IsMouseOn(position)) { int i = 0; while (i < highlightedEntities.Count && e.Sprite != null && (highlightedEntities[i].Sprite == null || highlightedEntities[i].Sprite.Depth < e.Sprite.Depth)) { i++; } highlightedEntities.Insert(i, e); if (i == 0) { highLightedEntity = e; } } } if (PlayerInput.MouseSpeed.LengthSquared() > 10) { highlightTimer = 0.0f; } else { bool mouseNearHighlightBox = false; if (highlightedListBox != null) { Rectangle expandedRect = highlightedListBox.Rect; expandedRect.Inflate(20, 20); mouseNearHighlightBox = expandedRect.Contains(PlayerInput.MousePosition); if (!mouseNearHighlightBox) { highlightedListBox = null; } } highlightTimer += (float)Timing.Step; if (highlightTimer > 1.0f) { if (!mouseNearHighlightBox) { UpdateHighlightedListBox(highlightedEntities); highlightTimer = 0.0f; } } } } if (highLightedEntity != null) { highLightedEntity.isHighlighted = true; } } Vector2 nudgeAmount = Vector2.Zero; if (PlayerInput.KeyHit(Keys.Up)) { nudgeAmount.Y = 1f; } if (PlayerInput.KeyHit(Keys.Down)) { nudgeAmount.Y = -1f; } if (PlayerInput.KeyHit(Keys.Left)) { nudgeAmount.X = -1f; } if (PlayerInput.KeyHit(Keys.Right)) { nudgeAmount.X = 1f; } if (nudgeAmount != Vector2.Zero) { foreach (MapEntity entityToNudge in selectedList) { entityToNudge.Move(nudgeAmount); } } //started moving selected entities if (startMovingPos != Vector2.Zero) { if (PlayerInput.LeftButtonReleased()) { //mouse released -> move the entities to the new position of the mouse Vector2 moveAmount = position - startMovingPos; moveAmount = Submarine.VectorToWorldGrid(moveAmount); if (moveAmount != Vector2.Zero) { //clone if (PlayerInput.KeyDown(Keys.LeftControl) || PlayerInput.KeyDown(Keys.RightControl)) { var clones = Clone(selectedList); selectedList = clones; selectedList.ForEach(c => c.Move(moveAmount)); } else // move { foreach (MapEntity e in selectedList) { e.Move(moveAmount); } } } startMovingPos = Vector2.Zero; } } //started dragging a "selection rectangle" else if (selectionPos != Vector2.Zero) { selectionSize.X = position.X - selectionPos.X; selectionSize.Y = selectionPos.Y - position.Y; List <MapEntity> newSelection = new List <MapEntity>();// FindSelectedEntities(selectionPos, selectionSize); if (Math.Abs(selectionSize.X) > Submarine.GridSize.X || Math.Abs(selectionSize.Y) > Submarine.GridSize.Y) { newSelection = FindSelectedEntities(selectionPos, selectionSize); } else { if (highLightedEntity != null) { newSelection.Add(highLightedEntity); } } if (PlayerInput.LeftButtonReleased()) { if (PlayerInput.KeyDown(Keys.LeftControl) || PlayerInput.KeyDown(Keys.RightControl)) { foreach (MapEntity e in newSelection) { if (selectedList.Contains(e)) { selectedList.Remove(e); } else { selectedList.Add(e); } } } else { selectedList = newSelection; } //select wire if both items it's connected to are selected var selectedItems = selectedList.Where(e => e is Item).Cast <Item>().ToList(); foreach (Item item in selectedItems) { if (item.Connections == null) { continue; } foreach (Connection c in item.Connections) { foreach (Wire w in c.Wires) { if (w == null || selectedList.Contains(w.Item)) { continue; } if (w.OtherConnection(c) != null && selectedList.Contains(w.OtherConnection(c).Item)) { selectedList.Add(w.Item); } } } } selectionPos = Vector2.Zero; selectionSize = Vector2.Zero; } } //default, not doing anything specific yet else { if (PlayerInput.LeftButtonHeld() && PlayerInput.KeyUp(Keys.Space) && (highlightedListBox == null || (GUIComponent.MouseOn != highlightedListBox && !highlightedListBox.IsParentOf(GUIComponent.MouseOn)))) { //if clicking a selected entity, start moving it foreach (MapEntity e in selectedList) { if (e.IsMouseOn(position)) { startMovingPos = position; } } selectionPos = position; } } }
/// <summary> /// Allows the game to run logic such as updating the world, /// checking for collisions, gathering input, and playing audio. /// </summary> public override void Update(double deltaTime) { #if CLIENT if (Character.Spied != null) { if ((PlayerInput.KeyDown(InputType.Up) || PlayerInput.KeyDown(InputType.Down) || PlayerInput.KeyDown(InputType.Left) || PlayerInput.KeyDown(InputType.Right)) && !DebugConsole.IsOpen) { if (GameMain.NetworkMember != null && !GameMain.NetworkMember.chatMsgBox.Selected) { if (Character.Controlled != null) { cam.Position = Character.Controlled.WorldPosition; } else { cam.Position = Character.Spied.WorldPosition; } Character.Spied = null; cam.UpdateTransform(true); } } } #endif #if DEBUG && CLIENT if (GameMain.GameSession != null && GameMain.GameSession.Level != null && GameMain.GameSession.Submarine != null && !DebugConsole.IsOpen && GUIComponent.KeyboardDispatcher.Subscriber == null) { /* * var closestSub = Submarine.FindClosest(cam.WorldViewCenter); * if (closestSub == null) closestSub = GameMain.GameSession.Submarine; * * Vector2 targetMovement = Vector2.Zero; * if (PlayerInput.KeyDown(Keys.I)) targetMovement.Y += 1.0f; * if (PlayerInput.KeyDown(Keys.K)) targetMovement.Y -= 1.0f; * if (PlayerInput.KeyDown(Keys.J)) targetMovement.X -= 1.0f; * if (PlayerInput.KeyDown(Keys.L)) targetMovement.X += 1.0f; * * if (targetMovement != Vector2.Zero) * closestSub.ApplyForce(targetMovement * closestSub.SubBody.Body.Mass * 100.0f); */ } #endif #if CLIENT GameMain.NilModProfiler.SWMapEntityUpdate.Start(); #endif foreach (MapEntity e in MapEntity.mapEntityList) { e.IsHighlighted = false; } #if CLIENT GameMain.NilModProfiler.SWMapEntityUpdate.Stop(); if (GameMain.GameSession != null) { GameMain.NilModProfiler.SWGameSessionUpdate.Start(); GameMain.GameSession.Update((float)deltaTime); GameMain.NilModProfiler.RecordGameSessionUpdate(); } GameMain.NilModProfiler.SWParticleManager.Start(); GameMain.ParticleManager.Update((float)deltaTime); GameMain.NilModProfiler.RecordParticleManager(); GameMain.NilModProfiler.SWLightManager.Start(); GameMain.LightManager.Update((float)deltaTime); GameMain.NilModProfiler.RecordLightManager(); #endif if (Level.Loaded != null) { #if CLIENT GameMain.NilModProfiler.SWLevelUpdate.Start(); #endif Level.Loaded.Update((float)deltaTime, cam); #if CLIENT GameMain.NilModProfiler.RecordLevelUpdate(); #endif } #if CLIENT if (Character.Controlled != null && Character.Controlled.SelectedConstruction != null && Character.Controlled.CanInteractWith(Character.Controlled.SelectedConstruction)) { Character.Controlled.SelectedConstruction.UpdateHUD(cam, Character.Controlled); } GameMain.NilModProfiler.SWCharacterUpdate.Start(); #endif Character.UpdateAll((float)deltaTime, cam); #if CLIENT //NilMod spy Code if (Character.Spied != null) { Character.ViewSpied((float)deltaTime, Cam, true); Lights.LightManager.ViewTarget = Character.Spied; CharacterHUD.Update((float)deltaTime, Character.Spied); foreach (HUDProgressBar progressBar in Character.Spied.HUDProgressBars.Values) { progressBar.Update((float)deltaTime); } foreach (var pb in Character.Spied.HUDProgressBars) { if (pb.Value.FadeTimer <= 0.0f) { Character.Spied.HUDProgressBars.Remove(pb.Key); } } } GameMain.NilModProfiler.SWCharacterUpdate.Stop(); GameMain.NilModProfiler.RecordCharacterUpdate(); GameMain.NilModProfiler.SWStatusEffect.Start(); #endif StatusEffect.UpdateAll((float)deltaTime); #if CLIENT GameMain.NilModProfiler.RecordStatusEffect(); if ((Character.Controlled != null && Lights.LightManager.ViewTarget != null) || (Character.Spied != null && Lights.LightManager.ViewTarget != null)) { cam.TargetPos = Lights.LightManager.ViewTarget.WorldPosition; } #endif cam.MoveCamera((float)deltaTime); #if CLIENT GameMain.NilModProfiler.SWSetTransforms.Start(); #endif foreach (Submarine sub in Submarine.Loaded) { sub.SetPrevTransform(sub.Position); } foreach (PhysicsBody pb in PhysicsBody.List) { pb.SetPrevTransform(pb.SimPosition, pb.Rotation); } #if CLIENT GameMain.NilModProfiler.RecordSetTransforms(); GameMain.NilModProfiler.SWMapEntityUpdate.Start(); #endif MapEntity.UpdateAll((float)deltaTime, cam); #if CLIENT GameMain.NilModProfiler.RecordMapEntityUpdate(); GameMain.NilModProfiler.SWCharacterAnimUpdate.Start(); #endif Character.UpdateAnimAll((float)deltaTime); #if CLIENT GameMain.NilModProfiler.RecordCharacterAnimUpdate(); GameMain.NilModProfiler.SWRagdollUpdate.Start(); #endif Ragdoll.UpdateAll((float)deltaTime, cam); #if CLIENT GameMain.NilModProfiler.RecordRagdollUpdate(); GameMain.NilModProfiler.SWSubmarineUpdate.Start(); #endif foreach (Submarine sub in Submarine.Loaded) { sub.Update((float)deltaTime); } #if CLIENT GameMain.NilModProfiler.RecordSubmarineUpdate(); GameMain.NilModProfiler.SWCharacterUpdate.Start(); #endif #if CLIENT GameMain.NilModProfiler.RecordCharacterUpdate(); GameMain.NilModProfiler.SWPhysicsWorldStep.Start(); #endif GameMain.World.Step((float)deltaTime); #if CLIENT GameMain.NilModProfiler.RecordPhysicsWorldStep(); if (!PlayerInput.LeftButtonHeld()) { Inventory.draggingSlot = null; Inventory.draggingItem = null; } #endif }
public void Load(bool unloadPrevious, XElement submarineElement = null) { if (unloadPrevious) { Unload(); } Loading = true; if (submarineElement == null) { XDocument doc = OpenFile(filePath); if (doc == null || doc.Root == null) { return; } submarineElement = doc.Root; } Description = submarineElement.GetAttributeString("description", ""); Enum.TryParse(submarineElement.GetAttributeString("tags", ""), out tags); //place the sub above the top of the level HiddenSubPosition = HiddenSubStartPosition; if (GameMain.GameSession != null && GameMain.GameSession.Level != null) { HiddenSubPosition += Vector2.UnitY * GameMain.GameSession.Level.Size.Y; } foreach (Submarine sub in Submarine.loaded) { HiddenSubPosition += Vector2.UnitY * (sub.Borders.Height + 5000.0f); } IdOffset = 0; foreach (MapEntity me in MapEntity.mapEntityList) { IdOffset = Math.Max(IdOffset, me.ID); } foreach (XElement element in submarineElement.Elements()) { string typeName = element.Name.ToString(); Type t; try { t = Type.GetType("Barotrauma." + typeName, true, true); if (t == null) { DebugConsole.ThrowError("Error in " + filePath + "! Could not find a entity of the type \"" + typeName + "\"."); continue; } } catch (Exception e) { DebugConsole.ThrowError("Error in " + filePath + "! Could not find a entity of the type \"" + typeName + "\".", e); continue; } try { MethodInfo loadMethod = t.GetMethod("Load"); loadMethod.Invoke(t, new object[] { element, this }); } catch (Exception e) { DebugConsole.ThrowError("Could not find the method \"Load\" in " + t + ".", e); } } Vector2 center = Vector2.Zero; var matchingHulls = Hull.hullList.FindAll(h => h.Submarine == this); if (matchingHulls.Any()) { Vector2 topLeft = new Vector2(matchingHulls[0].Rect.X, matchingHulls[0].Rect.Y); Vector2 bottomRight = new Vector2(matchingHulls[0].Rect.X, matchingHulls[0].Rect.Y); foreach (Hull hull in matchingHulls) { if (hull.Rect.X < topLeft.X) { topLeft.X = hull.Rect.X; } if (hull.Rect.Y > topLeft.Y) { topLeft.Y = hull.Rect.Y; } if (hull.Rect.Right > bottomRight.X) { bottomRight.X = hull.Rect.Right; } if (hull.Rect.Y - hull.Rect.Height < bottomRight.Y) { bottomRight.Y = hull.Rect.Y - hull.Rect.Height; } } center = (topLeft + bottomRight) / 2.0f; center.X -= center.X % GridSize.X; center.Y -= center.Y % GridSize.Y; if (center != Vector2.Zero) { foreach (Item item in Item.ItemList) { if (item.Submarine != this) { continue; } var wire = item.GetComponent <Items.Components.Wire>(); if (wire != null) { wire.MoveNodes(-center); } } for (int i = 0; i < MapEntity.mapEntityList.Count; i++) { if (MapEntity.mapEntityList[i].Submarine != this) { continue; } MapEntity.mapEntityList[i].Move(-center); } } } subBody = new SubmarineBody(this); subBody.SetPosition(HiddenSubPosition); loaded.Add(this); if (entityGrid != null) { Hull.EntityGrids.Remove(entityGrid); entityGrid = null; } entityGrid = Hull.GenerateEntityGrid(this); for (int i = 0; i < MapEntity.mapEntityList.Count; i++) { if (MapEntity.mapEntityList[i].Submarine != this) { continue; } MapEntity.mapEntityList[i].Move(HiddenSubPosition); } Loading = false; MapEntity.MapLoaded(this); //WayPoint.GenerateSubWaypoints(); #if CLIENT GameMain.LightManager.OnMapLoaded(); #endif ID = (ushort)(ushort.MaxValue - Submarine.loaded.IndexOf(this)); }