From 296c5a14edc764620ba4aef17579872ce52cffd5 Mon Sep 17 00:00:00 2001 From: Regalis Date: Thu, 23 Jun 2016 18:23:20 +0300 Subject: [PATCH] - host can respawn - respawn info texts - camera clamped to the the upper edge of the level - fixed submarinebody being generated from all walls (and not just the ones belonging to that specific sub) --- Subsurface/Content/Items/Engine/engine.xml | 2 +- Subsurface/Source/Camera.cs | 21 +-- .../Characters/AI/IndoorsSteeringManager.cs | 3 +- .../Source/Characters/AI/SteeringPath.cs | 5 + Subsurface/Source/Items/Components/Door.cs | 19 +- Subsurface/Source/Map/Levels/Level.cs | 12 +- .../Source/Map/Levels/Ruins/RuinGenerator.cs | 2 + Subsurface/Source/Map/SubmarineBody.cs | 10 +- Subsurface/Source/Networking/GameClient.cs | 22 ++- Subsurface/Source/Networking/GameServer.cs | 16 +- .../Source/Networking/RespawnManager.cs | 164 +++++++++++++----- Subsurface/Source/Screens/GameScreen.cs | 2 +- 12 files changed, 204 insertions(+), 74 deletions(-) diff --git a/Subsurface/Content/Items/Engine/engine.xml b/Subsurface/Content/Items/Engine/engine.xml index 0df9c95e3..c7739754e 100644 --- a/Subsurface/Content/Items/Engine/engine.xml +++ b/Subsurface/Content/Items/Engine/engine.xml @@ -44,7 +44,7 @@ - + diff --git a/Subsurface/Source/Camera.cs b/Subsurface/Source/Camera.cs index e073d267c..7a3ab5361 100644 --- a/Subsurface/Source/Camera.cs +++ b/Subsurface/Source/Camera.cs @@ -125,17 +125,11 @@ namespace Barotrauma public void Translate(Vector2 amount) { position += amount; + } public void UpdateTransform(bool interpolate = true, bool clampPos = false) { - - if (clampPos && Level.Loaded != null) - { - position.Y -= Math.Max(worldView.Y - Level.Loaded.Size.Y, 0.0f); - } - - Vector2 interpolatedPosition = interpolate ? Physics.Interpolate(prevPosition, position) : position; float interpolatedZoom = interpolate ? Physics.Interpolate(prevZoom, zoom) : zoom; @@ -143,6 +137,13 @@ namespace Barotrauma worldView.X = (int)(interpolatedPosition.X - worldView.Width / 2.0); worldView.Y = (int)(interpolatedPosition.Y + worldView.Height / 2.0); + + if (Level.Loaded != null && clampPos) + { + position.Y -= Math.Max(worldView.Y - Level.Loaded.Size.Y, 0.0f); + interpolatedPosition.Y -= Math.Max(worldView.Y - Level.Loaded.Size.Y, 0.0f); + } + transform = Matrix.CreateTranslation( new Vector3(-interpolatedPosition.X, interpolatedPosition.Y, 0)) * Matrix.CreateScale(new Vector3(interpolatedZoom, interpolatedZoom, 1)) * @@ -216,14 +217,14 @@ namespace Barotrauma Vector2 diff = (targetPos + offset) - position; - moveCam = diff / MoveSmoothness; + moveCam = diff / MoveSmoothness; } shakeTargetPosition = Rand.Vector(Shake); shakePosition = Vector2.Lerp(shakePosition, shakeTargetPosition, 0.5f); - Shake = MathHelper.Lerp(Shake, 0.0f, deltaTime*2.0f); + Shake = MathHelper.Lerp(Shake, 0.0f, deltaTime * 2.0f); - Translate(moveCam+shakePosition); + Translate(moveCam + shakePosition); } public Vector2 Position diff --git a/Subsurface/Source/Characters/AI/IndoorsSteeringManager.cs b/Subsurface/Source/Characters/AI/IndoorsSteeringManager.cs index cf76785eb..d8107f9d5 100644 --- a/Subsurface/Source/Characters/AI/IndoorsSteeringManager.cs +++ b/Subsurface/Source/Characters/AI/IndoorsSteeringManager.cs @@ -105,9 +105,8 @@ namespace Barotrauma { if (currentPath == null) return Vector2.Zero; - if (currentPath.CurrentIndex == currentPath.Nodes.Count) + if (currentPath.Finished) { - Vector2 pos2 = host.SimPosition; if (character != null && character.Submarine == null && CurrentPath.Nodes.Last().Submarine != null) { diff --git a/Subsurface/Source/Characters/AI/SteeringPath.cs b/Subsurface/Source/Characters/AI/SteeringPath.cs index 671421195..2a98ac366 100644 --- a/Subsurface/Source/Characters/AI/SteeringPath.cs +++ b/Subsurface/Source/Characters/AI/SteeringPath.cs @@ -70,6 +70,11 @@ namespace Barotrauma } } + public bool Finished + { + get { return currentIndex >= nodes.Count; } + } + public void SkipToNextNode() { currentIndex++; diff --git a/Subsurface/Source/Items/Components/Door.cs b/Subsurface/Source/Items/Components/Door.cs index f9c33c541..ba75e1999 100644 --- a/Subsurface/Source/Items/Components/Door.cs +++ b/Subsurface/Source/Items/Components/Door.cs @@ -444,28 +444,31 @@ namespace Barotrauma.Items.Components if (connection.Name=="toggle") { - SetState(!isOpen, false); + SetState(!isOpen, false, true); } else if (connection.Name == "set_state") { - SetState(signal != "0", false); + SetState(signal != "0", false, true); } - - item.NewComponentEvent(this, false, true); } - private void SetState(bool state, bool isNetWorkMessage) + public void SetState(bool open, bool isNetworkMessage, bool sendNetworkMessage = false) { - if (GameMain.Client != null && !isNetWorkMessage) return; + if (GameMain.Client != null && !isNetworkMessage) return; - if (isStuck || isOpen == state) return; + if (isStuck || isOpen == open) return; PlaySound(ActionType.OnUse, item.WorldPosition); - isOpen = state; + isOpen = open; //opening a partially stuck door makes it less stuck if (isOpen) stuck = MathHelper.Clamp(stuck - 30.0f, 0.0f, 100.0f); + + if (sendNetworkMessage) + { + item.NewComponentEvent(this, false, true); + } } public override bool FillNetworkData(Networking.NetworkEventType type, Lidgren.Network.NetBuffer message) diff --git a/Subsurface/Source/Map/Levels/Level.cs b/Subsurface/Source/Map/Levels/Level.cs index 8a34933fa..5516f9ed2 100644 --- a/Subsurface/Source/Map/Levels/Level.cs +++ b/Subsurface/Source/Map/Levels/Level.cs @@ -17,6 +17,8 @@ namespace Barotrauma class Level { + public const float ShaftHeight = 1000.0f; + public static Level Loaded { get { return loaded; } @@ -56,7 +58,7 @@ namespace Barotrauma private WrappingWall[,] wrappingWalls; - private float shaftHeight; + //private float shaftHeight; //List bodies; private List cells; @@ -121,7 +123,7 @@ namespace Barotrauma { get { return backgroundColor; } } - + public Level(string seed, float difficulty, int width, int height, int siteInterval) { this.seed = seed; @@ -513,7 +515,7 @@ namespace Barotrauma ShaftBodies = new Body[2]; for (int i = 0; i < 2; i++) { - ShaftBodies[i] = BodyFactory.CreateRectangle(GameMain.World, 200.0f, 10.0f, 5.0f); + ShaftBodies[i] = BodyFactory.CreateRectangle(GameMain.World, 200.0f, ConvertUnits.ToSimUnits(ShaftHeight), 5.0f); ShaftBodies[i].BodyType = BodyType.Static; ShaftBodies[i].CollisionCategories = Physics.CollisionLevel; @@ -585,7 +587,7 @@ namespace Barotrauma { List wayPoints = new List(); - var newWaypoint = new WayPoint(new Rectangle((int)pathCells[0].Center.X, (int)(borders.Height + shaftHeight), 10, 10), null); + var newWaypoint = new WayPoint(new Rectangle((int)pathCells[0].Center.X, borders.Height, 10, 10), null); newWaypoint.MoveWithLevel = true; wayPoints.Add(newWaypoint); @@ -625,7 +627,7 @@ namespace Barotrauma //prevWaypoint = newWaypoint; } - newWaypoint = new WayPoint(new Rectangle((int)pathCells[pathCells.Count - 1].Center.X, (int)(borders.Height + shaftHeight), 10, 10), null); + newWaypoint = new WayPoint(new Rectangle((int)pathCells[pathCells.Count - 1].Center.X, borders.Height, 10, 10), null); newWaypoint.MoveWithLevel = true; wayPoints.Add(newWaypoint); diff --git a/Subsurface/Source/Map/Levels/Ruins/RuinGenerator.cs b/Subsurface/Source/Map/Levels/Ruins/RuinGenerator.cs index cf4c1e67f..832339281 100644 --- a/Subsurface/Source/Map/Levels/Ruins/RuinGenerator.cs +++ b/Subsurface/Source/Map/Levels/Ruins/RuinGenerator.cs @@ -319,9 +319,11 @@ namespace Barotrauma.RuinGeneration (int)((wall.B.X - wall.A.X) + radius*2.0f), (int)((wall.B.Y - wall.A.Y) + radius*2.0f)); + //cut a section off from both ends of a horizontal wall to get nicer looking corners if (wall.A.Y == wall.B.Y) { rect.Inflate(-32, 0); + if (rect.Width < Submarine.GridSize.X) continue; } var structure = new Structure(rect, structurePrefab.Prefab as StructurePrefab, null); diff --git a/Subsurface/Source/Map/SubmarineBody.cs b/Subsurface/Source/Map/SubmarineBody.cs index 0d0b354a0..1cc21f166 100644 --- a/Subsurface/Source/Map/SubmarineBody.cs +++ b/Subsurface/Source/Map/SubmarineBody.cs @@ -114,6 +114,8 @@ namespace Barotrauma foreach (Structure wall in Structure.WallList) { + if (wall.Submarine != submarine) continue; + Rectangle rect = wall.Rect; FixtureFactory.AttachRectangle( ConvertUnits.ToSimUnits(rect.Width), @@ -241,7 +243,11 @@ namespace Barotrauma ForceTranslate(moveAmount); - if (submarine == Submarine.MainSub) GameMain.GameScreen.Cam.UpdateTransform(false); + if ((Character.Controlled != null && Character.Controlled.Submarine == submarine) || + (Character.Controlled == null && Submarine.GetClosest(GameMain.GameScreen.Cam.WorldViewCenter) == submarine)) + { + GameMain.GameScreen.Cam.UpdateTransform(false); + } submarine.SetPrevTransform(submarine.Position); submarine.UpdateTransform(); @@ -296,7 +302,7 @@ namespace Barotrauma if (Character.Controlled != null) Character.Controlled.CursorPosition += amount; if ((Character.Controlled != null && Character.Controlled.Submarine == submarine) || - Submarine.GetClosest(GameMain.GameScreen.Cam.WorldViewCenter) == submarine) + (Character.Controlled == null && Submarine.GetClosest(GameMain.GameScreen.Cam.WorldViewCenter) == submarine)) { GameMain.GameScreen.Cam.Position += amount; if (GameMain.GameScreen.Cam.TargetPos != Vector2.Zero) GameMain.GameScreen.Cam.TargetPos += amount; diff --git a/Subsurface/Source/Networking/GameClient.cs b/Subsurface/Source/Networking/GameClient.cs index 2d401dd9b..bfc5100d6 100644 --- a/Subsurface/Source/Networking/GameClient.cs +++ b/Subsurface/Source/Networking/GameClient.cs @@ -413,6 +413,11 @@ namespace Barotrauma.Networking reliableChannel.Update(deltaTime); + if (gameStarted && respawnManager != null) + { + respawnManager.Update(deltaTime); + } + if (updateTimer > DateTime.Now) return; if (myCharacter != null) @@ -730,6 +735,8 @@ namespace Barotrauma.Networking GameMain.GameScreen.Cam.TargetPos = Vector2.Zero; GameMain.LightManager.LosEnabled = false; + respawnManager = null; + float endPreviewLength = 10.0f; if (Screen.Selected == GameMain.GameScreen) @@ -779,11 +786,6 @@ namespace Barotrauma.Networking if (fileStreamReceiver != null && (fileStreamReceiver.Status == FileTransferStatus.Receiving || fileStreamReceiver.Status == FileTransferStatus.NotStarted)) { - //Vector2 pos = Screen.Selected == GameMain.NetLobbyScreen ? - // new Vector2(GameMain.NetLobbyScreen.SubList.Rect.X, GameMain.NetLobbyScreen.SubList.Rect.Bottom+5) : new Vector2(GameMain.GraphicsWidth / 2 - 200, 10); - - - Vector2 pos = new Vector2(GameMain.GraphicsWidth / 2 - 130, GameMain.NetLobbyScreen.InfoFrame.Rect.Y / 2 - 15); GUI.DrawString(spriteBatch, @@ -804,6 +806,16 @@ namespace Barotrauma.Networking } } + if (respawnManager != null && respawnManager.CurrentState == RespawnManager.State.Waiting && + myCharacter != null && myCharacter.IsDead) + { + GUI.DrawString(spriteBatch, + new Vector2(GameMain.GraphicsWidth - 300.0f, 20), + "Respawning in " + (int)respawnManager.RespawnTimer + " s", + Color.White, null, 0, GUI.SmallFont); + } + + if (!GameMain.DebugDraw) return; int width = 200, height = 300; diff --git a/Subsurface/Source/Networking/GameServer.cs b/Subsurface/Source/Networking/GameServer.cs index 5251d4705..392234741 100644 --- a/Subsurface/Source/Networking/GameServer.cs +++ b/Subsurface/Source/Networking/GameServer.cs @@ -850,6 +850,10 @@ namespace Barotrauma.Networking //save "normal" events again existingEvents = new List(NetworkEvent.Events); } + + yield return new WaitForSeconds(0.1f); + + sender.inGame = true; yield return CoroutineStatus.Success; } @@ -1102,6 +1106,8 @@ namespace Barotrauma.Networking GameMain.GameScreen.Cam.TargetPos = Vector2.Zero; GameMain.LightManager.LosEnabled = false; + respawnManager = null; + gameStarted = false; if (connectedClients.Count > 0) @@ -1144,7 +1150,7 @@ namespace Barotrauma.Networking } - public void RespawnClients() + public void SendRespawnManagerMsg() { NetOutgoingMessage msg = server.CreateMessage(); respawnManager.WriteNetworkEvent(msg); @@ -1342,6 +1348,14 @@ namespace Barotrauma.Networking log.LogFrame.Draw(spriteBatch); } + if (respawnManager != null && respawnManager.CurrentState == RespawnManager.State.Waiting && respawnManager.CountdownStarted) + { + GUI.DrawString(spriteBatch, + new Vector2(GameMain.GraphicsWidth - 500.0f, 20), + "Respawning in " + (int)respawnManager.RespawnTimer + " s", + Color.White, null, 0, GUI.SmallFont); + } + if (!ShowNetStats) return; int width = 200, height = 300; diff --git a/Subsurface/Source/Networking/RespawnManager.cs b/Subsurface/Source/Networking/RespawnManager.cs index 8d4be8c2d..1b5a4d2f5 100644 --- a/Subsurface/Source/Networking/RespawnManager.cs +++ b/Subsurface/Source/Networking/RespawnManager.cs @@ -16,7 +16,7 @@ namespace Barotrauma.Networking const float RespawnInterval = 20.0f; - enum State + public enum State { Waiting, Transporting, @@ -31,6 +31,22 @@ namespace Barotrauma.Networking private Steering shuttleSteering; private List shuttleDoors; + public float RespawnTimer + { + get { return respawnTimer; } + } + + public bool CountdownStarted + { + get; + private set; + } + + public State CurrentState + { + get { return state; } + } + private float respawnTimer, shuttleReturnTimer; public RespawnManager(NetworkMember server) @@ -85,42 +101,49 @@ namespace Barotrauma.Networking private void UpdateWaiting(float deltaTime) { var server = networkMember as GameServer; - if (server == null) return; + if (server == null) + { + if (CountdownStarted) + { + respawnTimer = Math.Max(0.0f, respawnTimer - deltaTime); + } + return; + } respawnShuttle.Velocity = Vector2.Zero; shuttleSteering.AutoPilot = false; shuttleSteering.MaintainPos = false; - if (GetClientsToRespawn().Count < MinCharactersToRespawn) return; + int characterToRespawnCount = GetClientsToRespawn().Count; + if (server.Character != null && server.Character.IsDead) characterToRespawnCount++; - if (respawnTimer % 10.0f < 5.0f && (respawnTimer - deltaTime) % 10.0f > 5.0f) - { - string time = respawnTimer <= 60.0f ? - (int)respawnTimer + " seconds" : - (int)Math.Floor(respawnTimer / 60.0f) + " minutes"; + CountdownStarted = characterToRespawnCount >= MinCharactersToRespawn; - server.SendChatMessage("Transportation shuttle dispatching in " + time, ChatMessageType.Server); - } + if (!CountdownStarted) return; respawnTimer -= deltaTime; if (respawnTimer <= 0.0f) { - Respawn(); - respawnTimer = RespawnInterval; - state = State.Transporting; + + Respawn(); } } private void UpdateTransporting(float deltaTime) { + var server = networkMember as GameServer; + if (server == null) return; + if (Character.CharacterList.Any(c => c.Submarine == respawnShuttle && !c.IsDead)) return; shuttleReturnTimer += deltaTime; if (shuttleReturnTimer > 10.0f) { state = State.Returning; + + server.SendRespawnManagerMsg(); shuttleReturnTimer = 0.0f; } } @@ -134,14 +157,31 @@ namespace Barotrauma.Networking shuttleSteering.AutoPilot = true; shuttleSteering.MaintainPos = false; - shuttleDoors.ForEach(s => s.IsOpen = false); - - if (shuttleSteering.SteeringPath != null && shuttleSteering.SteeringPath.CurrentIndex == shuttleSteering.SteeringPath.Nodes.Count-1) + foreach (Door door in shuttleDoors) + { + if (door.IsOpen) door.SetState(false, false, true); + } + + var server = networkMember as GameServer; + if (server == null) return; + + //shuttle has returned if the path has been traversed or the shuttle is close enough to the exit + if (shuttleSteering.SteeringPath != null && shuttleSteering.SteeringPath.Finished + || (respawnShuttle.WorldPosition.Y + respawnShuttle.Borders.Y > Level.Loaded.StartPosition.Y - Level.ShaftHeight && + Math.Abs(Level.Loaded.StartPosition.X - respawnShuttle.WorldPosition.X) < 1000.0f)) { CoroutineManager.StartCoroutine( ForceShuttleToPos(new Vector2(Level.Loaded.StartPosition.X, Level.Loaded.Size.Y + 1000.0f), 100.0f)); + + if (GameMain.GameSession != null && GameMain.GameSession.Map != null) + { + string msg = "The transportation shuttle has returned to " + GameMain.GameSession.Map.SelectedLocation; + server.SendChatMessage(ChatMessage.Create("", msg, ChatMessageType.Server, null), server.ConnectedClients); + } + state = State.Waiting; + server.SendRespawnManagerMsg(); } shuttleReturnTimer = 0.0f; @@ -153,13 +193,15 @@ namespace Barotrauma.Networking var server = networkMember as GameServer; if (server == null) return; + state = State.Transporting; + ResetShuttlePos(); - server.SendChatMessage("Transportation shuttle dispatched"); + server.SendChatMessage(ChatMessage.Create("", "Transportation shuttle dispatched", ChatMessageType.Server, null), server.ConnectedClients); - server.RespawnClients(); + server.SendRespawnManagerMsg(); - CoroutineManager.StartCoroutine(ForceShuttleToPos(Level.Loaded.StartPosition, 100.0f)); + CoroutineManager.StartCoroutine(ForceShuttleToPos(Level.Loaded.StartPosition - Vector2.UnitY * Level.ShaftHeight, 100.0f)); } private IEnumerable ForceShuttleToPos(Vector2 position, float speed) @@ -171,15 +213,18 @@ namespace Barotrauma.Networking Vector2 displayVel = Vector2.Normalize(position - respawnShuttle.WorldPosition) * speed; respawnShuttle.SubBody.Body.LinearVelocity = ConvertUnits.ToSimUnits(displayVel); yield return CoroutineStatus.Running; + + if (respawnShuttle.SubBody == null) yield return CoroutineStatus.Success; } respawnShuttle.SubBody.Body.RestoreCollisionWith(Level.Loaded.ShaftBodies[0]); + yield return CoroutineStatus.Success; } private void ResetShuttlePos() { - respawnShuttle.SetPosition(new Vector2(Level.Loaded.StartPosition.X, Level.Loaded.Size.Y + 1000.0f)); + respawnShuttle.SetPosition(new Vector2(Level.Loaded.StartPosition.X, Level.Loaded.Size.Y + respawnShuttle.Borders.Height)); respawnShuttle.Velocity = Vector2.Zero; } @@ -187,40 +232,81 @@ namespace Barotrauma.Networking public void WriteNetworkEvent(NetOutgoingMessage msg) { var server = networkMember as GameServer; - var clients = GetClientsToRespawn(); - + msg.Write((byte)PacketTypes.Respawn); - var waypoints = WayPoint.SelectCrewSpawnPoints(clients.Select(c => c.characterInfo).ToList(), respawnShuttle); + msg.WriteRangedInteger(0, Enum.GetNames(typeof(State)).Length, (int)state); - msg.Write((byte)clients.Count); - for (int i = 0; i < clients.Count; i++) + switch (state) { - msg.Write((byte)clients[i].ID); - clients[i].Character = Character.Create(clients[i].characterInfo, waypoints[i].WorldPosition, true, false); - clients[i].Character.GiveJobItems(waypoints[i]); + case State.Transporting: + var clients = GetClientsToRespawn(); - GameMain.GameSession.CrewManager.characters.Add(clients[i].Character); + List characterInfos = clients.Select(c => c.characterInfo).ToList(); + if (server.Character != null && server.Character.IsDead) characterInfos.Add(server.CharacterInfo); - server.WriteCharacterData(msg, clients[i].Character.Name, clients[i].Character); + var waypoints = WayPoint.SelectCrewSpawnPoints(characterInfos, respawnShuttle); + + msg.Write((byte)characterInfos.Count); + for (int i = 0; i < characterInfos.Count; i++) + { + var character = Character.Create(characterInfos[i], waypoints[i].WorldPosition, true, false); + + if (i < clients.Count) + { + msg.Write((byte)clients[i].ID); + } + else + { + msg.Write((byte)0); + server.Character = character; + Character.Controlled = character; + } + + character.GiveJobItems(waypoints[i]); + + GameMain.GameSession.CrewManager.characters.Add(character); + + server.WriteCharacterData(msg, character.Name, character); + } + + break; + case State.Waiting: + msg.Write(respawnTimer); + break; } } public void ReadNetworkEvent(NetIncomingMessage inc) { - ResetShuttlePos(); + state = (State)inc.ReadRangedInteger(0, Enum.GetNames(typeof(State)).Length); - var client = networkMember as GameClient; - - int clientCount = inc.ReadByte(); - for (int i = 0; i