Spawnpoints for different jobs, spawning crew members with job-specific items, fixed issues with non-matching entity IDs between client and server, Unity-like coroutine system (connecting to server doesn't freeze the game anymore), map drawing improvements

This commit is contained in:
Regalis
2015-07-09 01:40:27 +03:00
parent d56f7f3f77
commit 2254585dac
35 changed files with 831 additions and 312 deletions

View File

@@ -268,6 +268,12 @@ namespace Subsurface
{
}
public Character(CharacterInfo characterInfo, WayPoint spawnPoint, bool isNetworkPlayer = false)
: this(characterInfo.File, spawnPoint.SimPosition, characterInfo, isNetworkPlayer)
{
}
public Character(CharacterInfo characterInfo, Vector2 position, bool isNetworkPlayer = false)
: this(characterInfo.File, position, characterInfo, isNetworkPlayer)
{
@@ -351,7 +357,6 @@ namespace Subsurface
}
}
AnimController.FindHull();
//if (info.ID >= 0)
@@ -362,6 +367,24 @@ namespace Subsurface
CharacterList.Add(this);
}
public void GiveJobItems()
{
if (Info == null || Info.Job == null) return;
foreach (string itemName in Info.Job.SpawnItemNames)
{
ItemPrefab itemPrefab = ItemPrefab.list.Find(ip => ip.Name == itemName) as ItemPrefab;
if (itemPrefab == null)
{
DebugConsole.ThrowError("Tried to spawn ''" + Name + "'' with the item ''" + itemName + "''. Matching item prefab not found.");
continue;
}
Item item = new Item(itemPrefab, Position);
inventory.TryPutItem(item, item.AllowedSlots, false);
}
}
public void Control(float deltaTime, Camera cam, bool forcePick = false)
{
if (isDead) return;
@@ -612,15 +635,17 @@ namespace Subsurface
spriteBatch.DrawString(GUI.font, Info.Name, namePos, Color.White);
}
Vector2 pos = ConvertUnits.ToDisplayUnits(AnimController.limbs[0].SimPosition);
pos.Y = -pos.Y;
spriteBatch.DrawString(GUI.font, ID.ToString(), pos, Color.White);
if (this == Character.controlled) return;
Vector2 healthBarPos = new Vector2(Position.X - 50, -Position.Y - 50.0f);
GUI.DrawRectangle(spriteBatch, new Rectangle((int)healthBarPos.X-2, (int)healthBarPos.Y-2, 100+4, 15+4), Color.Black, false);
GUI.DrawRectangle(spriteBatch, new Rectangle((int)healthBarPos.X, (int)healthBarPos.Y, (int)(100.0f*(health/maxHealth)), 15), Color.Red, true);
Vector2 pos = ConvertUnits.ToDisplayUnits(AnimController.limbs[0].SimPosition);
pos.Y = -pos.Y;
spriteBatch.DrawString(GUI.font, ID.ToString(), pos, Color.White);
//GUI.DrawLine(spriteBatch, ConvertUnits.ToDisplayUnits(animController.limbs[0].SimPosition.X, animController.limbs[0].SimPosition.Y),
// ConvertUnits.ToDisplayUnits(animController.limbs[0].SimPosition.X, animController.limbs[0].SimPosition.Y) +
// ConvertUnits.ToDisplayUnits(animController.targetMovement.X, animController.targetMovement.Y), Color.Green);
@@ -1036,7 +1061,9 @@ namespace Subsurface
if (controlled == this) controlled = null;
if (Game1.Client!=null && Game1.Client.Character == this) Game1.Client.Character = null;
if (Game1.Client!=null && Game1.Client.Character == this) Game1.Client.Character = null;
if (inventory != null) inventory.Remove();
if (aiTarget != null)
aiTarget.Remove();

View File

@@ -19,6 +19,8 @@ namespace Subsurface
public int Salary;
public bool StartItemsGiven;
//public string GenderString()
//{
// return gender.ToString();
@@ -96,11 +98,10 @@ namespace Subsurface
string genderStr = ToolBox.GetAttributeString(element, "gender", "male").ToLower();
Gender = (genderStr == "male") ? Gender.Male : Gender.Female;
File = ToolBox.GetAttributeString(element, "file", "");
Salary = ToolBox.GetAttributeInt(element, "salary", 1000);
HeadSpriteId = ToolBox.GetAttributeInt(element, "headspriteid", 1);
File = ToolBox.GetAttributeString(element, "file", "");
Salary = ToolBox.GetAttributeInt(element, "salary", 1000);
HeadSpriteId = ToolBox.GetAttributeInt(element, "headspriteid", 1);
StartItemsGiven = ToolBox.GetAttributeBool(element, "startitemsgiven", false);
foreach (XElement subElement in element.Elements())
{
@@ -120,7 +121,8 @@ namespace Subsurface
new XAttribute("file", File),
new XAttribute("gender", Gender == Gender.Male ? "male" : "female"),
new XAttribute("salary", Salary),
new XAttribute("headspriteid", HeadSpriteId));
new XAttribute("headspriteid", HeadSpriteId),
new XAttribute("startitemsgiven", StartItemsGiven));
Job.Save(charElement);

View File

