diff --git a/Subsurface/Characters/Character.cs b/Subsurface/Characters/Character.cs index d06d5b1c5..bd051967e 100644 --- a/Subsurface/Characters/Character.cs +++ b/Subsurface/Characters/Character.cs @@ -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(); diff --git a/Subsurface/Characters/CharacterInfo.cs b/Subsurface/Characters/CharacterInfo.cs index 161bde969..4eb7d32c4 100644 --- a/Subsurface/Characters/CharacterInfo.cs +++ b/Subsurface/Characters/CharacterInfo.cs @@ -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); diff --git a/Subsurface/Characters/Jobs/Job.cs b/Subsurface/Characters/Jobs/Job.cs index 4cb711608..7d6ea2be3 100644 --- a/Subsurface/Characters/Jobs/Job.cs +++ b/Subsurface/Characters/Jobs/Job.cs @@ -24,6 +24,16 @@ namespace Subsurface get { return prefab.Description; } } + public JobPrefab Prefab + { + get { return prefab; } + } + + public List SpawnItemNames + { + get { return prefab.ItemNames; } + } + public Job(JobPrefab jobPrefab) { diff --git a/Subsurface/Characters/Jobs/JobPrefab.cs b/Subsurface/Characters/Jobs/JobPrefab.cs index 2ab9a2416..e492989e8 100644 --- a/Subsurface/Characters/Jobs/JobPrefab.cs +++ b/Subsurface/Characters/Jobs/JobPrefab.cs @@ -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", ""); diff --git a/Subsurface/Content/Characters/Jobs.xml b/Subsurface/Content/Characters/Jobs.xml index 83d15703d..6e0a0fa3b 100644 --- a/Subsurface/Content/Characters/Jobs.xml +++ b/Subsurface/Content/Characters/Jobs.xml @@ -1,6 +1,6 @@  - + @@ -15,4 +15,10 @@ + + + + + + \ No newline at end of file diff --git a/Subsurface/Content/Map/iceCrack.png b/Subsurface/Content/Map/iceCrack.png new file mode 100644 index 000000000..a2e737ca2 Binary files /dev/null and b/Subsurface/Content/Map/iceCrack.png differ diff --git a/Subsurface/Content/Map/iceCraters.png b/Subsurface/Content/Map/iceCraters.png new file mode 100644 index 000000000..9c690d927 Binary files /dev/null and b/Subsurface/Content/Map/iceCraters.png differ diff --git a/Subsurface/Content/Map/iceSurface.png b/Subsurface/Content/Map/iceSurface.png new file mode 100644 index 000000000..c85833504 Binary files /dev/null and b/Subsurface/Content/Map/iceSurface.png differ diff --git a/Subsurface/Content/UI/style.xml b/Subsurface/Content/UI/style.xml index 4f3086e60..53f89f74b 100644 --- a/Subsurface/Content/UI/style.xml +++ b/Subsurface/Content/UI/style.xml @@ -16,17 +16,18 @@ + hovercolor="1.0, 0.57, 0.31, 1.0" + selectedcolor="1.0, 0.0, 0.0, 1.0"/> + selectedcolor="1.0, 0.6, 0.0, 0.3" + padding="10.0, 0.0, 10.0, 0.0"/> + + + + + + \ No newline at end of file diff --git a/Subsurface/Content/randomevents.xml b/Subsurface/Content/randomevents.xml index fbe619158..beb43f35c 100644 --- a/Subsurface/Content/randomevents.xml +++ b/Subsurface/Content/randomevents.xml @@ -5,13 +5,13 @@ commonness="10" difficulty="30" minamount="2" maxamount="3" - starttimemin="5" starttimemax="10" + starttimemin="15" starttimemax="20" musictype="monster"/> \ No newline at end of file diff --git a/Subsurface/CoroutineManager.cs b/Subsurface/CoroutineManager.cs new file mode 100644 index 000000000..d34f5d6e4 --- /dev/null +++ b/Subsurface/CoroutineManager.cs @@ -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> Coroutines = new List>(); + + // 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 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; + } + } + } + } +} diff --git a/Subsurface/Events/TaskManager.cs b/Subsurface/Events/TaskManager.cs index 531d20f78..8f94c3645 100644 --- a/Subsurface/Events/TaskManager.cs +++ b/Subsurface/Events/TaskManager.cs @@ -63,7 +63,6 @@ namespace Subsurface { ScriptedEvent scriptedEvent = ScriptedEvent.LoadRandom(level.Seed); AddTask(new ScriptedTask(scriptedEvent)); - } public void TaskStarted(Task task) diff --git a/Subsurface/GUI/GUIMessageBox.cs b/Subsurface/GUI/GUIMessageBox.cs index ec58e4fc4..317e4f45e 100644 --- a/Subsurface/GUI/GUIMessageBox.cs +++ b/Subsurface/GUI/GUIMessageBox.cs @@ -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); diff --git a/Subsurface/GUI/GUITextBlock.cs b/Subsurface/GUI/GUITextBlock.cs index eee250c3d..df7e25f9f 100644 --- a/Subsurface/GUI/GUITextBlock.cs +++ b/Subsurface/GUI/GUITextBlock.cs @@ -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) { } diff --git a/Subsurface/Game1.cs b/Subsurface/Game1.cs index 9db8ebb2c..be8ca847a 100644 --- a/Subsurface/Game1.cs +++ b/Subsurface/Game1.cs @@ -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(); } diff --git a/Subsurface/GameSession/CrewManager.cs b/Subsurface/GameSession/CrewManager.cs index a8837b431..f42eb5cfe 100644 --- a/Subsurface/GameSession/CrewManager.cs +++ b/Subsurface/GameSession/CrewManager.cs @@ -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() diff --git a/Subsurface/GameSession/GameSession.cs b/Subsurface/GameSession/GameSession.cs index 7ab807ebe..c3ef9d5d8 100644 --- a/Subsurface/GameSession/GameSession.cs +++ b/Subsurface/GameSession/GameSession.cs @@ -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) { diff --git a/Subsurface/GameSession/SinglePlayerMode.cs b/Subsurface/GameSession/SinglePlayerMode.cs index 0ca0ad861..5b06a622b 100644 --- a/Subsurface/GameSession/SinglePlayerMode.cs +++ b/Subsurface/GameSession/SinglePlayerMode.cs @@ -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); diff --git a/Subsurface/Items/CharacterInventory.cs b/Subsurface/Items/CharacterInventory.cs index 17611bd93..5606c124f 100644 --- a/Subsurface/Items/CharacterInventory.cs +++ b/Subsurface/Items/CharacterInventory.cs @@ -46,7 +46,7 @@ namespace Subsurface /// /// If there is room, puts the item in the inventory and returns true, otherwise returns false /// - 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); diff --git a/Subsurface/Items/Components/ItemComponent.cs b/Subsurface/Items/Components/ItemComponent.cs index 3fe5ef3a7..9910c839d 100644 --- a/Subsurface/Items/Components/ItemComponent.cs +++ b/Subsurface/Items/Components/ItemComponent.cs @@ -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; diff --git a/Subsurface/Items/Inventory.cs b/Subsurface/Items/Inventory.cs index 10d19af36..2e802cccb 100644 --- a/Subsurface/Items/Inventory.cs +++ b/Subsurface/Items/Inventory.cs @@ -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 /// /// If there is room, puts the item in the inventory and returns true, otherwise returns false /// - 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) diff --git a/Subsurface/Items/ItemInventory.cs b/Subsurface/Items/ItemInventory.cs index d355df0e3..fe2840ab9 100644 --- a/Subsurface/Items/ItemInventory.cs +++ b/Subsurface/Items/ItemInventory.cs @@ -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++) { diff --git a/Subsurface/Map/Entity.cs b/Subsurface/Map/Entity.cs index c3f456773..09ef1323a 100644 --- a/Subsurface/Map/Entity.cs +++ b/Subsurface/Map/Entity.cs @@ -45,7 +45,7 @@ namespace Subsurface { //give an unique ID bool IDfound; - id = 0; + id = 1;//Rand.Int(int.MaxValue); do { id += 1; diff --git a/Subsurface/Map/Map.cs b/Subsurface/Map/Map.cs index b26df7e6f..fbad41b5d 100644 --- a/Subsurface/Map/Map.cs +++ b/Subsurface/Map/Map.cs @@ -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(); + 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 GenerateCrack(Vector2 start, Vector2 end, int generations) + { + List segments = new List(); + + segments.Add(new Vector2[] {start, end}); + + float offsetAmount = 5.0f; + + for (int n = 0; n CrackSegments; public Location[] Locations { diff --git a/Subsurface/Map/Submarine.cs b/Subsurface/Map/Submarine.cs index ac8e5ede7..3e8420c9f 100644 --- a/Subsurface/Map/Submarine.cs +++ b/Subsurface/Map/Submarine.cs @@ -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(); diff --git a/Subsurface/Map/WayPoint.cs b/Subsurface/Map/WayPoint.cs index 6f0da80f3..ddb25c95a 100644 --- a/Subsurface/Map/WayPoint.cs +++ b/Subsurface/Map/WayPoint.cs @@ -13,16 +13,35 @@ namespace Subsurface public enum SpawnType { None, Human, Enemy }; class WayPoint : MapEntity { - + public static List WayPointList = new List(); 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 = 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 wayPoints = new List(); - 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 crew) + { + List unassignedWayPoints = new List(); + 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 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); + } } } diff --git a/Subsurface/Networking/GameClient.cs b/Subsurface/Networking/GameClient.cs index 45634ff2c..7c5e2f043 100644 --- a/Subsurface/Networking/GameClient.cs +++ b/Subsurface/Networking/GameClient.cs @@ -15,7 +15,15 @@ namespace Subsurface.Networking private Character myCharacter; private CharacterInfo characterInfo; + GUIMessageBox reconnectBox; + + private bool connected; + + private int myID; + List otherClients; + + private string serverIP; public Character Character { @@ -37,8 +45,10 @@ namespace Subsurface.Networking otherClients = new List(); } - 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 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; } diff --git a/Subsurface/Networking/GameServer.cs b/Subsurface/Networking/GameServer.cs index 33113f133..dccba5bd9 100644 --- a/Subsurface/Networking/GameServer.cs +++ b/Subsurface/Networking/GameServer.cs @@ -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 characterInfos = new List(); + 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); diff --git a/Subsurface/Networking/NetworkEvent.cs b/Subsurface/Networking/NetworkEvent.cs index 688c727b0..6a236beac 100644 --- a/Subsurface/Networking/NetworkEvent.cs +++ b/Subsurface/Networking/NetworkEvent.cs @@ -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; } diff --git a/Subsurface/Networking/NetworkMember.cs b/Subsurface/Networking/NetworkMember.cs index 7ddf9609e..605d8aebe 100644 --- a/Subsurface/Networking/NetworkMember.cs +++ b/Subsurface/Networking/NetworkMember.cs @@ -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(); } diff --git a/Subsurface/Screens/LobbyScreen.cs b/Subsurface/Screens/LobbyScreen.cs index 49dde1e29..4f4b40146 100644 --- a/Subsurface/Screens/LobbyScreen.cs +++ b/Subsurface/Screens/LobbyScreen.cs @@ -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) { diff --git a/Subsurface/Screens/MainMenu.cs b/Subsurface/Screens/MainMenu.cs index 325362492..9e4ea13a3 100644 --- a/Subsurface/Screens/MainMenu.cs +++ b/Subsurface/Screens/MainMenu.cs @@ -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; + //} } } diff --git a/Subsurface/Screens/NetLobbyScreen.cs b/Subsurface/Screens/NetLobbyScreen.cs index bbac16c6d..b340a7f11 100644 --- a/Subsurface/Screens/NetLobbyScreen.cs +++ b/Subsurface/Screens/NetLobbyScreen.cs @@ -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 + @@ -362,6 +363,15 @@ PreserveNewest + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + PreserveNewest diff --git a/Subsurface_Solution.v12.suo b/Subsurface_Solution.v12.suo index c4d398f2a..9639db8c3 100644 Binary files a/Subsurface_Solution.v12.suo and b/Subsurface_Solution.v12.suo differ