using Barotrauma.Extensions; using Barotrauma.Items.Components; using Microsoft.Xna.Framework; using System; using System.Collections.Generic; using System.Linq; namespace Barotrauma { partial class TestGameMode : GameMode { public Action OnRoundEnd; public bool SpawnOutpost; public OutpostGenerationParams OutpostParams; public LocationType OutpostType; public EventPrefab TriggeredEvent; private List scriptedEvent; private GUIButton createEventButton; public LevelGenerationParams BackgroundParams { get; private set; } public Vector2 WaterParticleOffset; public override void Start() { base.Start(); CrewManager.InitSinglePlayerRound(); foreach (Submarine submarine in Submarine.Loaded) { submarine.NeutralizeBallast(); switch (submarine.Info.Type) { case SubmarineType.Outpost: case SubmarineType.OutpostModule: case SubmarineType.Wreck: case SubmarineType.BeaconStation: //normally the body would be made static during level generation, //but in the test mode we load the outpost/wreck/beacon as if it was a normal sub and need to do this manually submarine.PhysicsBody.BodyType = FarseerPhysics.BodyType.Static; if (submarine.Info.ShouldBeRuin) { submarine.Info.Type = SubmarineType.Ruin; } submarine.TeamID = submarine.Info.IsOutpost ? CharacterTeamType.FriendlyNPC : CharacterTeamType.None; break; } } if (SpawnOutpost) { GenerateOutpost(Submarine.MainSub); } if (TriggeredEvent != null) { scriptedEvent = new List { TriggeredEvent.CreateInstance(GameMain.GameSession.EventManager.RandomSeed) }; GameMain.GameSession.EventManager.PinnedEvent = scriptedEvent.Last(); createEventButton = new GUIButton(new RectTransform(new Point(128, 64), GUI.Canvas, Anchor.TopCenter) { ScreenSpaceOffset = new Point(0, 32) }, TextManager.Get("create")) { OnClicked = delegate { scriptedEvent.Add(TriggeredEvent.CreateInstance(GameMain.GameSession.EventManager.RandomSeed)); GameMain.GameSession.EventManager.PinnedEvent = scriptedEvent.Last(); return true; } }; } if (Level.Loaded == null) { BackgroundParams ??= LevelGenerationParams.LevelParams.Where(lp => !lp.AllowedBiomeIdentifiers.Contains("endzone")).GetRandom(Rand.RandSync.Unsynced); GameMain.LightManager.AmbientLight = BackgroundParams.AmbientLightColor; } } public override void AddToGUIUpdateList() { base.AddToGUIUpdateList(); createEventButton?.AddToGUIUpdateList(); } public override void End(CampaignMode.TransitionType transitionType = CampaignMode.TransitionType.None) { GameMain.GameSession.EventManager.PinnedEvent = null; OnRoundEnd?.Invoke(); } public override void Update(float deltaTime) { base.Update(deltaTime); if (scriptedEvent != null) { foreach (Event sEvent in scriptedEvent.Where(sEvent => !sEvent.IsFinished)) { sEvent.Update(deltaTime); } } BackgroundParams?.UpdateWaterParticleOffset(ref WaterParticleOffset, BackgroundParams.WaterParticleVelocity, deltaTime); } private void GenerateOutpost(Submarine submarine) { Submarine outpost = OutpostGenerator.Generate(OutpostParams ?? OutpostGenerationParams.OutpostParams.GetRandomUnsynced(), OutpostType ?? LocationType.Prefabs.GetRandomUnsynced()); outpost.SetPosition(Vector2.Zero); 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 == outpost) { 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, outpost.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; Vector2 spawnPos = (outPostPort.Item.WorldPosition - portDiff) - Vector2.UnitY * outPostPort.DockedDistance; submarine.SetPosition(spawnPos); myPort.Dock(outPostPort); myPort.Lock(true); } if (Character.Controlled != null) { Character.Controlled.TeleportTo(outpost.GetWaypoints(false).GetRandomUnsynced(point => point.SpawnType == SpawnType.Human).WorldPosition); } } } }