@@ -24,6 +24,16 @@ namespace Subsurface
get { return prefab.Description; }
}
public JobPrefab Prefab
{
get { return prefab; }
}
public List<string> SpawnItemNames
{
get { return prefab.ItemNames; }
}
public Job(JobPrefab jobPrefab)
{

View File

@@ -68,7 +68,7 @@ namespace Subsurface
foreach (XElement subElement in element.Elements())
{
switch (subElement.Name.ToString())
switch (subElement.Name.ToString().ToLower())
{
case "item":
string itemName = ToolBox.GetAttributeString(subElement, "name", "");

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?>
<Jobs>
<Captain description="The Commanding Officer with authority over the entire crew.">
<Captain description="The Commanding Officer with authority over the entire crew." minnumber="1" maxnumber="1">
<Item name="ID Card"/>
</Captain>
@@ -15,4 +15,10 @@
<Item name="Wrench"/>
<Item name="Screwdriver"/>
</Mechanic>
<Assistant allowalways="true">
<Item name="ID Card"/>
<Item name="Wrench"/>
<Item name="Screwdriver"/>
</Assistant>
</Jobs>

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 MiB

View File

@@ -16,17 +16,18 @@
</GUIFrame>
<GUIButton
color="0.6, 0.2, 0.2, 1.0"
color="0.88, 0.25, 0.15, 1.0"
textcolor="1.0, 1.0, 1.0, 1.0"
hovercolor="0.88, 0.19, 0.16, 1.0"
selectedcolor="0.8, 0.8, 0.8, 1.0"/>
hovercolor="1.0, 0.57, 0.31, 1.0"
selectedcolor="1.0, 0.0, 0.0, 1.0"/>
<GUITextBlock
textcolor="1.0, 1.0, 1.0, 1.0"
hovercolor="1.0, 1.0, 1.0, 0.3"
selectedcolor="1.0, 0.6, 0.0, 0.3"/>
selectedcolor="1.0, 0.6, 0.0, 0.3"
padding="10.0, 0.0, 10.0, 0.0"/>
<GUIListBox
color="0.5, 0.5, 0.5, 1.0"
@@ -46,11 +47,26 @@
</GUIScrollBar>
<GUITextBox
color="0.5, 0.5, 0.5, 1.0"
color="0.8, 0.8, 0.8, 1.0"
textcolor="1.0, 1.0, 1.0, 1.0"
textcolor="0.0, 0.0, 0.0, 1.0"
outlinecolor="0.5, 0.57, 0.6, 1.0">
<Sprite texture="Content\UI\uiBackground.png" size="0.0, 1.0" sourcerect ="0.0, 0.0, 0.0, 90.0"/>
</GUITextBox>
<GUIMessageBox
padding="40.0, 40.0, 40.0, 40.0"
color="1.0, 1.0, 1.0, 1.0"
textcolor="0.0, 0.0, 0.0, 1.0"
hovercolor="0.8, 0.8, 0.8, 1.0"
selectedcolor="1.0, 0.82, 0.05, 1.0"
outlinecolor="0.5, 0.57, 0.6, 1.0">
<Sprite texture="Content\UI\uiBackground.png" size="0.0, 0.0" sourcerect ="0.0, 90.0, 0.0, 100.0"/>
<Sprite texture="Content\UI\uiBackground.png" size="0.0, 1.0" sourcerect ="0.0, 0.0, 0.0, 90.0"/>
</GUIMessageBox>
</style>

View File

@@ -5,13 +5,13 @@
commonness="10"
difficulty="30"
minamount="2" maxamount="3"
starttimemin="5" starttimemax="10"
starttimemin="15" starttimemax="20"
musictype="monster"/>
<MonsterEvent name="Under attack" description=""
characterfile="Content/Characters/TigerThresher/tigerthresher.xml"
commonness="10"
difficulty="50"
starttimemin="5" starttimemax="10"
starttimemin="15" starttimemax="20"
musictype="monster"/>
</Randomevents>

View File

@@ -0,0 +1,45 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Subsurface
{
enum Status
{
Running, Success, Failure
}
// Keeps track of all running coroutines, and runs them till the end.
static class CoroutineManager
{
static List<IEnumerator<Status>> Coroutines = new List<IEnumerator<Status>>();
// Starting a coroutine just means adding an enumerator to the list.
// You might also want to be able to stop coroutines or delete them,
// which might mean putting them into a dictionary
public static void StartCoroutine(IEnumerable<Status> func)
{
Coroutines.Add(func.GetEnumerator());
}
// Updating just means stepping through all the coroutines
public static void Update()
{
for (int i = Coroutines.Count-1; i>=0; i--)
{
Coroutines[i].MoveNext();
switch (Coroutines[i].Current)
{
case Status.Success:
Coroutines.RemoveAt(i);
break;
case Status.Failure:
DebugConsole.ThrowError("Coroutine ''" + Coroutines[i]+ "'' has failed");
break;
}
}
}
}
}

View File

@@ -63,7 +63,6 @@ namespace Subsurface
{
ScriptedEvent scriptedEvent = ScriptedEvent.LoadRandom(level.Seed);
AddTask(new ScriptedTask(scriptedEvent));
}
public void TaskStarted(Task task)

View File

@@ -21,17 +21,17 @@ namespace Subsurface
this.Buttons[0].OnClicked = Close;
}
public GUIMessageBox(string header, string text, string[] buttons, Alignment textAlignment = (Alignment.Left | Alignment.Top))
: base(new Rectangle(Game1.GraphicsWidth / 2 - DefaultWidth / 2, Game1.GraphicsHeight / 2 - DefaultHeight / 2, DefaultWidth, DefaultHeight),
null, Alignment.CenterX, GUI.style, null)
public GUIMessageBox(string header, string text, string[] buttons, Alignment textAlignment = Alignment.TopLeft)
: base(new Rectangle(0,0, DefaultWidth, DefaultHeight),
null, Alignment.Center, GUI.style, null)
{
//Padding = GUI.style.smallPadding;
if (buttons == null || buttons.Length == 0)
{
DebugConsole.ThrowError("Creating a message box with no buttons isn't allowed");
return;
}
//if (buttons == null || buttons.Length == 0)
//{
// DebugConsole.ThrowError("Creating a message box with no buttons isn't allowed");
// return;
//}
new GUITextBlock(new Rectangle(0, 0, 0, 30), header, Color.Transparent, Color.White, textAlignment, GUI.style, this, true);
new GUITextBlock(new Rectangle(0, 30, 0, DefaultHeight - 70), text, Color.Transparent, Color.White, textAlignment, GUI.style, this, true);

View File

@@ -69,7 +69,7 @@ namespace Subsurface
}
public GUITextBlock(Rectangle rect, string text, GUIStyle style, Alignment alignment = (Alignment.Left | Alignment.Top), Alignment textAlignment = (Alignment.Left | Alignment.Top), GUIComponent parent = null, bool wrap = false)
public GUITextBlock(Rectangle rect, string text, GUIStyle style, Alignment alignment = Alignment.TopLeft, Alignment textAlignment = Alignment.TopLeft, GUIComponent parent = null, bool wrap = false)
: this (rect, text, null, null, alignment, textAlignment, style, parent, wrap)
{
//hoverColor = style.hoverColor;
@@ -77,7 +77,7 @@ namespace Subsurface
}
public GUITextBlock(Rectangle rect, string text, Color? color, Color? textColor, Alignment textAlignment = Alignment.Left, GUIStyle style = null, GUIComponent parent = null, bool wrap = false)
: this(rect, text,color, textColor, (Alignment.Left | Alignment.Top), textAlignment, style, parent, wrap)
: this(rect, text,color, textColor, Alignment.TopLeft, textAlignment, style, parent, wrap)
{
}

View File

@@ -196,11 +196,16 @@ namespace Subsurface
GUI.Update((float)deltaTime);
if (NetworkMember != null) NetworkMember.Update();
if (NetworkMember != null)
{
NetworkMember.Update();
}
else
{
NetworkEvent.events.Clear();
}
}
CoroutineManager.Update();
}

View File

@@ -117,17 +117,26 @@ namespace Subsurface
listBox.ClearChildren();
characters.Clear();
foreach (CharacterInfo ci in characterInfos)
WayPoint[] waypoints = WayPoint.SelectCrewSpawnPoints(characterInfos);
for (int i = 0; i < waypoints.Length; i++)
{
WayPoint randomWayPoint = WayPoint.GetRandom(SpawnType.Human);
Vector2 position = (randomWayPoint == null) ? Vector2.Zero : randomWayPoint.SimPosition;
Character character = new Character(ci.File, position, ci);
Character character = new Character(characterInfos[i], waypoints[i]);
Character.Controlled = character;
if (!character.Info.StartItemsGiven)
{
character.GiveJobItems();
character.Info.StartItemsGiven = true;
}
AddCharacter(character);
}
if (characters.Count>0) SelectCharacter(characters[0]);
if (characters.Count > 0) SelectCharacter(characters[0]);
}
public void EndShift()

View File

