diff --git a/Subsurface/Barotrauma.csproj b/Subsurface/Barotrauma.csproj
index 48b0a5c18..c9d2e5a0b 100644
--- a/Subsurface/Barotrauma.csproj
+++ b/Subsurface/Barotrauma.csproj
@@ -104,7 +104,8 @@
-
+
+
@@ -905,6 +906,21 @@
PreserveNewest
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
PreserveNewest
@@ -932,6 +948,9 @@
PreserveNewest
+
+ PreserveNewest
+
PreserveNewest
diff --git a/Subsurface/Content/Map/dustparticles.png b/Subsurface/Content/Map/dustparticles.png
index a68587406..0f8efffb1 100644
Binary files a/Subsurface/Content/Map/dustparticles.png and b/Subsurface/Content/Map/dustparticles.png differ
diff --git a/Subsurface/Content/Sounds/Damage/creak1.ogg b/Subsurface/Content/Sounds/Damage/creak1.ogg
new file mode 100644
index 000000000..1b407a531
Binary files /dev/null and b/Subsurface/Content/Sounds/Damage/creak1.ogg differ
diff --git a/Subsurface/Content/Sounds/Damage/creak2.ogg b/Subsurface/Content/Sounds/Damage/creak2.ogg
new file mode 100644
index 000000000..519077568
Binary files /dev/null and b/Subsurface/Content/Sounds/Damage/creak2.ogg differ
diff --git a/Subsurface/Content/Sounds/Damage/creak3.ogg b/Subsurface/Content/Sounds/Damage/creak3.ogg
new file mode 100644
index 000000000..4ffbc42e1
Binary files /dev/null and b/Subsurface/Content/Sounds/Damage/creak3.ogg differ
diff --git a/Subsurface/Content/Sounds/Damage/creak4.ogg b/Subsurface/Content/Sounds/Damage/creak4.ogg
new file mode 100644
index 000000000..22df1ea74
Binary files /dev/null and b/Subsurface/Content/Sounds/Damage/creak4.ogg differ
diff --git a/Subsurface/Content/Sounds/Damage/creak5.ogg b/Subsurface/Content/Sounds/Damage/creak5.ogg
new file mode 100644
index 000000000..5a5a55d1d
Binary files /dev/null and b/Subsurface/Content/Sounds/Damage/creak5.ogg differ
diff --git a/Subsurface/Content/Sounds/Music/amb_JD_drone_clattering_machine.ogg b/Subsurface/Content/Sounds/Music/amb_JD_drone_clattering_machine.ogg
new file mode 100644
index 000000000..799bb38c4
Binary files /dev/null and b/Subsurface/Content/Sounds/Music/amb_JD_drone_clattering_machine.ogg differ
diff --git a/Subsurface/Content/Sounds/sounds.xml b/Subsurface/Content/Sounds/sounds.xml
index 95075bb76..4c6afb20b 100644
--- a/Subsurface/Content/Sounds/sounds.xml
+++ b/Subsurface/Content/Sounds/sounds.xml
@@ -28,7 +28,11 @@
-
+
+
+
+
+
@@ -36,4 +40,5 @@
+
\ No newline at end of file
diff --git a/Subsurface/Source/Characters/Character.cs b/Subsurface/Source/Characters/Character.cs
index 3040be6e6..fe7777f30 100644
--- a/Subsurface/Source/Characters/Character.cs
+++ b/Subsurface/Source/Characters/Character.cs
@@ -379,12 +379,15 @@ namespace Barotrauma
if (Info.PickedItemIDs.Any())
{
- foreach (ushort id in Info.PickedItemIDs)
+ for (ushort i = 0; i < Info.PickedItemIDs.Count; i++ )
{
- Item item = FindEntityByID(id) as Item;
+ if (i == 0) continue;
+
+ Item item = FindEntityByID(Info.PickedItemIDs[i]) as Item;
if (item == null) continue;
- item.Pick(this);
+ item.Pick(this, true, true, true);
+ inventory.TryPutItem(item, i, false);
}
}
diff --git a/Subsurface/Source/Characters/CharacterInfo.cs b/Subsurface/Source/Characters/CharacterInfo.cs
index edbd7df7e..1ee00a41e 100644
--- a/Subsurface/Source/Characters/CharacterInfo.cs
+++ b/Subsurface/Source/Characters/CharacterInfo.cs
@@ -1,4 +1,5 @@
using Microsoft.Xna.Framework;
+using Microsoft.Xna.Framework.Graphics;
using System;
using System.Collections.Generic;
using System.Xml.Linq;
@@ -186,25 +187,27 @@ namespace Barotrauma
{
GUIImage image = new GUIImage(new Rectangle(0,0,30,30), HeadSprite, Alignment.TopLeft, frame);
+ SpriteFont font = frame.Rect.Width<280 ? GUI.SmallFont : GUI.Font;
+
int x = 0, y = 0;
- new GUITextBlock(new Rectangle(x+80, y, 200, 20), Name, GUI.Style, frame);
+ new GUITextBlock(new Rectangle(x+60, y, 200, 20), Name, GUI.Style, frame, font);
y += 20;
if (Job!=null)
{
- new GUITextBlock(new Rectangle(x+80, y, 200, 20), Job.Name, GUI.Style, frame);
+ new GUITextBlock(new Rectangle(x + 60, y, 200, 20), Job.Name, GUI.Style, frame, font);
y += 30;
var skills = Job.Skills;
skills.Sort((s1, s2) => -s1.Level.CompareTo(s2.Level));
- new GUITextBlock(new Rectangle(x, y, 200, 20), "Skills:", GUI.Style, frame);
+ new GUITextBlock(new Rectangle(x, y, 200, 20), "Skills:", GUI.Style, frame, font);
y += 20;
foreach (Skill skill in skills)
{
Color textColor = Color.White * (0.5f + skill.Level/200.0f);
- new GUITextBlock(new Rectangle(x+20, y, 200, 20), skill.Name, Color.Transparent, textColor, Alignment.Left, GUI.Style, frame);
- new GUITextBlock(new Rectangle(x + 20, y, 200, 20), skill.Level.ToString(), Color.Transparent, textColor, Alignment.Right, GUI.Style, frame);
+ new GUITextBlock(new Rectangle(x, y, 200, 20), skill.Name, Color.Transparent, textColor, Alignment.Left, GUI.Style, frame).Font = font;
+ new GUITextBlock(new Rectangle(x, y, 200, 20), skill.Level.ToString(), Color.Transparent, textColor, Alignment.Right, GUI.Style, frame).Font = font;
y += 20;
}
}
@@ -218,8 +221,7 @@ namespace Barotrauma
pickedItems.Clear();
foreach (Item item in Character.Inventory.items)
{
- if (item == null) continue;
- pickedItems.Add(item.ID);
+ pickedItems.Add(item == null ? (ushort)0 : item.ID);
}
}
diff --git a/Subsurface/Source/Events/Quests/SalvageQuest.cs b/Subsurface/Source/Events/Quests/SalvageQuest.cs
index 82f01a3ed..d7a3ae9ba 100644
--- a/Subsurface/Source/Events/Quests/SalvageQuest.cs
+++ b/Subsurface/Source/Events/Quests/SalvageQuest.cs
@@ -37,10 +37,35 @@ namespace Barotrauma
public override void Start(Level level)
{
- Vector2 position = level.PositionsOfInterest[Rand.Int(level.PositionsOfInterest.Count, false)];
+ Vector2 position = Vector2.Zero;
+
+ int tries = 0;
+ do
+ {
+ Vector2 tryPos = level.PositionsOfInterest[Rand.Int(level.PositionsOfInterest.Count, false)];
+
+ if (Submarine.PickBody(
+ tryPos + level.Position,
+ tryPos + level.Position - Vector2.UnitY*level.Size.Y,
+ null, Physics.CollisionLevel) != null)
+ {
+ position = tryPos;
+ break;
+ }
+
+ tries++;
+
+ if (tries==10)
+ {
+ position = level.EndPosition - Vector2.UnitY*300.0f;
+ }
+
+ } while (tries < 10);
+
item = new Item(itemPrefab, position + level.Position);
item.MoveWithLevel = true;
+ item.body.FarseerBody.GravityScale = 0.5f;
//item.MoveWithLevel = true;
}
diff --git a/Subsurface/Source/GUI/GUIComponent.cs b/Subsurface/Source/GUI/GUIComponent.cs
index 618f489ff..1bf6fe961 100644
--- a/Subsurface/Source/GUI/GUIComponent.cs
+++ b/Subsurface/Source/GUI/GUIComponent.cs
@@ -370,12 +370,12 @@ namespace Barotrauma
public GUIComponent FindChild(object userData)
{
- foreach (GUIComponent child in children)
- {
- if (child.userData == userData) return child;
- }
+ return children.FirstOrDefault(c => c.userData == userData);
+ }
- return null;
+ public List FindChildren(object userData)
+ {
+ return children .FindAll(c => c.userData == userData);
}
public virtual void ClearChildren()
diff --git a/Subsurface/Source/GUI/GUITextBlock.cs b/Subsurface/Source/GUI/GUITextBlock.cs
index 24050692c..8d9b9d95b 100644
--- a/Subsurface/Source/GUI/GUITextBlock.cs
+++ b/Subsurface/Source/GUI/GUITextBlock.cs
@@ -76,7 +76,13 @@ namespace Barotrauma
{
get { return caretPos; }
}
-
+
+ public GUITextBlock(Rectangle rect, string text, GUIStyle style, GUIComponent parent, SpriteFont font)
+ : this(rect, text, style, Alignment.TopLeft, Alignment.TopLeft, parent, false, font)
+ {
+ }
+
+
public GUITextBlock(Rectangle rect, string text, GUIStyle style, GUIComponent parent = null, bool wrap = false)
: this(rect, text, style, Alignment.TopLeft, Alignment.TopLeft, parent, wrap)
{
diff --git a/Subsurface/Source/GameSession/GameModes/TutorialMode.cs b/Subsurface/Source/GameSession/GameModes/TutorialMode.cs
index d8b926c31..45618a090 100644
--- a/Subsurface/Source/GameSession/GameModes/TutorialMode.cs
+++ b/Subsurface/Source/GameSession/GameModes/TutorialMode.cs
@@ -160,7 +160,7 @@ namespace Barotrauma
infoBox = CreateInfoFrame("The amount of power generated by the reactor should be kept close to the amount of power consumed by the devices in the submarine. "
+"If there isn't enough power, devices won't function properly (or at all), and if there's too much power, some devices may be damaged."
- +" Try to raise the temperature of the reactor close to 3000 degrees by adjusting the fission and cooling rates.");
+ +" Try to raise the temperature of the reactor close to 3000 degrees by adjusting the fission and cooling rates.", true);
while (Math.Abs(reactor.Temperature-3000.0f) > 100.0f)
{
diff --git a/Subsurface/Source/Items/Components/Machines/Radar.cs b/Subsurface/Source/Items/Components/Machines/Radar.cs
index 9560934b9..0b5311f0f 100644
--- a/Subsurface/Source/Items/Components/Machines/Radar.cs
+++ b/Subsurface/Source/Items/Components/Machines/Radar.cs
@@ -47,7 +47,7 @@ namespace Barotrauma.Items.Components
{
base.Update(deltaTime, cam);
- if (voltage>=minVoltage)
+ if (voltage >= minVoltage)
{
pingState = (pingState + deltaTime * 0.5f);
if (pingState>1.0f)
diff --git a/Subsurface/Source/Map/Levels/Level.cs b/Subsurface/Source/Map/Levels/Level.cs
index 7e8eaeab6..92ca9cdc4 100644
--- a/Subsurface/Source/Map/Levels/Level.cs
+++ b/Subsurface/Source/Map/Levels/Level.cs
@@ -65,6 +65,11 @@ namespace Barotrauma
private set;
}
+ public Vector2 Size
+ {
+ get { return new Vector2(borders.Width, borders.Height); }
+ }
+
public Vector2 EndPosition
{
get { return endPosition; }
@@ -277,7 +282,7 @@ namespace Barotrauma
var newPathCells = GeneratePath(new List { start, end }, cells, pathBorders, 0.0f, 0.8f, mirror);
- for (int n = 0; n < newPathCells.Count-5; n += 3)
+ for (int n = 0; n < newPathCells.Count; n += 5)
{
positionsOfInterest.Add(newPathCells[n].Center);
}
@@ -297,9 +302,13 @@ namespace Barotrauma
// GeneratePath(rand, tunnelStart, new Vector2(tunnelStart.X, borders.Height), cells, pathBorders, minWidth, 0.1f, mirror)
// );
//}
-
- cells = CleanCells(pathCells);
+ cells = CleanCells(pathCells);
+
+ pathCells.AddRange(CreateBottomHoles(1.0f, new Rectangle(
+ (int)(borders.Width * 0.2f), 0,
+ (int)(borders.Width * 0.6f), (int)(borders.Height * 0.3f))));
+
foreach (VoronoiCell cell in pathCells)
{
cells.Remove(cell);
@@ -344,6 +353,17 @@ namespace Barotrauma
}
}
+
+ for (int i = 0; i < 2; i++)
+ {
+ Body shaftBody = BodyFactory.CreateRectangle(GameMain.World, 100.0f, 10.0f, 5.0f);
+ shaftBody.BodyType = BodyType.Kinematic;
+ shaftBody.CollisionCategories = Physics.CollisionLevel;
+ shaftBody.SetTransform(ConvertUnits.ToSimUnits((i == 0) ? startPosition : endPosition), 0.0f);
+ shaftBody.SleepingAllowed = false;
+ bodies.Add(shaftBody);
+ }
+
foreach (VoronoiCell cell in cells)
{
foreach (GraphEdge edge in cell.edges)
@@ -381,6 +401,7 @@ namespace Barotrauma
//lower values will cause the path to "wander" more, higher will make it head straight to the end
wanderAmount = MathHelper.Clamp(wanderAmount, 0.0f, 1.0f);
+ List allowedEdges = new List();
List pathCells = new List();
VoronoiCell[] targetCells = new VoronoiCell[points.Count];
@@ -398,12 +419,21 @@ namespace Barotrauma
{
int edgeIndex = 0;
+ allowedEdges.Clear();
+ foreach (GraphEdge edge in currentCell.edges)
+ {
+ if (!limits.Contains(edge.AdjacentCell(currentCell).Center)) continue;
+
+ allowedEdges.Add(edge);
+ }
+
//steer towards target
- if (Rand.Range(0.0f, 1.0f, false) > wanderAmount)
+ if (Rand.Range(0.0f, 1.0f, false) > wanderAmount || allowedEdges.Count == 0)
{
for (int i = 0; i < currentCell.edges.Count; i++)
{
- if (!MathUtils.LinesIntersect(currentCell.Center, targetCells[currentTargetIndex].Center, currentCell.edges[i].point1, currentCell.edges[i].point2)) continue;
+ if (!MathUtils.LinesIntersect(currentCell.Center, targetCells[currentTargetIndex].Center,
+ currentCell.edges[i].point1, currentCell.edges[i].point2)) continue;
edgeIndex = i;
break;
}
@@ -411,24 +441,18 @@ namespace Barotrauma
//choose random edge (ignoring ones where the adjacent cell is outside limits)
else
{
- List allowedEdges = new List();
- foreach (GraphEdge edge in currentCell.edges)
- {
- if (!limits.Contains(edge.AdjacentCell(currentCell).Center)) continue;
- allowedEdges.Add(edge);
- }
- if (allowedEdges.Count==0)
- {
- edgeIndex = Rand.Int(currentCell.edges.Count, false);
- }
- else
- {
+ //if (allowedEdges.Count==0)
+ //{
+ // edgeIndex = Rand.Int(currentCell.edges.Count, false);
+ //}
+ //else
+ //{
edgeIndex = Rand.Int(allowedEdges.Count, false);
if (mirror && edgeIndex > 0) edgeIndex = allowedEdges.Count - edgeIndex;
edgeIndex = currentCell.edges.IndexOf(allowedEdges[edgeIndex]);
- }
+ //}
}
currentCell = currentCell.edges[edgeIndex].AdjacentCell(currentCell);
@@ -495,6 +519,26 @@ namespace Barotrauma
return pathCells;
}
+ private List CreateBottomHoles(float holeProbability, Rectangle limits)
+ {
+ List toBeRemoved = new List();
+ foreach (VoronoiCell cell in cells)
+ {
+ if (Rand.Range(0.0f, 1.0f, false) > holeProbability) continue;
+
+ if (!limits.Contains(cell.Center)) continue;
+
+ toBeRemoved.Add(cell);
+ }
+
+ return toBeRemoved;
+
+ //foreach (VoronoiCell cell in toBeRemoved)
+ //{
+ // cells.Remove(cell);
+ //}
+ }
+
private List GetTooCloseCells(List emptyCells, float minDistance)
{
List tooCloseCells = new List();
@@ -671,17 +715,7 @@ namespace Barotrauma
bodies.Add(edgeBody);
}
- for (int i = 0; i < 2; i++ )
- {
- Body shaftBody = BodyFactory.CreateRectangle(GameMain.World, 100.0f, 10.0f, 5.0f);
- shaftBody.BodyType = BodyType.Kinematic;
- shaftBody.CollisionCategories = Physics.CollisionLevel;
- shaftBody.SetTransform(ConvertUnits.ToSimUnits((i==0) ? startPosition : endPosition), 0.0f);
- shaftBody.SleepingAllowed = false;
- bodies.Add(shaftBody);
- }
-
- return verticeList.ToArray();
+ return verticeList.ToArray();
}
public void SetPosition(Vector2 pos)
@@ -918,7 +952,7 @@ namespace Barotrauma
for (int i = 0; i < 2; i++)
{
basicEffect.World = Matrix.CreateTranslation(new Vector3(Position + wrappingWalls[side, i].Offset, 0.0f)) * cam.ShaderTransform
- * Matrix.CreateOrthographic(GameMain.GraphicsWidth, GameMain.GraphicsHeight, -1, 1) * 0.5f;
+ * Matrix.CreateOrthographic(GameMain.GraphicsWidth, GameMain.GraphicsHeight, -1, 1) * 0.5f;
basicEffect.CurrentTechnique.Passes[0].Apply();
diff --git a/Subsurface/Source/Map/Levels/WrappingWall.cs b/Subsurface/Source/Map/Levels/WrappingWall.cs
index d7050abc5..d58fb1af8 100644
--- a/Subsurface/Source/Map/Levels/WrappingWall.cs
+++ b/Subsurface/Source/Map/Levels/WrappingWall.cs
@@ -1,4 +1,5 @@
-using Microsoft.Xna.Framework;
+using FarseerPhysics;
+using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.Collections.Generic;
@@ -12,7 +13,7 @@ namespace Barotrauma
class WrappingWall
{
- const float wallWidth = 10000.0f;
+ const float wallWidth = 20000.0f;
public VertexPositionTexture[] Vertices;
@@ -60,7 +61,7 @@ namespace Barotrauma
}
}
- Vector2 wallSectionSize = new Vector2(2000.0f, 2000.0f);
+ Vector2 wallSectionSize = new Vector2(2300.0f, 2300.0f);
Vector2 startPos = (dir < 0) ?
edgeCell.Center + Vector2.UnitX * wallWidth * dir :
edgeCell.Center + wallWidth * Vector2.UnitX * (dir - 1);
@@ -77,7 +78,7 @@ namespace Barotrauma
float normalizedDist = distFromEdge / (wallWidth / 2);
float variance = 1000.0f * normalizedDist;
- bottomVertices.Add(center + new Vector2(Rand.Range(-variance, variance, false), Rand.Range(-variance, variance, false)*5.0f));
+ bottomVertices.Add(center + new Vector2(Rand.Range(-variance, variance, false), Rand.Range(-variance, variance, false)*2.0f));
}
for (int i = 1; i < bottomVertices.Count; i++)
@@ -127,6 +128,22 @@ namespace Barotrauma
walls[0, 0] = walls[0, 1];
walls[0, 1] = temp;
}
+ else if (pos.X > walls[1, 1].midPos.X && walls[1,0].midPos.X < pos.X)
+ {
+ walls[1, 0].Shift(2);
+
+ var temp = walls[1, 0];
+ walls[1, 0] = walls[1, 1];
+ walls[1, 1] = temp;
+ }
+ else if (pos.X < walls[1, 0].midPos.X && walls[1, 1].midPos.X > pos.X && walls[1, 1].slot > 0)
+ {
+ walls[1, 1].Shift(-2);
+
+ var temp = walls[0, 0];
+ walls[1, 0] = walls[1, 1];
+ walls[1, 1] = temp;
+ }
}
public void Shift(int amount)
@@ -134,9 +151,11 @@ namespace Barotrauma
slot += amount;
Vector2 moveAmount = Vector2.UnitX * wallWidth * amount;
+
+ Vector2 simMoveAmount = ConvertUnits.ToSimUnits(moveAmount);
foreach (VoronoiCell cell in cells)
{
- cell.body.SetTransform(cell.body.Position + moveAmount, 0.0f);
+ cell.body.SetTransform(cell.body.Position + simMoveAmount, 0.0f);
}
midPos += moveAmount;
diff --git a/Subsurface/Source/Map/SubmarineHull.cs b/Subsurface/Source/Map/SubmarineHull.cs
index 5518b77ce..55d59e0c8 100644
--- a/Subsurface/Source/Map/SubmarineHull.cs
+++ b/Subsurface/Source/Map/SubmarineHull.cs
@@ -16,6 +16,9 @@ namespace Barotrauma
{
class SubmarineBody
{
+ const float DamageDepth = 0.0f;
+ const float PressureDamageMultiplier = 0.001f;
+
//structure damage = impact * damageMultiplier
const float DamageMultiplier = 50.0f;
@@ -27,6 +30,8 @@ namespace Barotrauma
private set;
}
+ private float depthDamageTimer;
+
private Submarine sub;
private Body body;
@@ -207,6 +212,8 @@ namespace Barotrauma
ApplyForce(totalForce);
+ UpdateDepthDamage(deltaTime);
+
//hullBodies[0].body.LinearVelocity = -hullBodies[0].body.Position;
//hullBody.SetTransform(Vector2.Zero , 0.0f);
@@ -240,6 +247,48 @@ namespace Barotrauma
Speed += force / mass;
}
+ private void UpdateDepthDamage(float deltaTime)
+ {
+ if (sub.Position.Y > DamageDepth) return;
+
+ float depth = DamageDepth - sub.Position.Y;
+ depth = Math.Max(depth, -40000.0f);
+
+ // float prevTimer = depthDamageTimer;
+
+ depthDamageTimer -= deltaTime*depth*PressureDamageMultiplier;
+
+ //if (prevTimer>5.0f && depthDamageTimer<=5.0f)
+ //{
+ // SoundPlayer.PlayDamageSound(DamageSoundType.Pressure, 50.0f,);
+ //}
+
+ if (depthDamageTimer > 0.0f) return;
+
+ Vector2 damagePos = Vector2.Zero;
+ if (Rand.Int(2)==0)
+ {
+ damagePos = new Vector2(
+ (Rand.Int(2) == 0) ? Borders.X : Borders.X+Borders.Width,
+ Rand.Range(Borders.Y - Borders.Height, Borders.Y));
+ }
+ else
+ {
+ damagePos = new Vector2(
+ Rand.Range(Borders.X, Borders.X + Borders.Width),
+ (Rand.Int(2) == 0) ? Borders.Y : Borders.Y - Borders.Height);
+ }
+
+ SoundPlayer.PlayDamageSound(DamageSoundType.Pressure, 50.0f, damagePos, 5000.0f);
+
+ GameMain.GameScreen.Cam.Shake = depth * PressureDamageMultiplier * 0.1f;
+
+ Explosion.RangedStructureDamage(damagePos, depth * PressureDamageMultiplier * 50.0f, depth * PressureDamageMultiplier);
+ //SoundPlayer.PlayDamageSound(DamageSoundType.StructureBlunt, Rand.Range(0.0f, 100.0f), damagePos, 5000.0f);
+
+ depthDamageTimer = 10.0f;
+ }
+
private void UpdateColliding()
{
if (body.Position.LengthSquared()<0.00001f) return;
diff --git a/Subsurface/Source/Map/WayPoint.cs b/Subsurface/Source/Map/WayPoint.cs
index 6ed255969..d86ad027b 100644
--- a/Subsurface/Source/Map/WayPoint.cs
+++ b/Subsurface/Source/Map/WayPoint.cs
@@ -226,7 +226,6 @@ namespace Barotrauma
//try to give the crew member a spawnpoint that hasn't been assigned to anyone and matches their job
for (int n = 0; n < unassignedWayPoints.Count; n++)
{
-
if (crew[i].Job.Prefab != unassignedWayPoints[n].assignedJob) continue;
assignedWayPoints[i] = unassignedWayPoints[n];
unassignedWayPoints.RemoveAt(n);
diff --git a/Subsurface/Source/Networking/GameClient.cs b/Subsurface/Source/Networking/GameClient.cs
index 2830a071d..54c918929 100644
--- a/Subsurface/Source/Networking/GameClient.cs
+++ b/Subsurface/Source/Networking/GameClient.cs
@@ -438,7 +438,12 @@ namespace Barotrauma.Networking
AddChatMessage(inc.ReadString(), ChatMessageType.Server);
Client disconnectedClient = otherClients.Find(c => c.ID == leavingID);
- if (disconnectedClient != null) GameMain.NetLobbyScreen.RemovePlayer(disconnectedClient.name);
+
+ if (disconnectedClient != null)
+ {
+ otherClients.Remove(disconnectedClient);
+ GameMain.NetLobbyScreen.RemovePlayer(disconnectedClient.name);
+ }
if (!gameStarted) return;
@@ -487,6 +492,9 @@ namespace Barotrauma.Networking
case (byte)PacketTypes.LatestMessageID:
reliableChannel.HandleLatestMessageID(inc);
break;
+ case (byte)PacketTypes.VoteStatus:
+ Voting.ReadData(inc);
+ break;
}
}
}
@@ -512,7 +520,7 @@ namespace Barotrauma.Networking
yield return CoroutineStatus.Success;
}
- if (!GameMain.NetLobbyScreen.TrySelectMap(mapName, mapHash))
+ if (!GameMain.NetLobbyScreen.TrySelectSub(mapName, mapHash))
{
yield return CoroutineStatus.Success;
}
@@ -522,7 +530,7 @@ namespace Barotrauma.Networking
Rand.SetSyncedSeed(seed);
//int gameModeIndex = inc.ReadInt32();
- GameMain.GameSession = new GameSession(GameMain.NetLobbyScreen.SelectedMap, "", gameMode);
+ GameMain.GameSession = new GameSession(GameMain.NetLobbyScreen.SelectedSub, "", gameMode);
yield return CoroutineStatus.Running;
@@ -637,6 +645,25 @@ namespace Barotrauma.Networking
GameMain.NetworkMember = null;
}
+ public void Vote(VoteType voteType, object userData)
+ {
+ NetOutgoingMessage msg = client.CreateMessage();
+ msg.Write((byte)PacketTypes.Vote);
+ msg.Write((byte)voteType);
+
+ switch (voteType)
+ {
+ case VoteType.Sub:
+ msg.Write(((Submarine)userData).Name);
+ client.SendMessage(msg, NetDeliveryMethod.ReliableUnordered);
+ break;
+ case VoteType.Mode:
+ msg.Write(((GameModePreset)userData).Name);
+ client.SendMessage(msg, NetDeliveryMethod.ReliableUnordered);
+ break;
+ }
+ }
+
public void SendCharacterData()
{
if (characterInfo == null) return;
diff --git a/Subsurface/Source/Networking/GameServer.cs b/Subsurface/Source/Networking/GameServer.cs
index 4f5918815..8fb56e9c9 100644
--- a/Subsurface/Source/Networking/GameServer.cs
+++ b/Subsurface/Source/Networking/GameServer.cs
@@ -223,7 +223,6 @@ namespace Barotrauma.Networking
connectedClients.Find(c => c.character != null && !c.character.IsDead)==null &&
(myCharacter == null || myCharacter.IsDead))
{
- AutoRestartTimer = 20.0f;
EndButtonHit(null, null);
UpdateNetLobby(null,null);
return;
@@ -484,6 +483,9 @@ namespace Barotrauma.Networking
case (byte)PacketTypes.LatestMessageID:
dataSender.ReliableChannel.HandleLatestMessageID(inc);
break;
+ case (byte)PacketTypes.Vote:
+ Voting.RegisterVote(inc, connectedClients);
+ break;
}
break;
case NetIncomingMessageType.WarningMessage:
@@ -674,7 +676,8 @@ namespace Barotrauma.Networking
public bool StartGameClicked(GUIButton button, object obj)
{
- Submarine selectedSub = GameMain.NetLobbyScreen.SelectedMap as Submarine;
+ Submarine selectedSub = Voting.AllowSubVoting ?
+ Voting.HighestVoted(VoteType.Sub, connectedClients) : GameMain.NetLobbyScreen.SelectedSub;
if (selectedSub == null)
{
@@ -695,7 +698,11 @@ namespace Barotrauma.Networking
int seed = DateTime.Now.Millisecond;
Rand.SetSyncedSeed(seed);
- GameMain.GameSession = new GameSession(selectedSub, "", GameMain.NetLobbyScreen.SelectedMode);
+
+ GameModePreset selectedMode = Voting.HighestVoted(VoteType.Mode, connectedClients);
+ if (selectedMode==null) selectedMode=GameMain.NetLobbyScreen.SelectedMode;
+
+ GameMain.GameSession = new GameSession(selectedSub, "", selectedMode);
GameMain.GameSession.StartShift(GameMain.NetLobbyScreen.LevelSeed);
yield return CoroutineStatus.Running;
@@ -747,10 +754,10 @@ namespace Barotrauma.Networking
msg.Write(GameMain.NetLobbyScreen.LevelSeed);
- msg.Write(GameMain.NetLobbyScreen.SelectedMap.Name);
- msg.Write(GameMain.NetLobbyScreen.SelectedMap.MD5Hash.Hash);
+ msg.Write(selectedSub.Name);
+ msg.Write(selectedSub.MD5Hash.Hash);
- msg.Write(GameMain.NetLobbyScreen.SelectedMode.Name);
+ msg.Write(selectedMode.Name);
//msg.Write(GameMain.NetLobbyScreen.GameDuration.TotalMinutes);
@@ -788,6 +795,8 @@ namespace Barotrauma.Networking
{
GameMain.GameSession.gameMode.End("Server admin has ended the round");
+ if (autoRestart) AutoRestartTimer = 20.0f;
+
return true;
}
@@ -1044,6 +1053,27 @@ namespace Barotrauma.Networking
}
+ public void UpdateVoteStatus()
+ {
+ if (server.Connections.Count == 0) return;
+
+ try
+ {
+ NetOutgoingMessage msg = server.CreateMessage();
+ msg.Write((byte)PacketTypes.VoteStatus);
+ Voting.WriteData(msg, connectedClients);
+
+ server.SendMessage(msg, server.Connections, NetDeliveryMethod.ReliableUnordered, 0);
+ }
+ catch (Exception e)
+ {
+#if DEBUG
+ DebugConsole.ThrowError("Failed to update vote status", e);
+#endif
+ }
+
+ }
+
public bool UpdateNetLobby(object obj)
{
return UpdateNetLobby(null, obj);
@@ -1051,14 +1081,13 @@ namespace Barotrauma.Networking
public bool UpdateNetLobby(GUIComponent component, object obj)
{
+ if (server.Connections.Count == 0) return true;
+
NetOutgoingMessage msg = server.CreateMessage();
msg.Write((byte)PacketTypes.UpdateNetLobby);
GameMain.NetLobbyScreen.WriteData(msg);
- if (server.Connections.Count > 0)
- {
- server.SendMessage(msg, server.Connections, NetDeliveryMethod.ReliableUnordered, 0);
- }
+ server.SendMessage(msg, server.Connections, NetDeliveryMethod.ReliableUnordered, 0);
return true;
}
@@ -1320,6 +1349,8 @@ namespace Barotrauma.Networking
public string version;
public bool inGame;
+ private object[] votes;
+
public List jobPreferences;
public JobPrefab assignedJob;
@@ -1337,8 +1368,20 @@ namespace Barotrauma.Networking
{
this.name = name;
this.ID = ID;
+
+ votes = new object[Enum.GetNames(typeof(VoteType)).Length];
jobPreferences = new List(JobPrefab.List.GetRange(0,3));
}
+
+ public object GetVote(VoteType voteType)
+ {
+ return votes[(int)voteType];
+ }
+
+ public void SetVote(VoteType voteType, object value)
+ {
+ votes[(int)voteType] = value;
+ }
}
}
diff --git a/Subsurface/Source/Screens/NetLobbySettings.cs b/Subsurface/Source/Networking/GameServerSettings.cs
similarity index 88%
rename from Subsurface/Source/Screens/NetLobbySettings.cs
rename to Subsurface/Source/Networking/GameServerSettings.cs
index 91b21bff6..bfc0e1f44 100644
--- a/Subsurface/Source/Screens/NetLobbySettings.cs
+++ b/Subsurface/Source/Networking/GameServerSettings.cs
@@ -20,7 +20,7 @@ namespace Barotrauma.Networking
private SelectionMode subSelectionMode, modeSelectionMode;
- private bool randomizeSeed;
+ private bool randomizeSeed = true;
private bool registeredToMaster;
@@ -108,6 +108,13 @@ namespace Barotrauma.Networking
((GUITickBox)otherTickBox).Selected = false;
}
+ Voting.AllowSubVoting = subSelectionMode == SelectionMode.Vote;
+
+ if (subSelectionMode==SelectionMode.Random)
+ {
+ GameMain.NetLobbyScreen.SubList.Select(Rand.Range(0, GameMain.NetLobbyScreen.SubList.CountChildren));
+ }
+
return true;
}
@@ -121,6 +128,13 @@ namespace Barotrauma.Networking
((GUITickBox)otherTickBox).Selected = false;
}
+ Voting.AllowModeVoting = modeSelectionMode == SelectionMode.Vote;
+
+ if (modeSelectionMode == SelectionMode.Random)
+ {
+ GameMain.NetLobbyScreen.ModeList.Select(Rand.Range(0, GameMain.NetLobbyScreen.ModeList.CountChildren));
+ }
+
return true;
}
diff --git a/Subsurface/Source/Networking/NetworkMember.cs b/Subsurface/Source/Networking/NetworkMember.cs
index af75c2428..830c289f0 100644
--- a/Subsurface/Source/Networking/NetworkMember.cs
+++ b/Subsurface/Source/Networking/NetworkMember.cs
@@ -30,10 +30,20 @@ namespace Barotrauma.Networking
Traitor,
+ Vote,
+ VoteStatus,
+
ResendRequest,
ReliableMessage,
- LatestMessageID
-
+ LatestMessageID
+ }
+
+ enum VoteType
+ {
+ Unknown,
+ Sub,
+ Mode,
+ EndRound
}
class NetworkMember
@@ -61,6 +71,8 @@ namespace Barotrauma.Networking
protected Character myCharacter;
protected CharacterInfo characterInfo;
+ public Voting Voting;
+
public Character Character
{
get { return myCharacter; }
@@ -113,6 +125,8 @@ namespace Barotrauma.Networking
crewButton = new GUIButton(new Rectangle(chatBox.Rect.Right-80, chatBox.Rect.Y-30, 80, 20), "Crew", GUI.Style, inGameHUD);
crewButton.OnClicked = ToggleCrewFrame;
+
+ Voting = new Voting();
}
protected void CreateCrewFrame(List crew)
diff --git a/Subsurface/Source/Screens/GameScreen.cs b/Subsurface/Source/Screens/GameScreen.cs
index fb6c3acf0..974e2bc18 100644
--- a/Subsurface/Source/Screens/GameScreen.cs
+++ b/Subsurface/Source/Screens/GameScreen.cs
@@ -78,7 +78,7 @@ namespace Barotrauma
if (PlayerInput.KeyDown(Keys.J)) targetMovement.X -= 1.0f;
if (PlayerInput.KeyDown(Keys.L)) targetMovement.X += 1.0f;
- GameMain.GameSession.Submarine.ApplyForce(targetMovement * 100000.0f);
+ GameMain.GameSession.Submarine.ApplyForce(targetMovement * 1000000.0f);
}
#endif
dustOffset -= Vector2.UnitY * 10.0f * (float)deltaTime;
@@ -213,11 +213,11 @@ namespace Barotrauma
viewRect.Y = -viewRect.Y;
float multiplier = 0.8f;
- for (int i = 1; i < 3; i++)
+ for (int i = 1; i < 4; i++)
{
spriteBatch.Draw(dustParticles, viewRect,
new Rectangle((int)((backgroundPos.X * multiplier)), (int)((-backgroundPos.Y * multiplier)), cam.WorldView.Width, cam.WorldView.Height),
- Color.LightGray * multiplier, 0.0f, Vector2.Zero, SpriteEffects.None, 1.0f-multiplier);
+ Color.White * multiplier, 0.0f, Vector2.Zero, SpriteEffects.None, 1.0f-multiplier);
multiplier -= 0.15f;
}
diff --git a/Subsurface/Source/Screens/LobbyScreen.cs b/Subsurface/Source/Screens/LobbyScreen.cs
index 947cf2b75..24d588624 100644
--- a/Subsurface/Source/Screens/LobbyScreen.cs
+++ b/Subsurface/Source/Screens/LobbyScreen.cs
@@ -58,14 +58,14 @@ namespace Barotrauma
{
Rectangle panelRect = new Rectangle(
40, 40,
- 180,
+ GameMain.GraphicsWidth < 1000 ? 140 : 180,
GameMain.GraphicsHeight - 80);
leftPanel = new GUIFrame(panelRect, GUI.Style);
- //leftPanel.Padding = GUI.style.smallPadding;
+ leftPanel.Padding = new Vector4(20.0f, 20.0f, 20.0f, 20.0f);
- new GUITextBlock(new Rectangle(0, 0, 200, 25),
- "asdfdasfasdf", Color.Transparent, Color.White, Alignment.Left, GUI.Style, leftPanel);
+ //new GUITextBlock(new Rectangle(0, 0, 200, 25),
+ // save, Color.Transparent, Color.White, Alignment.Left, GUI.Style, leftPanel);
GUITextBlock moneyText = new GUITextBlock(new Rectangle(0, 30, 200, 25),
"", Color.Transparent, Color.White, Alignment.Left, GUI.Style, leftPanel);
@@ -100,17 +100,18 @@ namespace Barotrauma
rightPanel = new GUIFrame[4];
rightPanel[(int)PanelTab.Crew] = new GUIFrame(panelRect, GUI.Style);
- //rightPanel[(int)PanelTab.Crew].Padding = GUI.style.smallPadding;
+ rightPanel[(int)PanelTab.Crew].Padding = new Vector4(20.0f, 20.0f, 20.0f, 20.0f);
new GUITextBlock(new Rectangle(0, 0, 200, 25), "Crew:", Color.Transparent, Color.White, Alignment.Left, GUI.Style, rightPanel[(int)PanelTab.Crew]);
- characterList = new GUIListBox(new Rectangle(0, 30, 300, 0), GUI.Style, rightPanel[(int)PanelTab.Crew]);
+ int crewColumnWidth = Math.Min(300, (panelRect.Width - 40) / 2);
+ characterList = new GUIListBox(new Rectangle(0, 30, crewColumnWidth, 0), GUI.Style, rightPanel[(int)PanelTab.Crew]);
characterList.OnSelected = SelectCharacter;
//---------------------------------------
rightPanel[(int)PanelTab.Map] = new GUIFrame(panelRect, GUI.Style);
- //rightPanel[(int)PanelTab.Map].Padding = GUI.style.smallPadding;
+ rightPanel[(int)PanelTab.Map].Padding = new Vector4(20.0f, 20.0f, 20.0f, 20.0f);
startButton = new GUIButton(new Rectangle(0, 0, 100, 30), "Start",
Alignment.BottomRight, GUI.Style, rightPanel[(int)PanelTab.Map]);
@@ -124,17 +125,20 @@ namespace Barotrauma
//---------------------------------------
rightPanel[(int)PanelTab.Store] = new GUIFrame(panelRect, GUI.Style);
+ rightPanel[(int)PanelTab.Store].Padding = new Vector4(20.0f, 20.0f, 20.0f, 20.0f);
- selectedItemList = new GUIListBox(new Rectangle(0, 0, 300, 400), Color.White * 0.7f, GUI.Style, rightPanel[(int)PanelTab.Store]);
+ int sellColumnWidth = (panelRect.Width - 40) / 2 - 20;
+
+ selectedItemList = new GUIListBox(new Rectangle(0, 0, sellColumnWidth, 400), Color.White * 0.7f, GUI.Style, rightPanel[(int)PanelTab.Store]);
selectedItemList.OnSelected = DeselectItem;
- var costText = new GUITextBlock(new Rectangle(0, 0, 200, 25), "Cost: ", GUI.Style, Alignment.BottomLeft, Alignment.TopLeft, rightPanel[(int)PanelTab.Store]);
+ var costText = new GUITextBlock(new Rectangle(0, 0, 100, 25), "Cost: ", GUI.Style, Alignment.BottomLeft, Alignment.TopLeft, rightPanel[(int)PanelTab.Store]);
costText.TextGetter = CostTextGetter;
- buyButton = new GUIButton(new Rectangle(150, 0, 100, 25), "Buy", Alignment.Bottom, GUI.Style, rightPanel[(int)PanelTab.Store]);
+ buyButton = new GUIButton(new Rectangle(sellColumnWidth+20, 0, 100, 25), "Buy", Alignment.Bottom, GUI.Style, rightPanel[(int)PanelTab.Store]);
buyButton.OnClicked = BuyItems;
- itemList = new GUIListBox(new Rectangle(0, 0, 300, 400), Color.White * 0.7f, Alignment.TopRight, GUI.Style, rightPanel[(int)PanelTab.Store]);
+ itemList = new GUIListBox(new Rectangle(0, 0, sellColumnWidth, 400), Color.White * 0.7f, Alignment.TopRight, GUI.Style, rightPanel[(int)PanelTab.Store]);
itemList.OnSelected = SelectItem;
foreach (MapEntityPrefab ep in MapEntityPrefab.list)
@@ -237,7 +241,7 @@ namespace Barotrauma
c.Name + " (" + c.Job.Name + ")", GUI.Style,
Alignment.Left,
Alignment.Left,
- characterList);
+ characterList, false, GameMain.GraphicsWidth<1000 ? GUI.SmallFont : GUI.Font);
textBlock.Padding = new Vector4(10.0f, 0.0f, 0.0f, 0.0f);
textBlock.UserData = c;
}
@@ -254,12 +258,15 @@ namespace Barotrauma
frame.HoverColor = Color.Gold * 0.2f;
frame.SelectedColor = Color.Gold * 0.5f;
+ SpriteFont font = listBox.Rect.Width < 280 ? GUI.SmallFont : GUI.Font;
+
GUITextBlock textBlock = new GUITextBlock(
new Rectangle(40, 0, 0, 25),
ep.Name,
Color.Transparent, Color.White,
Alignment.Left, Alignment.Left,
null, frame);
+ textBlock.Font = font;
textBlock.Padding = new Vector4(5.0f, 0.0f, 5.0f, 0.0f);
textBlock = new GUITextBlock(
@@ -267,6 +274,7 @@ namespace Barotrauma
ep.Price.ToString(),
null, null,
Alignment.TopRight, GUI.Style, textBlock);
+ textBlock.Font = font;
if (ep.sprite != null)
{
@@ -410,7 +418,7 @@ namespace Barotrauma
if (previewFrame == null || previewFrame.UserData != characterInfo)
{
- previewFrame = new GUIFrame(new Rectangle(350, 60, 300, 300),
+ previewFrame = new GUIFrame(new Rectangle(rightPanel[(int)PanelTab.Crew].Rect.Width/2, 60, Math.Min(300,rightPanel[(int)PanelTab.Crew].Rect.Width/2 - 40), 300),
new Color(0.0f, 0.0f, 0.0f, 0.8f),
Alignment.Top, GUI.Style, rightPanel[selectedRightPanel]);
previewFrame.Padding = new Vector4(20.0f, 20.0f, 20.0f, 20.0f);
diff --git a/Subsurface/Source/Screens/NetLobbyScreen.cs b/Subsurface/Source/Screens/NetLobbyScreen.cs
index c20f4216b..471b5bdfc 100644
--- a/Subsurface/Source/Screens/NetLobbyScreen.cs
+++ b/Subsurface/Source/Screens/NetLobbyScreen.cs
@@ -11,7 +11,7 @@ using System.Collections.Generic;
namespace Barotrauma
{
- class NetLobbyScreen : Screen
+ partial class NetLobbyScreen : Screen
{
private GUIFrame menu;
private GUIFrame infoFrame;
@@ -43,7 +43,17 @@ namespace Barotrauma
get { return subList; }
}
- public Submarine SelectedMap
+ public GUIListBox ModeList
+ {
+ get { return modeList; }
+ }
+
+ public GUIFrame InfoFrame
+ {
+ get { return infoFrame; }
+ }
+
+ public Submarine SelectedSub
{
get { return subList.SelectedData as Submarine; }
}
@@ -105,7 +115,7 @@ namespace Barotrauma
if (autoRestartTimer == 0.0f) return "";
return "Restarting in " + (int)autoRestartTimer;
}
-
+
public NetLobbyScreen()
{
int width = Math.Min(GameMain.GraphicsWidth - 80, 1500);
@@ -156,12 +166,16 @@ namespace Barotrauma
//submarine list ------------------------------------------------------------------
- int columnWidth = infoFrame.Rect.Width / 5 - 30;
+ int columnWidth = infoFrame.Rect.Width / 3 - 5;
int columnX = 0;
new GUITextBlock(new Rectangle(columnX, 120, columnWidth, 30), "Submarine:", GUI.Style, infoFrame);
subList = new GUIListBox(new Rectangle(columnX, 150, columnWidth, infoFrame.Rect.Height - 150 - 80), Color.White, GUI.Style, infoFrame);
- subList.OnSelected = SelectMap;
+ subList.OnSelected = VotableClicked;
+
+ var voteText = new GUITextBlock(new Rectangle(columnX, 120, columnWidth, 30), "Votes: ", GUI.Style, Alignment.TopLeft, Alignment.TopRight, infoFrame);
+ voteText.UserData = "subvotes";
+ voteText.Visible = false;
if (Submarine.SavedSubmarines.Count > 0)
{
@@ -188,8 +202,13 @@ namespace Barotrauma
new GUITextBlock(new Rectangle(columnX, 120, 0, 30), "Game mode: ", GUI.Style, infoFrame);
modeList = new GUIListBox(new Rectangle(columnX, 150, columnWidth, infoFrame.Rect.Height - 150 - 80), GUI.Style, infoFrame);
+ modeList.OnSelected = VotableClicked;
+ voteText = new GUITextBlock(new Rectangle(columnX, 120, columnWidth, 30), "Votes: ", GUI.Style, Alignment.TopLeft, Alignment.TopRight, infoFrame);
+ voteText.UserData = "modevotes";
+ voteText.Visible = false;
+
foreach (GameModePreset mode in GameModePreset.list)
{
if (mode.IsSinglePlayer) continue;
@@ -199,29 +218,31 @@ namespace Barotrauma
mode.Name, GUI.Style,
Alignment.Left, Alignment.Left,
modeList);
+ textBlock.ToolTip = mode.Description;
textBlock.Padding = new Vector4(10.0f, 0.0f, 0.0f, 0.0f);
textBlock.UserData = mode;
}
- columnX += columnWidth;
+
+ columnX += columnWidth + 20;
//gamemode description ------------------------------------------------------------------
- var modeDescription = new GUITextBlock(
- new Rectangle(columnX, 150, (int)(columnWidth * 1.5f), infoFrame.Rect.Height - 150 - 80),
- "", GUI.Style, Alignment.TopLeft, Alignment.TopLeft, infoFrame, true, GameMain.GraphicsWidth>1024 ? GUI.Font : GUI.SmallFont);
- modeDescription.Color = Color.Black * 0.3f;
+ //var modeDescription = new GUITextBlock(
+ // new Rectangle(columnX, 150, (int)(columnWidth * 1.2f), infoFrame.Rect.Height - 150 - 80),
+ // "", GUI.Style, Alignment.TopLeft, Alignment.TopLeft, infoFrame, true, GUI.SmallFont);
+ //modeDescription.Color = Color.Black * 0.3f;
- modeList.UserData = modeDescription;
+ //modeList.UserData = modeDescription;
- columnX += modeDescription.Rect.Width + 40;
+ //columnX += modeDescription.Rect.Width + 20;
//seed ------------------------------------------------------------------
- new GUITextBlock(new Rectangle(columnX, 120, columnWidth, 20),
+ new GUITextBlock(new Rectangle(columnX, 120, 180, 20),
"Level Seed: ", GUI.Style, Alignment.Left, Alignment.TopLeft, infoFrame);
- seedBox = new GUITextBox(new Rectangle(columnX, 150, columnWidth, 20),
+ seedBox = new GUITextBox(new Rectangle(columnX, 150, columnWidth/2, 20),
Alignment.TopLeft, GUI.Style, infoFrame);
seedBox.OnTextChanged = SelectSeed;
LevelSeed = ToolBox.RandomSeed(8);
@@ -264,16 +285,16 @@ namespace Barotrauma
Character.Controlled = null;
GameMain.GameScreen.Cam.TargetPos = Vector2.Zero;
-
- subList.Enabled = GameMain.Server != null;
+
+ subList.Enabled = GameMain.Server != null || GameMain.NetworkMember.Voting.AllowSubVoting;
playerList.Enabled = GameMain.Server != null;
- modeList.Enabled = GameMain.Server != null;
+ modeList.Enabled = GameMain.Server != null || GameMain.NetworkMember.Voting.AllowModeVoting;
seedBox.Enabled = GameMain.Server != null;
serverMessage.Enabled = GameMain.Server != null;
autoRestartBox.Enabled = GameMain.Server != null;
ServerName = (GameMain.Server==null) ? "Server" : GameMain.Server.Name;
- modeList.OnSelected += SelectMode;
+
infoFrame.RemoveChild(infoFrame.children.Find(c => c.UserData as string == "startButton"));
@@ -281,6 +302,11 @@ namespace Barotrauma
if (IsServer && GameMain.Server != null)
{
+ modeList.OnSelected = VotableClicked;
+ modeList.OnSelected += SelectMode;
+ subList.OnSelected = VotableClicked;
+ subList.OnSelected += SelectMode;
+
GUIButton startButton = new GUIButton(new Rectangle(0, 0, 80, 30), "Start", Alignment.BottomRight, GUI.Style, infoFrame);
startButton.OnClicked = GameMain.Server.StartGameClicked;
startButton.UserData = "startButton";
@@ -294,7 +320,7 @@ namespace Barotrauma
banListButton.UserData = "banListButton";
//mapList.OnSelected = new GUIListBox.OnSelectedHandler(Game1.server.UpdateNetLobby);
- modeList.OnSelected += GameMain.Server.UpdateNetLobby;
+ //modeList.OnSelected += GameMain.Server.UpdateNetLobby;
if (subList.CountChildren > 0 && subList.Selected == null) subList.Select(-1);
if (GameModePreset.list.Count > 0 && modeList.Selected == null) modeList.Select(-1);
@@ -339,21 +365,21 @@ namespace Barotrauma
playerName.Text = characterInfo.Name;
playerName.OnEnterPressed += ChangeCharacterName;
- GUIButton toggleHead = new GUIButton(new Rectangle(0, 50, 20, 20), "<", GUI.Style, myPlayerFrame);
+ GUIButton toggleHead = new GUIButton(new Rectangle(0, 50, 15, 15), "<", GUI.Style, myPlayerFrame);
toggleHead.UserData = -1;
toggleHead.OnClicked = ToggleHead;
- toggleHead = new GUIButton(new Rectangle(60, 50, 20, 20), ">", GUI.Style, myPlayerFrame);
+ toggleHead = new GUIButton(new Rectangle(60, 50, 15, 15), ">", GUI.Style, myPlayerFrame);
toggleHead.UserData = 1;
toggleHead.OnClicked = ToggleHead;
- new GUITextBlock(new Rectangle(0, 100, 200, 30), "Gender: ", GUI.Style, myPlayerFrame);
+ new GUITextBlock(new Rectangle(0, 90, 200, 30), "Gender: ", GUI.Style, myPlayerFrame);
- GUIButton maleButton = new GUIButton(new Rectangle(70, 100, 60, 20), "Male",
+ GUIButton maleButton = new GUIButton(new Rectangle(0, 110, 60, 20), "Male",
Alignment.TopLeft, GUI.Style, myPlayerFrame);
maleButton.UserData = Gender.Male;
maleButton.OnClicked += SwitchGender;
- GUIButton femaleButton = new GUIButton(new Rectangle(140, 100, 60, 20), "Female",
+ GUIButton femaleButton = new GUIButton(new Rectangle(70, 110, 60, 20), "Female",
Alignment.TopLeft, GUI.Style, myPlayerFrame);
femaleButton.UserData = Gender.Female;
femaleButton.OnClicked += SwitchGender;
@@ -367,7 +393,9 @@ namespace Barotrauma
int i = 1;
foreach (JobPrefab job in JobPrefab.List)
{
- GUITextBlock jobText = new GUITextBlock(new Rectangle(0, 0, 0, 20), i + ". " + job.Name+" ", GUI.Style, Alignment.Left, Alignment.Right, jobList);
+ GUITextBlock jobText = new GUITextBlock(new Rectangle(0, 0, 0, 20), i + ". " + job.Name+" ",
+ GUI.Style,Alignment.Left, Alignment.Right, jobList, false,
+ GameMain.GraphicsWidth<1000 ? GUI.SmallFont : GUI.Font);
jobText.UserData = job;
GUIButton infoButton = new GUIButton(new Rectangle(0, 0, 15, 15), "?", GUI.Style, jobText);
@@ -439,6 +467,31 @@ namespace Barotrauma
return true;
}
+ public bool VotableClicked(GUIComponent component, object userData)
+ {
+ if (GameMain.Client == null) return false;
+
+ VoteType voteType = VoteType.Unknown;
+ if (component.Parent == GameMain.NetLobbyScreen.SubList)
+ {
+ if (!GameMain.Client.Voting.AllowSubVoting) return false;
+ voteType = VoteType.Sub;
+ }
+ else if (component.Parent == GameMain.NetLobbyScreen.ModeList)
+ {
+ if (!GameMain.Client.Voting.AllowModeVoting) return false;
+ voteType = VoteType.Mode;
+ }
+ else
+ {
+ return false;
+ }
+
+ GameMain.Client.Vote(voteType, userData);
+
+ return true;
+ }
+
public bool ChangeServerName(GUITextBox textBox, string text)
{
if (GameMain.Server == null) return false;
@@ -581,7 +634,7 @@ namespace Barotrauma
spriteBatch.Begin();
menu.Draw(spriteBatch);
-
+
if (jobInfoFrame != null) jobInfoFrame.Draw(spriteBatch);
//if (previewPlayer!=null) previewPlayer.Draw(spriteBatch);
@@ -664,15 +717,16 @@ namespace Barotrauma
private bool SelectMode(GUIComponent component, object obj)
{
+ if (GameMain.NetworkMember == null) return false;
+
+ //if (GameMain.Server==null)
+ //{
+ // return VotableClicked(component, obj);
+ //}
+
GameModePreset modePreset = obj as GameModePreset;
if (modePreset == null) return false;
- GUITextBlock description = modeList.UserData as GUITextBlock;
-
- description.Text = modePreset.Description;
-
- //if (Game1.Server != null) Game1.Server.UpdateNetLobby(null);
-
return true;
}
@@ -767,34 +821,34 @@ namespace Barotrauma
if (GameMain.Client!=null) GameMain.Client.SendCharacterData();
}
- public bool TrySelectMap(string mapName, string md5Hash)
+ public bool TrySelectSub(string subName, string md5Hash)
{
- Submarine map = Submarine.SavedSubmarines.Find(m => m.Name == mapName);
- if (map == null)
+ Submarine sub = Submarine.SavedSubmarines.Find(m => m.Name == subName);
+ if (sub == null)
{
- new GUIMessageBox("Submarine not found!","The submarine ''" + mapName + "'' has been selected by the server. Matching file not found in your map folder.");
+ new GUIMessageBox("Submarine not found!","The submarine ''" + subName + "'' has been selected by the server. Matching file not found in your map folder.");
return false;
}
else
{
- if (map.MD5Hash.Hash != md5Hash)
+ if (sub.MD5Hash.Hash != md5Hash)
{
new GUIMessageBox("Submarine not found!",
- "Your version of the map file ''" + map.Name + "'' doesn't match the server's version!"
- +"\nYour file: " + map.Name + "(MD5 hash : " + map.MD5Hash.Hash + ")"
- +"\nServer's file: " + mapName + "(MD5 hash : " + md5Hash + ")");
+ "Your version of the map file ''" + sub.Name + "'' doesn't match the server's version!"
+ +"\nYour file: " + sub.Name + "(MD5 hash : " + sub.MD5Hash.Hash + ")"
+ +"\nServer's file: " + subName + "(MD5 hash : " + md5Hash + ")");
return false;
}
else
{
- subList.Select(map);
+ subList.Select(sub);
//map.Load();
return true;
}
}
}
-
+
public void WriteData(NetOutgoingMessage msg)
{
Submarine selectedMap = subList.SelectedData as Submarine;
@@ -813,6 +867,9 @@ namespace Barotrauma
msg.Write(ServerName);
msg.Write(ServerMessage);
+ //msg.Write(AllowSubVoting);
+ //msg.Write(AllowModeVoting);
+
msg.Write(modeList.SelectedIndex-1);
//msg.Write(durationBar.BarScroll);
msg.Write(LevelSeed);
@@ -828,8 +885,6 @@ namespace Barotrauma
}
}
-
-
public void ReadData(NetIncomingMessage msg)
{
string mapName="", md5Hash="";
@@ -844,20 +899,23 @@ namespace Barotrauma
try
{
- mapName = msg.ReadString();
- md5Hash = msg.ReadString();
+ mapName = msg.ReadString();
+ md5Hash = msg.ReadString();
- ServerName = msg.ReadString();
- ServerMessage = msg.ReadString();
+ ServerName = msg.ReadString();
+ ServerMessage = msg.ReadString();
- modeIndex = msg.ReadInt32();
+ //AllowSubVoting = msg.ReadBoolean();
+ //AllowModeVoting = msg.ReadBoolean();
+
+ modeIndex = msg.ReadInt32();
//durationScroll = msg.ReadFloat();
- levelSeed = msg.ReadString();
+ levelSeed = msg.ReadString();
- autoRestart = msg.ReadBoolean();
- restartTimer = msg.ReadFloat();
+ autoRestart = msg.ReadBoolean();
+ restartTimer = msg.ReadFloat();
int playerCount = msg.ReadByte();
@@ -873,9 +931,9 @@ namespace Barotrauma
return;
}
- if (!string.IsNullOrWhiteSpace(mapName)) TrySelectMap(mapName, md5Hash);
+ if (!string.IsNullOrWhiteSpace(mapName) && !GameMain.NetworkMember.Voting.AllowSubVoting) TrySelectSub(mapName, md5Hash);
- modeList.Select(modeIndex);
+ if (!GameMain.NetworkMember.Voting.AllowModeVoting) modeList.Select(modeIndex);
autoRestartBox.Selected = autoRestart;
autoRestartTimer = restartTimer;
diff --git a/Subsurface/Source/Screens/NetLobbyVoting.cs b/Subsurface/Source/Screens/NetLobbyVoting.cs
new file mode 100644
index 000000000..ee3a3029f
--- /dev/null
+++ b/Subsurface/Source/Screens/NetLobbyVoting.cs
@@ -0,0 +1,234 @@
+using Barotrauma.Networking;
+using Lidgren.Network;
+using Microsoft.Xna.Framework;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Barotrauma
+{
+ class Voting
+ {
+ private bool allowSubVoting, allowModeVoting;
+
+ public bool AllowSubVoting
+ {
+ get { return allowSubVoting; }
+ set
+ {
+ if (value == allowSubVoting) return;
+ allowSubVoting = value;
+ GameMain.NetLobbyScreen.SubList.Enabled = value || GameMain.Server != null;
+ GameMain.NetLobbyScreen.InfoFrame.FindChild("subvotes").Visible = value;
+
+ if (GameMain.Server != null)
+ {
+ UpdateVoteTexts(GameMain.Server.connectedClients, VoteType.Sub);
+ GameMain.Server.UpdateVoteStatus();
+ }
+ else
+ {
+ GameMain.NetLobbyScreen.SubList.Deselect();
+ }
+ }
+ }
+ public bool AllowModeVoting
+ {
+ get { return allowModeVoting; }
+ set
+ {
+ if (value == allowModeVoting) return;
+ allowModeVoting = value;
+ GameMain.NetLobbyScreen.ModeList.Enabled = value || GameMain.Server != null;
+ GameMain.NetLobbyScreen.InfoFrame.FindChild("modevotes").Visible = value;
+ if (GameMain.Server != null)
+ {
+ UpdateVoteTexts(GameMain.Server.connectedClients, VoteType.Mode);
+ GameMain.Server.UpdateVoteStatus();
+ }
+ else
+ {
+ GameMain.NetLobbyScreen.ModeList.Deselect();
+ }
+ }
+ }
+
+ public void RegisterVote(NetIncomingMessage inc, List connectedClients)
+ {
+ byte voteTypeByte = inc.ReadByte();
+ VoteType voteType = VoteType.Unknown;
+ try
+ {
+ voteType = (VoteType)voteTypeByte;
+ }
+ catch
+ {
+ return;
+ }
+ Client sender = connectedClients.Find(x => x.Connection == inc.SenderConnection);
+ switch (voteType)
+ {
+ case VoteType.Sub:
+ string subName = inc.ReadString();
+ Submarine sub = Submarine.SavedSubmarines.Find(s => s.Name == subName);
+ sender.SetVote(voteType, sub);
+ UpdateVoteTexts(connectedClients, voteType);
+ break;
+
+ case VoteType.Mode:
+ string modeName = inc.ReadString();
+ GameModePreset mode = GameModePreset.list.Find(gm => gm.Name == modeName);
+ sender.SetVote(voteType, mode);
+ UpdateVoteTexts(connectedClients, voteType);
+ break;
+ case VoteType.EndRound:
+ sender.SetVote(voteType, inc.ReadBoolean());
+ break;
+ }
+
+ GameMain.Server.UpdateVoteStatus();
+ }
+
+ public void UpdateVoteTexts(List clients, VoteType voteType)
+ {
+ GUIListBox listBox = (voteType == VoteType.Sub) ?
+ GameMain.NetLobbyScreen.SubList : GameMain.NetLobbyScreen.ModeList;
+
+ foreach (GUIComponent comp in listBox.children)
+ {
+ GUITextBlock voteText = comp.FindChild("votes") as GUITextBlock;
+ if (voteText != null) comp.RemoveChild(voteText);
+ }
+
+ List> voteList = GetVoteList(voteType, clients);
+ foreach (Pair