Infinite wall fixes, pressure damage to sub, sub/mode voting & randomization working now, better ui scaling

This commit is contained in:
Regalis
2015-10-31 00:29:51 +02:00
parent dc4b502248
commit bcc96cee97
33 changed files with 1068 additions and 151 deletions

View File

@@ -104,7 +104,8 @@
<Compile Include="Source\Networking\NetStats.cs" />
<Compile Include="Source\Networking\ReliableSender.cs" />
<Compile Include="Source\Particles\ParticleEmitter.cs" />
<Compile Include="Source\Screens\NetLobbySettings.cs" />
<Compile Include="Source\Networking\GameServerSettings.cs" />
<Compile Include="Source\Screens\NetLobbyVoting.cs" />
<Compile Include="Source\Screens\ServerListScreen.cs" />
<Compile Include="Source\Utils\Rand.cs" />
<Compile Include="Source\Events\PropertyTask.cs" />
@@ -905,6 +906,21 @@
<None Include="Content\SmallFont.xnb">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="Content\Sounds\Damage\creak1.ogg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="Content\Sounds\Damage\creak2.ogg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="Content\Sounds\Damage\creak3.ogg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="Content\Sounds\Damage\creak4.ogg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="Content\Sounds\Damage\creak5.ogg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="Content\Sounds\Damage\HitArmor1.ogg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
@@ -932,6 +948,9 @@
<None Include="Content\Sounds\Damage\StructureBlunt7.ogg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="Content\Sounds\Music\amb_JD_drone_clattering_machine.ogg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="Content\Sounds\Music\Enter the Maze.ogg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 MiB

After

Width:  |  Height:  |  Size: 381 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -28,7 +28,11 @@
<damagesound file="Content/Sounds/Damage/implode.ogg" damagerange="0.0,100.0" damagesoundtype="Implode"/>
<damagesound file="Content/Sounds/Damage/implode.ogg" damagerange="0.0,100.0" damagesoundtype="Implode"/>
<damagesound file="Content/Sounds/Damage/creak1.ogg" damagesoundtype="Pressure"/>
<damagesound file="Content/Sounds/Damage/creak2.ogg" damagesoundtype="Pressure"/>
<damagesound file="Content/Sounds/Damage/creak3.ogg" damagesoundtype="Pressure"/>
<damagesound file="Content/Sounds/Damage/creak4.ogg" damagesoundtype="Pressure"/>
<damagesound file="Content/Sounds/Damage/creak5.ogg" damagesoundtype="Pressure"/>
<music file="Content/Sounds/Music/Simplex.ogg" type="default"/>
@@ -36,4 +40,5 @@
<music file="Content/Sounds/Music/Enter the Maze.ogg" type="repair" priorityrange="30,60"/>
<music file="Content/Sounds/Music/Static Motion.ogg" type="repair" priorityrange="50,80"/>
<music file="Content/Sounds/Music/Unseen Horrors.ogg" type="monster" priorityrange="40,100"/>
<music file="Content/Sounds/Music/amb_JD_drone_clattering_machine.ogg" type="deep"/>
</sounds>

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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;
}

View File

@@ -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<GUIComponent> FindChildren(object userData)
{
return children .FindAll(c => c.userData == userData);
}
public virtual void ClearChildren()

View File

@@ -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)
{

View File

@@ -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)
{

View File

@@ -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)

View File

@@ -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<Vector2> { 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<GraphEdge> allowedEdges = new List<GraphEdge>();
List<VoronoiCell> pathCells = new List<VoronoiCell>();
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<GraphEdge> allowedEdges = new List<GraphEdge>();
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<VoronoiCell> CreateBottomHoles(float holeProbability, Rectangle limits)
{
List<VoronoiCell> toBeRemoved = new List<VoronoiCell>();
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<VoronoiCell> GetTooCloseCells(List<VoronoiCell> emptyCells, float minDistance)
{
List<VoronoiCell> tooCloseCells = new List<VoronoiCell>();
@@ -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();

View File

@@ -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;

View File

@@ -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;

View File

@@ -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);

View File

@@ -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;

View File

@@ -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<Submarine>(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<GameModePreset>(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<JobPrefab> 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>(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;
}
}
}

View File

@@ -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;
}

View File

@@ -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<Character> crew)

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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;

View File