@@ -22,7 +22,7 @@ namespace Subsurface
private GUIFrame guiRoot;
private GUIListBox chatBox;
//private GUIListBox chatBox;
private GUITextBox textBox;
private string savePath;
@@ -59,20 +59,20 @@ namespace Subsurface
map = new Map(Rand.Int(), 500);
int width = 350, height = 100;
if (Game1.NetworkMember!=null)
{
chatBox = new GUIListBox(new Rectangle(
Game1.GraphicsWidth - 20 - width,
Game1.GraphicsHeight - 40 - 25 - height,
width, height),
Color.White * 0.5f, GUI.style, guiRoot);
//int width = 350, height = 100;
//if (Game1.NetworkMember!=null)
//{
// chatBox = new GUIListBox(new Rectangle(
// Game1.GraphicsWidth - 20 - width,
// Game1.GraphicsHeight - 40 - 25 - height,
// width, height),
// Color.White * 0.5f, GUI.style, guiRoot);
textBox = new GUITextBox(
new Rectangle(chatBox.Rect.X, chatBox.Rect.Y + chatBox.Rect.Height + 20, chatBox.Rect.Width, 25),
Color.White * 0.5f, Color.Black, Alignment.Bottom, Alignment.Left, GUI.style, guiRoot);
textBox.OnEnter = EnterChatMessage;
}
// textBox = new GUITextBox(
// new Rectangle(chatBox.Rect.X, chatBox.Rect.Y + chatBox.Rect.Height + 20, chatBox.Rect.Width, 25),
// Color.White * 0.5f, Color.Black, Alignment.Bottom, Alignment.Left, GUI.style, guiRoot);
// textBox.OnEnter = EnterChatMessage;
//}
this.gameMode = gameMode;
//if (gameMode != null && !gameMode.IsSinglePlayer)
@@ -124,7 +124,7 @@ namespace Subsurface
this.level = level;
if (Submarine.Loaded!=submarine) submarine.Load();
if (Submarine.Loaded != submarine) submarine.Load();
if (gameMode!=null) gameMode.Start(duration);
@@ -172,34 +172,35 @@ namespace Subsurface
return true;
}
public bool EnterChatMessage(GUITextBox textBox, string message)
{
if (string.IsNullOrWhiteSpace(message)) return false;
//public bool EnterChatMessage(GUITextBox textBox, string message)
//{
// if (string.IsNullOrWhiteSpace(message)) return false;
else if (Game1.NetworkMember != null)
{
Game1.NetworkMember.SendChatMessage(Game1.NetworkMember.Name + ": " + message);
}
// else if (Game1.NetworkMember != null)
// {
// Game1.NetworkMember.SendChatMessage(Game1.NetworkMember.Name + ": " + message);
// }
textBox.Deselect();
// textBox.Deselect();
return true;
}
// return true;
//}
public void NewChatMessage(string text, Color color)
{
GUITextBlock msg = new GUITextBlock(new Rectangle(0, 0, 0, 20), text,
((chatBox.CountChildren % 2) == 0) ? Color.Transparent : Color.Black * 0.1f, color,
Alignment.Left, null, null, true);
//public void NewChatMessage(string text, Color color)
//{
// GUITextBlock msg = new GUITextBlock(new Rectangle(0, 0, 0, 20), text,
msg.Padding = new Vector4(20.0f, 0, 0, 0);
chatBox.AddChild(msg);
// ((chatBox.CountChildren % 2) == 0) ? Color.Transparent : Color.Black * 0.1f, color,
// Alignment.Left, null, null, true);
while (chatBox.CountChildren > 20)
{
chatBox.RemoveChild(chatBox.children.First());
}
}
// msg.Padding = new Vector4(20.0f, 0, 0, 0);
// chatBox.AddChild(msg);
// while (chatBox.CountChildren > 20)
// {
// chatBox.RemoveChild(chatBox.children.First());
// }
//}
public void Update(float deltaTime)
{

View File

@@ -15,12 +15,12 @@ namespace Subsurface
private GUIButton endShiftButton;
private int day;
//private int day;
public int Day
{
get { return day; }
}
//public int Day
//{
// get { return day; }
//}
bool crewDead;
private float endTimer;
@@ -36,13 +36,13 @@ namespace Subsurface
hireManager.GenerateCharacters("Content/Characters/Human/human.xml", 10);
day = 1;
//day = 1;
}
public SinglePlayerMode(XElement element)
: this(GameModePreset.list.Find(gm => gm.Name == "Single Player"))
{
day = ToolBox.GetAttributeInt(element,"day",1);
//day = ToolBox.GetAttributeInt(element,"day",1);
foreach (XElement subElement in element.Elements())
{
@@ -145,15 +145,17 @@ namespace Subsurface
sb.Append("No casualties!");
}
new GUIMessageBox("Day #" + day + " is over!\n", sb.ToString());
Game1.GameSession.map.MoveToNextLocation();
day++;
//new GUIMessageBox("Day #" + day + " is over!\n", sb.ToString());
//day++;
}
crewManager.EndShift();
for (int i = Character.CharacterList.Count-1; i>=0; i--)
for (int i = Character.CharacterList.Count - 1; i >= 0; i--)
{
Character.CharacterList.RemoveAt(i);
Character.CharacterList[i].Remove();
}
Game1.GameSession.EndShift("");
@@ -163,7 +165,7 @@ namespace Subsurface
public void Save(XElement element)
{
element.Add(new XAttribute("day", day));
//element.Add(new XAttribute("day", day));
crewManager.Save(element);

View File

@@ -46,7 +46,7 @@ namespace Subsurface
/// <summary>
/// If there is room, puts the item in the inventory and returns true, otherwise returns false
/// </summary>
public override bool TryPutItem(Item item, LimbSlot usedSlots, bool createNetworkEvent = true)
public override bool TryPutItem(Item item, LimbSlot allowedSlots, bool createNetworkEvent = true)
{
for (int i = 0; i < capacity; i++)
{
@@ -54,7 +54,7 @@ namespace Subsurface
if (items[i] == item) return true;
}
if (usedSlots.HasFlag(LimbSlot.Any))
if (allowedSlots.HasFlag(LimbSlot.Any))
{
for (int i = 0; i < capacity; i++)
{
@@ -68,12 +68,12 @@ namespace Subsurface
for (int i = 0; i < capacity; i++)
{
if (usedSlots.HasFlag(limbSlots[i]) && items[i]!=null) return false;
if (allowedSlots.HasFlag(limbSlots[i]) && items[i]!=null) return false;
}
for (int i = 0; i < capacity; i++)
{
if (usedSlots.HasFlag(limbSlots[i]) && items[i] == null)
if (allowedSlots.HasFlag(limbSlots[i]) && items[i] == null)
{
PutItem(item, i, createNetworkEvent);
item.Equip(character);

View File

@@ -190,7 +190,7 @@ namespace Subsurface
guiFrame = new GUIFrame(
new Rectangle((int)rect.X, (int)rect.Y, (int)rect.Z, (int)rect.W),
new Color(color.X, color.Y, color.Z), alignment);
new Color(color.X, color.Y, color.Z, color.W), alignment);
//guiFrame.Alpha = color.W;
break;

View File

@@ -59,7 +59,7 @@ namespace Subsurface
return -1;
}
public virtual int CanBePut(Item item)
public virtual int FindAllowedSlot(Item item)
{
for (int i = 0; i < capacity; i++)
{
@@ -84,9 +84,9 @@ namespace Subsurface
/// <summary>
/// If there is room, puts the item in the inventory and returns true, otherwise returns false
/// </summary>
public virtual bool TryPutItem(Item item, LimbSlot usedSlots = 0, bool createNetworkEvent = true)
public virtual bool TryPutItem(Item item, LimbSlot allowedSlots = 0, bool createNetworkEvent = true)
{
int slot = CanBePut(item);
int slot = FindAllowedSlot(item);
if (slot < 0) return false;
PutItem(item, slot, createNetworkEvent);
@@ -268,8 +268,8 @@ namespace Subsurface
Vector2 pos = new Vector2(rect.X + rect.Width / 2, rect.Y - rect.Height + 20) - GUI.font.MeasureString(item.Name)*0.5f;
pos.X = (int)pos.X;
pos.Y = (int)pos.Y;
spriteBatch.DrawString(GUI.font, item.Name, pos - new Vector2(1.0f,1.0f), Color.Black);
spriteBatch.DrawString(GUI.font, item.Name, pos, Color.White);
spriteBatch.DrawString(GUI.font, item.Name + " - "+item.ID, pos - new Vector2(1.0f,1.0f), Color.Black);
spriteBatch.DrawString(GUI.font, item.Name + " - " + item.ID, pos, Color.White);
}
if (item.Condition < 100.0f)

View File

@@ -13,7 +13,7 @@ namespace Subsurface
this.container = container;
}
public override int CanBePut(Item item)
public override int FindAllowedSlot(Item item)
{
for (int i = 0; i < capacity; i++)
{

View File

@@ -45,7 +45,7 @@ namespace Subsurface
{
//give an unique ID
bool IDfound;
id = 0;
id = 1;//Rand.Int(int.MaxValue);
do
{
id += 1;

View File

@@ -19,6 +19,10 @@ namespace Subsurface
private int seed;
private int size;
private Texture2D iceTexture;
private Texture2D iceCraters;
private Texture2D iceCrack;
private Location currentLocation;
private Location selectedLocation;
@@ -34,49 +38,12 @@ namespace Subsurface
connections = new List<LocationConnection>();
iceTexture = Game1.textureLoader.FromFile("Content/Map/iceSurface.png");
iceCraters = Game1.textureLoader.FromFile("Content/Map/iceCraters.png");
iceCrack = Game1.textureLoader.FromFile("Content/Map/iceCrack.png");
GenerateLocations();
//for (int i = 0; i<10; i++)
//{
// Vector2 pos = new Vector2((float)Game1.random.NextDouble() * size, (float)Game1.random.NextDouble() * size);
// Location location =
// locations.Add(location);
//}
//for (int i = 0; i < 10; i++)
//{
// int closestIndex = 0;
// float closestDistance = 0.0f;
// for (int j = 0; j<10; j++)
// {
// if (j == i) continue;
// //ignore if already connected
// bool alreadyConnected = false;
// foreach (LocationConnection connection in connections)
// {
// if (connection.Locations.Contains(locations[i]) && connection.Locations.Contains(locations[j]))
// {
// alreadyConnected = true;
// break;
// }
// }
// if (alreadyConnected) continue;
// float dist = Vector2.Distance(locations[i].MapPosition, locations[j].MapPosition);
// if (closestDistance > 0.0f && dist > closestDistance) continue;
// closestDistance = dist;
// closestIndex = j;
// }
// connections.Add(new LocationConnection(locations[i], locations[closestIndex], level));
//}
currentLocation = locations[locations.Count/2];
}
@@ -97,6 +64,12 @@ namespace Subsurface
{
if (edge.point1 == edge.point2) continue;
//remove points from the edge of the map
if (edge.point1.X == 0 || edge.point1.X == size) continue;
if (edge.point1.Y == 0 || edge.point1.Y == size) continue;
if (edge.point2.X == 0 || edge.point2.X == size) continue;
if (edge.point2.Y == 0 || edge.point2.Y == size) continue;
Location[] newLocations = new Location[2];
newLocations[0] = locations.Find(l => l.MapPosition == edge.point1 || l.MapPosition == edge.point2);
newLocations[1] = locations.Find(l => l != newLocations[0] && (l.MapPosition == edge.point1 || l.MapPosition == edge.point2));
@@ -117,6 +90,8 @@ namespace Subsurface
}
connections.Add(new LocationConnection(newLocations[0], newLocations[1], Level.CreateRandom()));
}
float minDistance = 50.0f;
@@ -124,40 +99,103 @@ namespace Subsurface
{
LocationConnection connection = connections[i];
if (Vector2.Distance(connection.Locations[0].MapPosition, connection.Locations[1].MapPosition) > minDistance) continue;
if (Vector2.Distance(connection.Locations[0].MapPosition, connection.Locations[1].MapPosition) > minDistance)
{
continue;
}
locations.Remove(connection.Locations[0]);
connections.Remove(connection);
foreach (LocationConnection connection2 in connections)
{
if (connection == connection2) continue;
if (connection2.Locations[0] == connection.Locations[0]) connection2.Locations[0] = connection.Locations[1];
if (connection2.Locations[1] == connection.Locations[0]) connection2.Locations[1] = connection.Locations[1];
}
}
for (int i = connections.Count - 1; i >= 0; i--)
{
LocationConnection connection = connections[i];
for (int n = i-1; n >= 0; n--)
{
if (connection.Locations.Contains(connections[n].Locations[0])
&& connection.Locations.Contains(connections[n].Locations[1]))
{
connections.RemoveAt(i);
}
}
}
foreach (LocationConnection connection in connections)
{
Vector2 start = connection.Locations[0].MapPosition;
Vector2 end = connection.Locations[1].MapPosition;
int generations = (int)(Math.Sqrt(Vector2.Distance(start, end) / 10.0f));
connection.CrackSegments = GenerateCrack(start, end, generations);
}
}
private List<Vector2[]> GenerateCrack(Vector2 start, Vector2 end, int generations)
{
List<Vector2[]> segments = new List<Vector2[]>();
segments.Add(new Vector2[] {start, end});
float offsetAmount = 5.0f;
for (int n = 0; n<generations; n++)
{
for (int i = 0; i<segments.Count; i++)
{
Vector2 startSegment = segments[i][0];
Vector2 endSegment = segments[i][1];
segments.RemoveAt(i);
Vector2 midPoint = (startSegment + endSegment) / 2.0f;
Vector2 normal = Vector2.Normalize(endSegment - startSegment);
normal = new Vector2(-normal.Y, normal.X);
midPoint += normal * Rand.Range(-offsetAmount, offsetAmount);
segments.Insert(i, new Vector2[] { startSegment, midPoint });
segments.Insert(i+1, new Vector2[] { midPoint, endSegment });
i++;
}
}
return segments;
}
public void MoveToNextLocation()
{
currentLocation = selectedLocation;
selectedLocation = null;
}
private Location highlightedLocation;
public void Draw(SpriteBatch spriteBatch, Rectangle rect)
{
GUI.DrawRectangle(spriteBatch, rect, Color.DarkBlue, true);
//GUI.DrawRectangle(spriteBatch, rect, Color.DarkBlue, true);
spriteBatch.Draw(iceTexture, rect, Color.White);
Vector2 rectCorner = new Vector2(rect.X, rect.Y);
Vector2 scale = new Vector2((float)rect.Width/ size, (float)rect.Height/size);
float maxDist = 20.0f;
float closestDist = 0.0f;
Location highlightedLocation = null;
foreach (Location location in locations)
highlightedLocation = null;
for (int i = 0; i < locations.Count;i++ )
{
Vector2 pos = location.MapPosition * scale;
GUI.DrawRectangle(spriteBatch, new Rectangle(rect.X + (int)pos.X, rect.Y + (int)pos.Y, 5, 5), Color.White, true);
Location location = locations[i];
Vector2 pos = rectCorner + location.MapPosition * scale;
if (currentLocation == location)
{
GUI.DrawRectangle(spriteBatch, new Rectangle(rect.X + (int)pos.X - 4, rect.Y + (int)pos.Y - 4, 5+8, 5+8), Color.Red, false);
}
float dist = Vector2.Distance(PlayerInput.MousePosition, new Vector2(rect.X + pos.X, rect.Y + pos.Y));
float dist = Vector2.Distance(PlayerInput.MousePosition, new Vector2(pos.X, pos.Y));
if (dist < maxDist && (highlightedLocation == null || dist < closestDist))
{
closestDist = dist;
@@ -165,55 +203,78 @@ namespace Subsurface
}
}
if (highlightedLocation!=null)
{
Vector2 pos = highlightedLocation.MapPosition * scale;
pos.X = (int)pos.X;
pos.Y = (int)pos.Y;
spriteBatch.DrawString(GUI.font, highlightedLocation.Name, pos + new Vector2(rect.X - 50, rect.Y), Color.White);
GUI.DrawRectangle(spriteBatch, new Rectangle(rect.X + (int)pos.X - 4, rect.Y + (int)pos.Y - 4, 5 + 8, 5 + 8), Color.White, false);
}
if (selectedLocation != null)
{
Vector2 pos = selectedLocation.MapPosition * scale;
pos.X = (int)pos.X;
pos.Y = (int)pos.Y;
spriteBatch.DrawString(GUI.font, selectedLocation.Name, pos + new Vector2(rect.X - 50, rect.Y), Color.White);
GUI.DrawRectangle(spriteBatch, new Rectangle(rect.X + (int)pos.X - 4, rect.Y + (int)pos.Y - 4, 5 + 8, 5 + 8), Color.White, false);
}
Vector2 rectCorner = new Vector2(rect.X, rect.Y);
foreach (LocationConnection connection in connections)
{
GUI.DrawLine(spriteBatch,
connection.Locations[0].MapPosition * scale + rectCorner,
connection.Locations[1].MapPosition * scale + rectCorner, Color.LightGray);
if (highlightedLocation!=currentLocation &&
Color crackColor = Color.White;
if (highlightedLocation != currentLocation &&
connection.Locations.Contains(highlightedLocation) && connection.Locations.Contains(currentLocation))
{
GUI.DrawLine(spriteBatch,
connection.Locations[0].MapPosition * scale + rectCorner +Vector2.One,
connection.Locations[1].MapPosition * scale + rectCorner + Vector2.One, Color.White);
crackColor = Color.Red;
if (PlayerInput.LeftButtonClicked())
if(selectedLocation!=highlightedLocation && highlightedLocation!=null)
if (PlayerInput.LeftButtonClicked()&&
selectedLocation != highlightedLocation && highlightedLocation != null)
{
//currentLocation = highlightedLocation;
Game1.LobbyScreen.SelectLocation(highlightedLocation, connection);
selectedLocation = highlightedLocation;
}
selectedLocation = highlightedLocation;
}
}
if (selectedLocation != currentLocation &&
(connection.Locations.Contains(selectedLocation) && connection.Locations.Contains(currentLocation)))
{
GUI.DrawLine(spriteBatch,
connection.Locations[0].MapPosition * scale + rectCorner + Vector2.One,
connection.Locations[1].MapPosition * scale + rectCorner + Vector2.One, Color.White);
crackColor = Color.Red;
}
foreach (Vector2[] segment in connection.CrackSegments)
{
Vector2 start = segment[0] * scale + rectCorner;
Vector2 end = segment[1] * scale + rectCorner;
float dist = Vector2.Distance(start, end);
//spriteBatch.Draw(iceCrack,
// new Rectangle((int)((start.X + end.X) / 2.0f), (int)((start.Y + end.Y) / 2.0f), (int)dist, 30),
// new Rectangle(0, 0, iceCrack.Width, 60), crackColor, MathUtils.VectorToAngle(start - end),
// new Vector2(dist / 2, 30), SpriteEffects.None, 0.01f);
GUI.DrawLine(spriteBatch,
segment[0] * scale + rectCorner,
segment[1] * scale + rectCorner, crackColor);
}
}
for (int i = 0; i < locations.Count; i++)
{
Location location = locations[i];
Vector2 pos = rectCorner + location.MapPosition * scale;
int imgIndex = i % 16;
int xCell = imgIndex % 4;
int yCell = (int)Math.Floor(imgIndex / 4.0f);
spriteBatch.Draw(iceCraters, pos,
new Rectangle(xCell * 64, yCell * 64, 64, 64),
Color.White, i,
new Vector2(32, 32), 0.5f*scale, SpriteEffects.None, 0.0f);
}
for (int i = 0; i < 3; i++ )
{
Location location = (i == 0) ? highlightedLocation : selectedLocation;
if (i == 2) location = currentLocation;
if (location == null) continue;
Vector2 pos = rectCorner + location.MapPosition * scale;
pos.X = (int)pos.X;
pos.Y = (int)pos.Y;
if (highlightedLocation==location)
{
spriteBatch.DrawString(GUI.font, location.Name, pos + new Vector2(-50, -20), Color.DarkRed);
}
GUI.DrawRectangle(spriteBatch, new Rectangle((int)pos.X - 4, (int)pos.Y - 4, 5 + 8, 5 + 8), Color.DarkRed, false);
}
}
@@ -222,8 +283,10 @@ namespace Subsurface
class LocationConnection
{
Location[] locations;
Level level;
private Location[] locations;
private Level level;
public List<Vector2[]> CrackSegments;
public Location[] Locations
{

View File

@@ -820,7 +820,7 @@ namespace Subsurface
}
}
ID = 1;
//ID = 1;
loaded = this;
}
@@ -838,8 +838,7 @@ namespace Subsurface
public static void Unload()
{
if (loaded == null) return;
loaded.Remove();
loaded.Clear();

View File

@@ -13,16 +13,35 @@ namespace Subsurface
public enum SpawnType { None, Human, Enemy };
class WayPoint : MapEntity
{
public static List<WayPoint> WayPointList = new List<WayPoint>();
private SpawnType spawnType;
//characters spawning at the waypoint will be given an ID card with these tags
private string[] idCardTags;
//only characters with this job will be spawned at the waypoint
private JobPrefab assignedJob;
public SpawnType SpawnType
{
get { return spawnType; }
set { spawnType = value; }
}
public string[] IdCardTags
{
get { return idCardTags; }
private set
{
idCardTags = value;
for (int i = 0; i<idCardTags.Length; i++)
{
idCardTags[i] = idCardTags[i].Trim();
}
}
}
public override Vector2 SimPosition
{
get { return ConvertUnits.ToSimUnits(new Vector2(rect.X, rect.Y)); }
@@ -32,8 +51,10 @@ namespace Subsurface
{
rect = newRect;
linkedTo = new ObservableCollection<MapEntity>();
idCardTags = new string[0];
mapEntityList.Add(this);
WayPointList.Add(this);
}
public override void Draw(SpriteBatch spriteBatch, bool editing)
@@ -54,17 +75,13 @@ namespace Subsurface
public override void DrawEditing(SpriteBatch spriteBatch, Camera cam)
{
int x = 300, y = 10;
if (editingHUD==null)
{
editingHUD = CreateEditingHUD();
}
spriteBatch.DrawString(GUI.font, "Editing waypoint", new Vector2(x, y), Color.Black);
spriteBatch.DrawString(GUI.font, "Hold space to link to another entity", new Vector2(x, y + 20), Color.Black);
spriteBatch.DrawString(GUI.font, "Spawnpoint: "+spawnType.ToString()+" +/-", new Vector2(x, y + 40), Color.Black);
if (PlayerInput.KeyHit(Keys.Add)) spawnType += 1;
if (PlayerInput.KeyHit(Keys.Subtract)) spawnType -= 1;
if (spawnType > SpawnType.Enemy) spawnType = SpawnType.None;
if (spawnType < SpawnType.None) spawnType = SpawnType.Enemy;
editingHUD.Update((float)Physics.step);
editingHUD.Draw(spriteBatch);
if (!PlayerInput.LeftButtonClicked()) return;
@@ -82,18 +99,105 @@ namespace Subsurface
}
}
public static WayPoint GetRandom(SpawnType spawnType = SpawnType.None)
private bool ChangeSpawnType(GUIButton button, object obj)
{
GUITextBlock spawnTypeText = button.Parent as GUITextBlock;
spawnType += (int)button.UserData;
if (spawnType > SpawnType.Enemy) spawnType = SpawnType.None;
if (spawnType < SpawnType.None) spawnType = SpawnType.Enemy;
spawnTypeText.Text = spawnType.ToString();
return true;
}
private bool EnterIDCardTags(GUITextBox textBox, string text)
{
IdCardTags = text.Split(',');
textBox.Text = text;
textBox.Color = Color.White;
return true;
}
private bool EnterAssignedJob(GUITextBox textBox, string text)
{
string trimmedName = text.ToLower().Trim();
assignedJob = JobPrefab.List.Find(jp => jp.Name.ToLower() == trimmedName);
if (assignedJob !=null && trimmedName!="none")
{
textBox.Color = Color.White;
textBox.Text = (assignedJob == null) ? "None" : assignedJob.Name;
}
return true;
}
private bool TextBoxChanged(GUITextBox textBox, string text)
{
textBox.Color = Color.Red;
return true;
}
private GUIComponent CreateEditingHUD(bool inGame = false)
{
int width = 500;
int x = Game1.GraphicsWidth / 2 - width / 2, y = 10;
editingHUD = new GUIFrame(new Rectangle(x, y, width, 150), Color.Black * 0.5f);
editingHUD.Padding = new Vector4(10, 10, 0, 0);
editingHUD.UserData = this;
new GUITextBlock(new Rectangle(0, 0, 100, 20), "Editing waypoint", GUI.style, editingHUD);
new GUITextBlock(new Rectangle(0, 20, 100, 20), "Hold space to link to another entity", GUI.style, editingHUD);
new GUITextBlock(new Rectangle(0, 40, 100, 20), "Spawnpoint: ", GUI.style, editingHUD);
var spawnTypeText = new GUITextBlock(new Rectangle(0, 40, 200, 20), spawnType.ToString(), GUI.style, Alignment.Right, Alignment.TopLeft, editingHUD);
var button = new GUIButton(new Rectangle(-30,0,20,20), "-", Alignment.Right, GUI.style, spawnTypeText);
button.UserData = -1;
button.OnClicked = ChangeSpawnType;
button = new GUIButton(new Rectangle(0, 0, 20, 20), "+", Alignment.Right, GUI.style, spawnTypeText);
button.UserData = 1;
button.OnClicked = ChangeSpawnType;
//spriteBatch.DrawString(GUI.font, "Spawnpoint: " + spawnType.ToString() + " +/-", new Vector2(x, y + 40), Color.Black);
y = 40+20;
new GUITextBlock(new Rectangle(0, y, 100, 20), "ID Card tags:", Color.Transparent, Color.Black, Alignment.TopLeft, null, editingHUD);
GUITextBox propertyBox = new GUITextBox(new Rectangle(100, y, 200, 20), GUI.style, editingHUD);
propertyBox.Text = string.Join(", ", idCardTags);
propertyBox.OnEnter = EnterIDCardTags;
propertyBox.OnTextChanged = TextBoxChanged;
y = y + 30;
new GUITextBlock(new Rectangle(0, y, 100, 20), "Assigned job:", Color.Transparent, Color.Black, Alignment.TopLeft, null, editingHUD);
propertyBox = new GUITextBox(new Rectangle(100, y, 200, 20), GUI.style, editingHUD);
propertyBox.Text = (assignedJob == null) ? "None" : assignedJob.Name;
propertyBox.OnEnter = EnterAssignedJob;
propertyBox.OnTextChanged = TextBoxChanged;
y = y + 30;
return editingHUD;
}
public static WayPoint GetRandom(SpawnType spawnType = SpawnType.None, Job assignedJob = null)
{
List<WayPoint> wayPoints = new List<WayPoint>();
foreach (MapEntity e in mapEntityList)
foreach (WayPoint wp in WayPointList)
{
WayPoint wayPoint = e as WayPoint;
if (wayPoint==null) continue;
if (spawnType != SpawnType.None && wayPoint.spawnType != spawnType) continue;
if (spawnType != SpawnType.None && wp.spawnType != spawnType) continue;
if (assignedJob != null && wp.assignedJob != assignedJob.Prefab) continue;
wayPoints.Add(wayPoint);
wayPoints.Add(wp);
}
if (!wayPoints.Any()) return null;
@@ -101,6 +205,55 @@ namespace Subsurface
return wayPoints[Rand.Int(wayPoints.Count())];
}
public static WayPoint[] SelectCrewSpawnPoints(List<CharacterInfo> crew)
{
List<WayPoint> unassignedWayPoints = new List<WayPoint>();
foreach (WayPoint wp in WayPointList)
{
if (wp.spawnType == SpawnType.Human) unassignedWayPoints.Add(wp);
}
WayPoint[] assignedWayPoints = new WayPoint[crew.Count];
for (int i = 0; i < crew.Count; i++ )
{
//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);
break;
}
}
//go through the crewmembers that don't have a spawnpoint yet (if any)
for (int i = 0; i < crew.Count; i++)
{
if (assignedWayPoints[i] != null) continue;
//try to assign a spawnpoint that matches the job, even if the spawnpoint is already assigned to someone else
foreach (WayPoint wp in WayPointList)
{
if (wp.spawnType != SpawnType.Human || wp.assignedJob != crew[i].Job.Prefab) continue;
assignedWayPoints[i] = wp;
break;
}
if (assignedWayPoints[i] != null) continue;
//everything else failed -> just give a random spawnpoint
assignedWayPoints[i] = GetRandom(SpawnType.Human);
}
return assignedWayPoints;
}
public override XElement Save(XDocument doc)
{
XElement element = new XElement("WayPoint");
@@ -110,6 +263,16 @@ namespace Subsurface
new XAttribute("y", rect.Y),
new XAttribute("spawn", spawnType));
if (idCardTags.Length > 0)
{
element.Add(new XAttribute("idcardtags", string.Join(",", idCardTags)));
}
if (assignedJob != null)
{
element.Add(new XAttribute("job", assignedJob.Name));
}
doc.Root.Add(element);
if (linkedTo != null)
@@ -138,6 +301,18 @@ namespace Subsurface
w.spawnType = (SpawnType)Enum.Parse(typeof(SpawnType),
ToolBox.GetAttributeString(element, "spawn", "None"));
string idCardTagString = ToolBox.GetAttributeString(element, "idcardtags", "");
if (!string.IsNullOrWhiteSpace(idCardTagString))
{
w.IdCardTags = idCardTagString.Split(',');
}
string jobName = ToolBox.GetAttributeString(element, "job", "").ToLower();
if (!string.IsNullOrWhiteSpace(jobName))
{
w.assignedJob = JobPrefab.List.Find(jp => jp.Name.ToLower() == jobName);
}
w.linkedToID = new List<int>();
int i = 0;
while (element.Attribute("linkedto" + i) != null)
@@ -146,6 +321,13 @@ namespace Subsurface
i += 1;
}
}
public override void Remove()
{
base.Remove();
WayPointList.Remove(this);
}
}
}

View File

@@ -15,7 +15,15 @@ namespace Subsurface.Networking
private Character myCharacter;
private CharacterInfo characterInfo;
GUIMessageBox reconnectBox;
private bool connected;
private int myID;
List<Client> otherClients;
private string serverIP;
public Character Character
{
@@ -37,8 +45,10 @@ namespace Subsurface.Networking
otherClients = new List<Client>();
}
public bool ConnectToServer(string hostIP)
public void ConnectToServer(string hostIP)
{
serverIP = hostIP;
myCharacter = Character.Controlled;
// Create new instance of configs. Parameter is "application Id". It has to be same on client and server.
@@ -65,7 +75,7 @@ namespace Subsurface.Networking
catch (ArgumentNullException e)
{
DebugConsole.ThrowError("Couldn't connect to "+hostIP+". Error message: "+e.Message);
return false;
return;
}
// Create timespan of 30ms
@@ -78,27 +88,24 @@ namespace Subsurface.Networking
//update.Elapsed += new System.Timers.ElapsedEventHandler(Update);
// Funtion that waits for connection approval info from server
WaitForStartingInfo();
if (Client.ConnectionStatus != NetConnectionStatus.Connected)
{
DebugConsole.ThrowError("Couldn't connect to server");
return false;
}
else
{
return true;
}
CoroutineManager.StartCoroutine(WaitForStartingInfo());
// Start the timer
//update.Start();
}
private bool RetryConnection(GUIButton button, object obj)
{
ConnectToServer(serverIP);
return true;
}
// Before main looping starts, we loop here and wait for approval message
private void WaitForStartingInfo()
private IEnumerable<Status> WaitForStartingInfo()
{
reconnectBox = new GUIMessageBox("CONNECTING", "Connecting to "+serverIP, new string[0]);
// When this is set to true, we are approved and ready to go
bool CanStart = false;
@@ -107,7 +114,9 @@ namespace Subsurface.Networking
// Loop untill we are approved
while (!CanStart)
{
if (DateTime.Now>timeOut) return;
yield return Status.Running;
if (DateTime.Now > timeOut) break;
NetIncomingMessage inc;
// If new messages arrived
@@ -120,7 +129,9 @@ namespace Subsurface.Networking
case NetIncomingMessageType.Data:
if (inc.ReadByte() == (byte)PacketTypes.LoggedIn)
{
int myID = inc.ReadInt32();
myID = inc.ReadInt32();
Game1.NetLobbyScreen.ClearPlayers();
//add the names of other connected clients to the lobby screen
int existingClients = inc.ReadInt32();
@@ -149,19 +160,50 @@ namespace Subsurface.Networking
break;
default:
// Should not happen and if happens, don't care
Console.WriteLine(inc.ReadString() + " Strange message");
break;
}
}
}
if (reconnectBox != null)
{
reconnectBox.Close(null, null);
reconnectBox = null;
}
if (Client.ConnectionStatus != NetConnectionStatus.Connected)
{
reconnectBox = new GUIMessageBox("CONNECTION FAILED", "Failed to connect to server.", new string[] { "Retry", "Cancel" });
reconnectBox.Buttons[0].OnClicked += RetryConnection;
reconnectBox.Buttons[0].OnClicked += reconnectBox.Close;
}
else
{
Game1.NetLobbyScreen.Select();
connected = true;
}
yield return Status.Success;
}
public override void Update()
{
if (updateTimer > DateTime.Now) return;
if (myCharacter!=null)
if (!connected || updateTimer > DateTime.Now) return;
if (reconnectBox != null)
{
ConnectToServer(serverIP);
return;
}
if (Client.ConnectionStatus == NetConnectionStatus.Disconnected)
{
reconnectBox = new GUIMessageBox("CONNECTION LOST", "You have been disconnected from the server. Reconnecting...", new string[0]);
return;
}
if (myCharacter != null)
{
if (myCharacter.IsDead)
{
@@ -190,7 +232,6 @@ namespace Subsurface.Networking
NetworkEvent.events.Clear();
CheckServerMessages();
// Update current time
@@ -236,13 +277,20 @@ namespace Subsurface.Networking
Game1.GameSession = new GameSession(Submarine.Loaded);
Game1.GameSession.StartShift(duration, levelSeed);
myCharacter = ReadCharacterData(inc);
Character.Controlled = myCharacter;
//myCharacter = ReadCharacterData(inc);
//Character.Controlled = myCharacter;
int count = inc.ReadInt32();
for (int n = 0; n < count; n++)
{
ReadCharacterData(inc);
int id = inc.ReadInt32();
Character newCharacter = ReadCharacterData(inc);
if (id == myID)
{
myCharacter = newCharacter;
Character.Controlled = myCharacter;
}
}
gameStarted = true;
@@ -275,7 +323,7 @@ namespace Subsurface.Networking
case (byte)PacketTypes.KickedOut:
string msg = inc.ReadString();
DebugConsole.ThrowError(msg);
new GUIMessageBox("KICKED", msg);
Game1.MainMenuScreen.Select();
@@ -296,8 +344,8 @@ namespace Subsurface.Networking
case (byte)PacketTypes.Traitor:
string targetName = inc.ReadString();
Game1.GameSession.NewChatMessage("You are an agent of Ordo Europae", messageColor[(int)ChatMessageType.Server]);
Game1.GameSession.NewChatMessage("Your secret task is to assassinate " + targetName + "!", messageColor[(int)ChatMessageType.Server]);
new GUIMessageBox("You are the Traitor!", "Your secret task is to assassinate " + targetName + "!");
break;
}
@@ -356,20 +404,37 @@ namespace Subsurface.Networking
bool isFemale = inc.ReadBoolean();
int inventoryID = inc.ReadInt32();
int headSpriteID = inc.ReadInt32();
int headSpriteID = inc.ReadInt32();
Vector2 position = new Vector2(inc.ReadFloat(), inc.ReadFloat());
string jobName = inc.ReadString();
JobPrefab jobPrefab = JobPrefab.List.Find(jp => jp.Name == jobName);
Vector2 position = new Vector2(inc.ReadFloat(), inc.ReadFloat());
CharacterInfo ch = new CharacterInfo("Content/Characters/Human/human.xml", newName, isFemale ? Gender.Female : Gender.Male, jobPrefab);
ch.HeadSpriteId = headSpriteID;
Character character = new Character(ch, position);
WayPoint closestWaypoint = null;
float closestDist = 0.0f;
foreach (WayPoint wp in WayPoint.WayPointList)
{
float dist = Vector2.Distance(wp.SimPosition, position);
if (closestWaypoint != null && dist > closestDist) continue;
closestWaypoint = wp;
closestDist = dist;
continue;
}
Character character = (closestWaypoint == null) ?
new Character(ch, position) :
new Character(ch, closestWaypoint);
character.ID = ID;
character.Inventory.ID = inventoryID;
character.GiveJobItems();
return character;
}

View File

@@ -291,7 +291,9 @@ namespace Subsurface.Networking
Game1.GameSession = new GameSession(selectedMap, Game1.NetLobbyScreen.SelectedMode);
Game1.GameSession.StartShift(Game1.NetLobbyScreen.GameDuration, Game1.NetLobbyScreen.LevelSeed);
//EventManager.SelectEvent(Game1.netLobbyScreen.SelectedEvent);
List<CharacterInfo> characterInfos = new List<CharacterInfo>();
foreach (Client client in connectedClients)
{
client.inGame = true;
@@ -302,10 +304,21 @@ namespace Subsurface.Networking
{
client.characterInfo = new CharacterInfo("Content/Characters/Human/human.xml", client.name);
}
characterInfos.Add(client.characterInfo);
client.character = new Character(client.characterInfo, (spawnPoint == null) ? Vector2.Zero : spawnPoint.SimPosition, true);
//client.character = new Character(client.characterInfo, (spawnPoint == null) ? Vector2.Zero : spawnPoint.SimPosition, true);
}
WayPoint[] assignedWayPoints = WayPoint.SelectCrewSpawnPoints(characterInfos);
for (int i = 0; i < connectedClients.Count; i++ )
{
connectedClients[i].character = new Character(
connectedClients[i].characterInfo, assignedWayPoints[i], true);
connectedClients[i].character.GiveJobItems();
}
//todo: fix
if (myClient != null)
{
WayPoint spawnPoint = WayPoint.GetRandom(SpawnType.Human);
@@ -313,37 +326,38 @@ namespace Subsurface.Networking
myClient.character = new Character(ch, (spawnPoint == null) ? Vector2.Zero : spawnPoint.SimPosition);
}
//foreach (Client client in connectedClients)
//{
NetOutgoingMessage msg = Server.CreateMessage();
msg.Write((byte)PacketTypes.StartGame);
msg.Write(seed);
msg.Write(Game1.NetLobbyScreen.LevelSeed);
msg.Write(Game1.NetLobbyScreen.SelectedMap.Name);
msg.Write(Game1.NetLobbyScreen.SelectedMap.Hash.MD5Hash);
msg.Write(Game1.NetLobbyScreen.GameDuration.TotalMinutes);
//WriteCharacterData(msg, client.name, client.character);
msg.Write((myClient == null) ? connectedClients.Count : connectedClients.Count+1);
foreach (Client client in connectedClients)
{
NetOutgoingMessage msg = Server.CreateMessage();
msg.Write((byte)PacketTypes.StartGame);
msg.Write(seed);
msg.Write(Game1.NetLobbyScreen.LevelSeed);
msg.Write(Game1.NetLobbyScreen.SelectedMap.Name);
msg.Write(Game1.NetLobbyScreen.SelectedMap.Hash.MD5Hash);
msg.Write(Game1.NetLobbyScreen.GameDuration.TotalMinutes);
//if (otherClient == client) continue;
msg.Write(client.ID);
WriteCharacterData(msg, client.name, client.character);
msg.Write((myClient == null) ? connectedClients.Count - 1 : connectedClients.Count);
foreach (Client otherClient in connectedClients)
{
if (otherClient == client) continue;
WriteCharacterData(msg, otherClient.name, otherClient.character);
}
if (myClient!=null)
{
WriteCharacterData(msg, myClient.name, myClient.character);
}
Server.SendMessage(msg, client.Connection, NetDeliveryMethod.ReliableUnordered, 0);
}
if (myClient!=null)
{
WriteCharacterData(msg, myClient.name, myClient.character);
}
SendMessage(msg, NetDeliveryMethod.ReliableUnordered, null);
//}
gameStarted = true;
Game1.GameScreen.Cam.TargetPos = Vector2.Zero;
@@ -580,7 +594,7 @@ namespace Subsurface.Networking
//if there's enough crew members assigned to the job already, continue
if (assignedClientCount[jobIndex] >= JobPrefab.List[jobIndex].MaxNumber) continue;
unassigned[i].assignedJob = JobPrefab.List[i];
unassigned[i].assignedJob = JobPrefab.List[jobIndex];
assignedClientCount[jobIndex]++;
unassigned.RemoveAt(i);

View File

@@ -103,11 +103,12 @@ namespace Subsurface.Networking
DebugConsole.ThrowError("Received invalid network message");
return false;
}
//288=id, 280=char
Entity e = Entity.FindEntityByID(id);
if (e == null)
{
//DebugConsole.ThrowError("Couldn't find an entity matching the ID ''" + id + "''");
return false;
}

View File

@@ -28,13 +28,16 @@ namespace Subsurface.Networking
class NetworkMember
{
protected static Color[] messageColor = { Color.Black, Color.DarkRed, Color.DarkBlue, Color.DarkGreen };
protected static Color[] messageColor = { Color.White, Color.Red, Color.LightBlue, Color.LightGreen };
protected string name;
protected TimeSpan updateInterval;
protected DateTime updateTimer;
protected GUIFrame inGameHUD;
protected GUIListBox chatBox;
protected bool gameStarted;
public string Name
@@ -46,11 +49,56 @@ namespace Subsurface.Networking
name = value;
}
}
public GUIFrame InGameHUD
{
get { return inGameHUD; }
}
public NetworkMember()
{
inGameHUD = new GUIFrame(new Rectangle(0,0,0,0), null, null);
int width = 350, height = 100;
chatBox = new GUIListBox(new Rectangle(
Game1.GraphicsWidth - 20 - width,
Game1.GraphicsHeight - 40 - 25 - height,
width, height),
Color.White * 0.5f, GUI.style, inGameHUD);
var textBox = new GUITextBox(
new Rectangle(chatBox.Rect.X, chatBox.Rect.Y + chatBox.Rect.Height + 20, chatBox.Rect.Width, 25),
Color.White * 0.5f, Color.Black, Alignment.TopLeft, Alignment.Left, GUI.style, inGameHUD);
textBox.OnEnter = EnterChatMessage;
}
public bool EnterChatMessage(GUITextBox textBox, string message)
{
if (string.IsNullOrWhiteSpace(message)) return false;
SendChatMessage(Game1.NetworkMember.Name + ": " + message);
textBox.Deselect();
return true;
}
public void AddChatMessage(string message, ChatMessageType messageType)
{
Game1.NetLobbyScreen.NewChatMessage(message, messageColor[(int)messageType]);
if (Game1.GameSession != null) Game1.GameSession.NewChatMessage(message, messageColor[(int)messageType]);
GUITextBlock msg = new GUITextBlock(new Rectangle(0, 0, 0, 20), message,
((chatBox.CountChildren % 2) == 0) ? Color.Transparent : Color.Black * 0.1f, messageColor[(int)messageType],
Alignment.Left, null, null, true);
msg.Padding = new Vector4(20.0f, 0, 0, 0);
chatBox.AddChild(msg);
while (chatBox.CountChildren > 20)
{
chatBox.RemoveChild(chatBox.children[0]);
}
GUI.PlayMessageSound();
}

View File

@@ -198,22 +198,21 @@ namespace Subsurface
hireList.ClearChildren();
foreach (CharacterInfo c in gameMode.hireManager.availableCharacters)
{
GUIFrame frame = new GUIFrame(
new Rectangle(0, 0, 0, 25), Color.White, Alignment.Left, null, hireList);
frame.UserData = c;
frame.Padding = new Vector4(10.0f, 0.0f, 10.0f, 0.0f);
//GUIFrame frame = new GUIFrame(
// new Rectangle(0, 0, 0, 25), Color.Transparent, null, hireList);
//frame.UserData = c;
//frame.Padding = new Vector4(10.0f, 0.0f, 10.0f, 0.0f);
GUITextBlock textBlock = new GUITextBlock(
new Rectangle(0, 0, 0, 25),
c.Name + " (" + c.Job.Name + ")",
Color.Transparent, Color.Black,
Alignment.Left, null, frame);
c.Name + " (" + c.Job.Name + ")", GUI.style, hireList);
textBlock.UserData = c;
textBlock = new GUITextBlock(
new Rectangle(0, 0, 0, 25),
c.Salary.ToString(),
Color.Transparent, Color.Black,
Alignment.Right, null, frame);
null, null,
Alignment.TopRight, GUI.style, textBlock);
}
}
@@ -257,7 +256,7 @@ namespace Subsurface
spriteBatch.End();
if (characterList.SelectedData != null)
if (characterList.SelectedData != null && selectedRightPanel == (int)PanelTab.Crew)
{
if (previewCharacter != null)
{

View File

@@ -222,16 +222,18 @@ namespace Subsurface
if (string.IsNullOrEmpty(ipBox.Text)) return false;
Game1.NetworkMember = new GameClient(nameBox.Text);
if (Game1.Client.ConnectToServer(ipBox.Text))
{
Game1.NetLobbyScreen.Select();
return true;
}
else
{
Game1.NetworkMember = null;
return false;
}
Game1.Client.ConnectToServer(ipBox.Text);
return true;
//{
// Game1.NetLobbyScreen.Select();
// return true;
//}
//else
//{
// Game1.NetworkMember = null;
// return false;
//}
}
}