@@ -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<Client> 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<Client> 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<Pair<object, int>> voteList = GetVoteList(voteType, clients);
foreach (Pair<object, int> votable in voteList)
{
SetVoteText(listBox, votable.First, votable.Second);
}
}
private void SetVoteText(GUIListBox listBox, object userData, int votes)
{
if (userData == null) return;
foreach (GUIComponent comp in listBox.children)
{
if (comp.UserData != userData) continue;
GUITextBlock voteText = comp.FindChild("votes") as GUITextBlock;
if (voteText == null)
{
voteText = new GUITextBlock(new Rectangle(0, 0, 30, 0), "", GUI.Style, Alignment.Right, Alignment.Right, comp);
voteText.UserData = "votes";
}
voteText.Text = votes.ToString();
}
}
private List<Pair<object, int>> GetVoteList(VoteType voteType, List<Client> voters)
{
List<Pair<object, int>> voteList = new List<Pair<object, int>>();
foreach (Client voter in voters)
{
object vote = voter.GetVote(voteType);
if (vote == null) continue;
var existingVotable = voteList.Find(v => v.First == vote);
if (existingVotable == null)
{
voteList.Add(Pair<object, int>.Create(vote, 1));
}
else
{
existingVotable.Second++;
}
}
return voteList;
}
public T HighestVoted<T>(VoteType voteType, List<Client> voters)
{
if (voteType == VoteType.Sub && !AllowSubVoting) return default(T);
if (voteType == VoteType.Mode && !AllowModeVoting) return default(T);
List<Pair<object, int>> voteList = GetVoteList(voteType,voters);
T selected = default(T);
int highestVotes = 0;
foreach (Pair<object, int> votable in voteList)
{
if (selected == null || votable.Second > highestVotes)
{
highestVotes = votable.Second;
selected = (T)votable.First;
}
}
return selected;
}
public void WriteData(NetOutgoingMessage msg, List<Client> voters)
{
msg.Write(allowSubVoting);
if (allowSubVoting)
{
List<Pair<object, int>> voteList = GetVoteList(VoteType.Sub, voters);
msg.Write((byte)voteList.Count);
foreach (Pair<object, int> vote in voteList)
{
if (vote.Second < 1 || vote.First==null) continue;
msg.Write((byte)vote.Second);
msg.Write(((Submarine)vote.First).Name);
}
}
msg.Write(AllowModeVoting);
if (allowModeVoting)
{
List<Pair<object, int>> voteList = GetVoteList(VoteType.Mode, voters);
msg.Write((byte)voteList.Count);
foreach (Pair<object, int> vote in voteList)
{
if (vote.Second < 1 || vote.First == null) continue;
msg.Write((byte)vote.Second);
msg.Write(((GameModePreset)vote.First).Name);
}
}
}
public void ReadData(NetIncomingMessage msg)
{
AllowSubVoting = msg.ReadBoolean();
if (allowSubVoting)
{
int votableCount = msg.ReadByte();
for (int i = 0; i<votableCount; i++)
{
int votes = msg.ReadByte();
string subName = msg.ReadString();
Submarine sub = Submarine.SavedSubmarines.Find(sm => sm.Name == subName);
SetVoteText(GameMain.NetLobbyScreen.SubList, sub, votes);
}
}
AllowModeVoting = msg.ReadBoolean();
if (allowModeVoting)
{
int votableCount = msg.ReadByte();
for (int i = 0; i < votableCount; i++)
{
int votes = msg.ReadByte();
string modeName = msg.ReadString();
GameModePreset mode = GameModePreset.list.Find(m => m.Name == modeName);
SetVoteText(GameMain.NetLobbyScreen.SubList, mode, votes);
}
}
}
}
}

View File

@@ -65,11 +65,13 @@ namespace Barotrauma
if (n > 0) columnX[n] += columnX[n - 1];
}
new GUITextBlock(new Rectangle(middleX, 30, 0, 30), "Password", GUI.Style, menu);
SpriteFont font = serverList.Rect.Width < 400 ? GUI.SmallFont : GUI.Font;
new GUITextBlock(new Rectangle(middleX + columnX[0], 30, 0, 30), "Name", GUI.Style, menu);
new GUITextBlock(new Rectangle(middleX + columnX[1], 30, 0, 30), "Players", GUI.Style, menu);
new GUITextBlock(new Rectangle(middleX + columnX[2], 30, 0, 30), "Round started", GUI.Style, menu);
new GUITextBlock(new Rectangle(middleX, 30, 0, 30), "Password", GUI.Style, menu).Font = font;
new GUITextBlock(new Rectangle(middleX + columnX[0], 30, 0, 30), "Name", GUI.Style, menu).Font = font;
new GUITextBlock(new Rectangle(middleX + columnX[1], 30, 0, 30), "Players", GUI.Style, menu).Font = font;
new GUITextBlock(new Rectangle(middleX + columnX[2], 30, 0, 30), "Round started", GUI.Style, menu).Font = font;
joinButton = new GUIButton(new Rectangle(-170, 0, 150, 30), "Refresh", Alignment.BottomRight, GUI.Style, menu);
joinButton.OnClicked = RefreshServers;