View File

@@ -160,7 +160,7 @@ namespace Subsurface
//int oldMapIndex = 0;
//if (mapList != null && mapList.SelectedData != null) oldMapIndex = mapList.SelectedIndex;
new GUITextBlock(new Rectangle(0, 30, 0, 30), "Selected submarine:", null, null, Alignment.Left, null, infoFrame);
new GUITextBlock(new Rectangle(0, 30, 0, 30), "Selected submarine:", GUI.style, infoFrame);
subList = new GUIListBox(new Rectangle(0, 60, 200, 200), Color.White, GUI.style, infoFrame);
subList.OnSelected = SelectMap;
subList.Enabled = (Game1.Server != null);
@@ -184,7 +184,7 @@ namespace Subsurface
return;
}
new GUITextBlock(new Rectangle(220, 30, 0, 30), "Selected game mode: ", null, null, Alignment.Left, GUI.style, infoFrame);
new GUITextBlock(new Rectangle(220, 30, 0, 30), "Selected game mode: ", GUI.style, infoFrame);
modeList = new GUIListBox(new Rectangle(220, 60, 200, 200), GUI.style, infoFrame);
modeList.Enabled = (Game1.Server != null);
//modeList.OnSelected = new GUIListBox.OnSelectedHandler(SelectEvent);
@@ -202,15 +202,14 @@ namespace Subsurface
textBlock.UserData = mode;
}
GUITextBlock durationText = new GUITextBlock(new Rectangle((int)(modeList.Rect.Right + 20 - 100), 30, 100, 20),
GUITextBlock durationText = new GUITextBlock(new Rectangle((int)(modeList.Rect.Right + 20 - 80), 30, 100, 20),
"Game duration: ", GUI.style, Alignment.Left, Alignment.TopLeft, infoFrame);
durationText.TextGetter = DurationText;
durationBar = new GUIScrollBar(new Rectangle((int)(modeList.Rect.Right + 20 - 100), 60, 180, 20),
durationBar = new GUIScrollBar(new Rectangle((int)(modeList.Rect.Right + 20 - 80), 60, 180, 20),
GUI.style, 0.1f, infoFrame);
durationBar.BarSize = 0.1f;
durationBar.Enabled = (Game1.Server != null);
durationBar.Enabled = (Game1.Server != null);
new GUITextBlock(new Rectangle((int)(modeList.Rect.Right + 20 - 80), 100, 100, 20),
"Level Seed: ", GUI.style, Alignment.Left, Alignment.TopLeft, infoFrame);
@@ -236,20 +235,24 @@ namespace Subsurface
else
{
int x = playerFrame.Rect.Width / 2;
GUITextBox playerName = new GUITextBox(new Rectangle(x, 0, 0, 20),
new GUITextBlock(new Rectangle(x, 0, 200, 30), "Name: ", GUI.style, playerFrame);
GUITextBox playerName = new GUITextBox(new Rectangle(x, 30, 0, 20),
Alignment.TopLeft, GUI.style, playerFrame);
playerName.Text = Game1.Client.CharacterInfo.Name;
playerName.OnEnter += ChangeCharacterName;
new GUITextBlock(new Rectangle(x,40,200, 30), "Gender: ", Color.Transparent, Color.Black,
Alignment.TopLeft, GUI.style, playerFrame);
new GUITextBlock(new Rectangle(x,70,200, 30), "Gender: ", GUI.style, playerFrame);
GUIButton maleButton = new GUIButton(new Rectangle(x+70,50,70,20), "Male",
GUIButton maleButton = new GUIButton(new Rectangle(x, 100, 70, 20), "Male",
Alignment.TopLeft, GUI.style,playerFrame);
maleButton.UserData = Gender.Male;
maleButton.OnClicked += SwitchGender;
GUIButton femaleButton = new GUIButton(new Rectangle(x+150, 50, 70, 20), "Female",
GUIButton femaleButton = new GUIButton(new Rectangle(x+150, 100, 70, 20), "Female",
Alignment.TopLeft, GUI.style, playerFrame);
femaleButton.UserData = Gender.Female;
femaleButton.OnClicked += SwitchGender;
@@ -311,6 +314,14 @@ namespace Subsurface
playerList.RemoveChild(playerList.GetChild(client));
}
public void ClearPlayers()
{
for (int i = 1; i<playerList.CountChildren; i++)
{
playerList.RemoveChild(playerList.children[i]);
}
}
public override void Update(double deltaTime)
{
base.Update(deltaTime);
@@ -406,6 +417,7 @@ namespace Subsurface
Vector2 pos = new Vector2(1000.0f, 1000.0f);
Character character = new Character(Game1.Client.CharacterInfo, pos);
character.ID = int.MaxValue;
Game1.Client.Character = character;
@@ -422,6 +434,7 @@ namespace Subsurface
{
pos = ConvertUnits.ToDisplayUnits(pos);
previewHull = new Hull(new Rectangle((int)pos.X - 100, (int)pos.Y + 100, 200, 200));
previewHull.ID = int.MaxValue - 2;
}
Physics.Alpha = 1.0f;
@@ -501,11 +514,12 @@ namespace Subsurface
private void UpdateJobPreferences(GUIListBox listBox)
{
listBox.Deselect();
for (int i = 0; i<listBox.children.Count; i++)
for (int i = 1; i<listBox.children.Count; i++)
{
float a = (float)i/listBox.children.Count;
Color color = new Color(a, 1.0f - a, 0.5f, 1.0f);
float a = (float)(i - 1) / 3.0f;
a = Math.Min(a, 3);
Color color = new Color(1.0f-a, (1.0f - a)*0.6f, 0.0f, 0.3f);
listBox.children[i].Color = color;
}

View File

@@ -63,6 +63,7 @@
<Compile Include="Characters\Jobs\JobPrefab.cs" />
<Compile Include="Characters\AI\SteeringManager.cs" />
<Compile Include="Characters\AI\SteeringPath.cs" />
<Compile Include="CoroutineManager.cs" />
<Compile Include="Rand.cs" />
<Compile Include="Events\PropertyTask.cs" />
<Compile Include="Events\RepairTask.cs" />
@@ -362,6 +363,15 @@
<Content Include="Content\Items\Pump\pump.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\Map\iceCrack.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\Map\iceCraters.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\Map\iceSurface.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\UI\caret.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>

Binary file not shown.