View File

@@ -0,0 +1,337 @@
using System;
using Lidgren.Network;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Barotrauma.Networking;
using FarseerPhysics;
using FarseerPhysics.Factories;
using FarseerPhysics.Dynamics;
using System.IO;
using System.Collections.Generic;
using RestSharp;
namespace Barotrauma
{
class ServerListScreen : Screen
{
//how often the client is allowed to refresh servers
private TimeSpan AllowedRefreshInterval = new TimeSpan(0,0,3);
private GUIFrame menu;
private GUIListBox serverList;
private GUIButton joinButton;
private GUITextBox clientNameBox, ipBox;
//private RestRequestAsyncHandle restRequestHandle;
private bool masterServerResponded;
private int[] columnX;
//a timer for
private DateTime refreshDisableTimer;
private bool waitingForRefresh;
public ServerListScreen()
{
int width = Math.Min(GameMain.GraphicsWidth - 160, 1000);
int height = Math.Min(GameMain.GraphicsHeight - 160, 700);
Rectangle panelRect = new Rectangle(0, 0, width, height);
menu = new GUIFrame(panelRect, null, Alignment.Center, GUI.Style);
menu.Padding = new Vector4(40.0f, 40.0f, 40.0f, 20.0f);
new GUITextBlock(new Rectangle(0, -25, 0, 30), "Join Server", GUI.Style, Alignment.CenterX, Alignment.CenterX, menu, false, GUI.LargeFont);
new GUITextBlock(new Rectangle(0, 30, 0, 30), "Your Name:", GUI.Style, menu);
clientNameBox = new GUITextBox(new Rectangle(0, 60, 200, 30), GUI.Style, menu);
new GUITextBlock(new Rectangle(0, 100, 0, 30), "Server IP:", GUI.Style, menu);
ipBox = new GUITextBox(new Rectangle(0, 130, 200, 30), GUI.Style, menu);
int middleX = (int)(width * 0.4f);
serverList = new GUIListBox(new Rectangle(middleX,60,0,height-160), GUI.Style, menu);
serverList.OnSelected = SelectServer;
float[] columnRelativeX = new float[] { 0.15f, 0.55f, 0.15f, 0.15f };
columnX = new int[columnRelativeX.Length];
for (int n = 0; n < columnX.Length; n++)
{
columnX[n] = (int)(columnRelativeX[n] * serverList.Rect.Width);
if (n > 0) columnX[n] += columnX[n - 1];
}
SpriteFont font = serverList.Rect.Width < 400 ? GUI.SmallFont : GUI.Font;
new GUITextBlock(new Rectangle(middleX, 30, 0, 30), "Password", GUI.Style, menu).Font = font;
new GUITextBlock(new Rectangle(middleX + columnX[0], 30, 0, 30), "Name", GUI.Style, menu).Font = font;
new GUITextBlock(new Rectangle(middleX + columnX[1], 30, 0, 30), "Players", GUI.Style, menu).Font = font;
new GUITextBlock(new Rectangle(middleX + columnX[2], 30, 0, 30), "Round started", GUI.Style, menu).Font = font;
joinButton = new GUIButton(new Rectangle(-170, 0, 150, 30), "Refresh", Alignment.BottomRight, GUI.Style, menu);
joinButton.OnClicked = RefreshServers;
joinButton = new GUIButton(new Rectangle(0,0,150,30), "Join", Alignment.BottomRight, GUI.Style, menu);
joinButton.OnClicked = JoinServer;
GUIButton button = new GUIButton(new Rectangle(-20, -20, 100, 30), "Back", Alignment.TopLeft, GUI.Style, menu);
button.OnClicked = GameMain.MainMenuScreen.SelectTab;
button.CanBeSelected = false;
button.SelectedColor = button.Color;
refreshDisableTimer = DateTime.Now;
}
public override void Select()
{
base.Select();
RefreshServers(null, null);
}
private bool SelectServer(GUIComponent component, object obj)
{
string ip = obj as string;
if (string.IsNullOrWhiteSpace(ip)) return false;
ipBox.Text = ip;
return true;
}
private bool RefreshServers(GUIButton button, object obj)
{
if (waitingForRefresh) return false;
serverList.ClearChildren();
new GUITextBlock(new Rectangle(0, 0, 0, 20), "Refreshing server list...", GUI.Style, serverList);
CoroutineManager.StartCoroutine(WaitForRefresh());
return true;
}
private IEnumerable<object> WaitForRefresh()
{
waitingForRefresh = true;
if (refreshDisableTimer > DateTime.Now)
{
yield return new WaitForSeconds((float)(refreshDisableTimer - DateTime.Now).TotalSeconds);
}
//CoroutineManager.StartCoroutine(UpdateServerList());
CoroutineManager.StartCoroutine(SendMasterServerRequest());
waitingForRefresh = false;
refreshDisableTimer = DateTime.Now + AllowedRefreshInterval;
yield return CoroutineStatus.Success;
}
private void UpdateServerList(string masterServerData)
{
serverList.ClearChildren();
//string masterServerData = GetMasterServerData();
if (string.IsNullOrWhiteSpace(masterServerData))
{
var nameText = new GUITextBlock(new Rectangle(0, 0, 0, 20), "Couldn't find any servers", GUI.Style, serverList);
return;
}
if (masterServerData.Substring(0,5).ToLower()=="error")
{
DebugConsole.ThrowError("Error while connecting to master server ("+masterServerData+")!");
return;
}
string[] lines = masterServerData.Split('\n');
for (int i = 0; i<lines.Length; i++)
{
string[] arguments = lines[i].Split('|');
if (arguments.Length < 3) continue;
string IP = arguments[0];
string port = arguments[1];
string serverName = arguments[2];
string gameStarted = (arguments.Length > 3) ? arguments[3] : "";
string playerCountStr = (arguments.Length > 4) ? arguments[4] : "";
string hasPassWordStr = (arguments.Length > 5) ? arguments[5] : "";
var serverFrame = new GUIFrame(new Rectangle(0,0,0,20), (i%2 == 0) ? Color.Transparent : Color.White*0.2f, null, serverList);
serverFrame.UserData = IP+":"+port;
serverFrame.HoverColor = Color.Gold * 0.2f;
serverFrame.SelectedColor = Color.Gold * 0.5f;
var passwordBox = new GUITickBox(new Rectangle(columnX[0]/2, 0, 20, 20), "", Alignment.TopLeft, serverFrame);
passwordBox.Selected = hasPassWordStr == "1";
passwordBox.Enabled = false;
passwordBox.UserData = "password";
var nameText = new GUITextBlock(new Rectangle(columnX[0], 0, 0, 0), serverName, GUI.Style, serverFrame);
int playerCount, maxPlayers;
playerCount = GameClient.ByteToPlayerCount((byte)int.Parse(playerCountStr), out maxPlayers);
var playerCountText = new GUITextBlock(new Rectangle(columnX[1], 0, 0, 0), playerCount + "/" + maxPlayers, GUI.Style, serverFrame);
var gameStartedBox = new GUITickBox(new Rectangle(columnX[2] + (columnX[3] - columnX[2])/ 2, 0, 20, 20), "", Alignment.TopLeft, serverFrame);
gameStartedBox.Selected = gameStarted == "1";
gameStartedBox.Enabled = false;
}
}
private IEnumerable<object> SendMasterServerRequest()
{
RestClient client = null;
try
{
client = new RestClient(NetConfig.MasterServerUrl);
}
catch (Exception e)
{
DebugConsole.ThrowError("Error while connecting to master server", e);
}
if (client == null) yield return CoroutineStatus.Success;
var request = new RestRequest("masterserver.php", Method.GET);
request.AddParameter("gamename", "barotrauma"); // adds to POST or URL querystring based on Method
request.AddParameter("action", "listservers"); // adds to POST or URL querystring based on Method
// easily add HTTP Headers
//request.AddHeader("header", "value");
//// add files to upload (works with compatible verbs)
//request.AddFile(path);
// execute the request
masterServerResponded = false;
var restRequestHandle = client.ExecuteAsync(request, response => MasterServerCallBack(response));
DateTime timeOut = DateTime.Now + new TimeSpan(0, 0, 8);
while (!masterServerResponded)
{
if (DateTime.Now > timeOut)
{
serverList.ClearChildren();
restRequestHandle.Abort();
DebugConsole.ThrowError("Couldn't connect to master server (request timed out)");
}
yield return CoroutineStatus.Running;
}
yield return CoroutineStatus.Success;
}
private void MasterServerCallBack(IRestResponse response)
{
masterServerResponded = true;
if (response.ErrorException!=null)
{
serverList.ClearChildren();
DebugConsole.ThrowError("Error while connecting to master server", response.ErrorException);
return;
}
if (response.StatusCode!= System.Net.HttpStatusCode.OK)
{
serverList.ClearChildren();
DebugConsole.ThrowError("Error while connecting to master server (" +response.StatusCode+": "+response.StatusDescription+")");
return;
}
UpdateServerList(response.Content);
}
private bool JoinServer(GUIButton button, object obj)
{
if (string.IsNullOrWhiteSpace(clientNameBox.Text))
{
clientNameBox.Flash();
return false;
}
string ip = ipBox.Text;
if (string.IsNullOrWhiteSpace(ip))
{
ipBox.Flash();
return false;
}
CoroutineManager.StartCoroutine(JoinServer(ip));
return true;
}
private IEnumerable<object> JoinServer(string ip)
{
string selectedPassword = "";
if (serverList.Selected!=null && (serverList.Selected.GetChild("password") as GUITickBox).Selected)
{
var msgBox = new GUIMessageBox("Password required:", "");
var passwordBox = new GUITextBox(new Rectangle(0,40,150,25), Alignment.TopLeft, GUI.Style, msgBox);
passwordBox.UserData = "password";
var okButton = msgBox.GetChild<GUIButton>();
while (GUIMessageBox.MessageBoxes.Contains(msgBox))
{
okButton.Enabled = !string.IsNullOrWhiteSpace(passwordBox.Text);
yield return CoroutineStatus.Running;
}
selectedPassword = passwordBox.Text;
}
GameMain.NetworkMember = new GameClient(clientNameBox.Text);
GameMain.Client.ConnectToServer(ip, selectedPassword);
yield return CoroutineStatus.Success;
}
public override void Draw(double deltaTime, GraphicsDevice graphics, SpriteBatch spriteBatch)
{
graphics.Clear(Color.CornflowerBlue);
GameMain.GameScreen.DrawMap(graphics, spriteBatch);
spriteBatch.Begin();
menu.Draw(spriteBatch);
//if (previewPlayer!=null) previewPlayer.Draw(spriteBatch);
GUI.Draw((float)deltaTime, spriteBatch, null);
spriteBatch.End();
}
public override void Update(double deltaTime)
{
menu.Update((float)deltaTime);
GUI.Update((float)deltaTime);
}
}
}

View File

@@ -14,7 +14,7 @@ namespace Barotrauma
None,
StructureBlunt, StructureSlash,
LimbBlunt, LimbSlash, LimbArmor,
Implode }
Implode, Pressure }
public struct DamageSound
{
@@ -228,7 +228,11 @@ namespace Barotrauma
}
List<BackgroundMusic> suitableMusic = null;
if (criticalTask == null)
if (Submarine.Loaded!=null && Submarine.Loaded.Position.Y<0.0f)
{
suitableMusic = musicClips.Where(x => x != null && x.type == "deep").ToList();
}
else if (criticalTask == null)
{
suitableMusic = musicClips.Where(x => x != null && x.type == "default").ToList();
}
@@ -278,7 +282,7 @@ namespace Barotrauma
PlayDamageSound(damageType, damage, bodyPosition);
}
public static void PlayDamageSound(DamageSoundType damageType, float damage, Vector2 position)
public static void PlayDamageSound(DamageSoundType damageType, float damage, Vector2 position, float range = 2000.0f)
{
damage = MathHelper.Clamp(damage+Rand.Range(-10.0f, 10.0f), 0.0f, 100.0f);
var sounds = damageSounds.Where(x => damage >= x.damageRange.X && damage <= x.damageRange.Y && x.damageType == damageType).ToList();
@@ -291,7 +295,7 @@ namespace Barotrauma
{
if (i == selectedSound)
{
s.sound.Play(1.0f, 2000.0f, position);
s.sound.Play(1.0f, range, position);
Debug.WriteLine("playing: " + s.sound);
return;
}

View File

@@ -10,6 +10,21 @@ using System.Xml.Linq;
namespace Barotrauma
{
public class Pair<T1, T2>
{
public T1 First { get; set; }
public T2 Second { get; set; }
public static Pair<T1, T2> Create(T1 first, T2 second)
{
Pair<T1, T2> pair = new Pair<T1, T2>();
pair.First = first;
pair.Second = second;
return pair;
}
}
public static class ToolBox
{
public static XDocument TryLoadXml(string filePath)

Binary file not shown.