From 24ba9b1b98ed0530bbdc863617ee0f1deb67f6a3 Mon Sep 17 00:00:00 2001 From: Regalis Date: Fri, 19 Jun 2015 11:53:31 +0300 Subject: [PATCH] GameMode/CrewManager bugfixes, fabricators --- .../Content/Items/Fabricators/fabricator.png | Bin 0 -> 2133 bytes .../Content/Items/Fabricators/fabricators.xml | 24 ++ .../Content/Items/{ => Weapons}/railgun.ogg | Bin .../Content/Items/{ => Weapons}/railgun.xml | 0 .../Items/{ => Weapons}/railgunbarrel.png | Bin .../Items/{ => Weapons}/railgunbase.png | Bin .../Items/{ => Weapons}/railguncontroller.png | Bin .../Items/{ => Weapons}/railgunloader.png | Bin .../Items/{ => Weapons}/railgunshell.png | Bin Subsurface/GUI/GUIComponent.cs | 10 + Subsurface/GameSession/GameMode.cs | 34 ++- Subsurface/GameSession/GameSession.cs | 48 ++-- Subsurface/GameSession/SinglePlayerMode.cs | 21 +- Subsurface/GameSession/TraitorMode.cs | 2 + Subsurface/Items/Components/Container.cs | 72 +++--- Subsurface/Items/Components/Fabricator.cs | 216 ++++++++++++++++++ Subsurface/Items/Inventory.cs | 38 ++- Subsurface/Items/Item.cs | 6 + Subsurface/Items/ItemInventory.cs | 7 +- Subsurface/Map/Map.cs | 4 - Subsurface/Networking/GameClient.cs | 4 +- Subsurface/Networking/GameServer.cs | 5 +- Subsurface/Screens/LobbyScreen.cs | 3 +- Subsurface/Screens/MainMenu.cs | 2 +- Subsurface/Subsurface.csproj | 22 +- Subsurface_Solution.v12.suo | Bin 291328 -> 274944 bytes 26 files changed, 420 insertions(+), 98 deletions(-) create mode 100644 Subsurface/Content/Items/Fabricators/fabricator.png create mode 100644 Subsurface/Content/Items/Fabricators/fabricators.xml rename Subsurface/Content/Items/{ => Weapons}/railgun.ogg (100%) rename Subsurface/Content/Items/{ => Weapons}/railgun.xml (100%) rename Subsurface/Content/Items/{ => Weapons}/railgunbarrel.png (100%) rename Subsurface/Content/Items/{ => Weapons}/railgunbase.png (100%) rename Subsurface/Content/Items/{ => Weapons}/railguncontroller.png (100%) rename Subsurface/Content/Items/{ => Weapons}/railgunloader.png (100%) rename Subsurface/Content/Items/{ => Weapons}/railgunshell.png (100%) create mode 100644 Subsurface/Items/Components/Fabricator.cs diff --git a/Subsurface/Content/Items/Fabricators/fabricator.png b/Subsurface/Content/Items/Fabricators/fabricator.png new file mode 100644 index 0000000000000000000000000000000000000000..e82943efb3a04add5766915f64b9d54fdf284c29 GIT binary patch literal 2133 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H1SEZ8zRdwrjKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCij$3p^r=85sBugD~Uq{1qt-4D7EwT^vIy;@(c(IBAYKU&~je?;d`!r4L>G zWGssd-q-oonQ+~nad)q5riaJTb$o0rbuY6Q=+y7FT3;V4d&%}d;$3E$Yd~r(vqyf{ zy{e91!XK6I@B8xpe*JGvp4_Rursik9GaTpnY^!Qnk_KpS1->YtW#+*)RJA=;W}^YvoLSq?td+s4T&I6R@V9>} zucycVDX9I-=jnIwhJIbcpP=3HKX&rl|MSwfY(1sOC6&1Mwq9R^1RGnfXzbbO2QhXv zl`o##{rRFjl?L+952V!n_#JHj{o(QWm#WJHFg=OI)$8jU?D{MWR?93}Ab4%}+eaO( zi3u0NE?(V}n)kGWc{8Rbo`sDnAI>2Yx0lVxAY=85tb0b=i;gr_KC6Dtkjo29zehKo zS*x>WPSU#natVuDrw5<;dcVHO%<9nro6mde8GaW&DX%+-nR5D-_kZSY17$wlVr_Ss z8KHcE7dY0(F-uBp2`w?rpBZflGT`oiCXh*MiaMIyBHn*{eB%9|riEzva`klwXg&fb z!SglW_c!z+(&Ar>PuBYr5Dt%gD!|(N;g#uxM#pH^@XynBPF3bRV|@Rwe!^lPL#tgQ zqvdO!eczvR`Vznr12v~(^~}So*$R+i1mctQedT-?t^s`PSyYAP z(U||X2i&;zm(O^;pZ!M0!>1y}f4?(G>!OAobIz6zMO{1pRX6mC#rYXtujk)zaX<|D ze~De;fn%yfMG;rpJI1&bJk0)n2haRf&zKL1WZVw@-x9wPqT2QV_teA(CpBm6{Lk`s zGXa17o&P}_s+zrGp%IUbC9CoG`3q_Z1;c;gx}^}+{&ESme~fO%i-QuD-IfFC5aTMp zGpzpGm-C~&`md?$g|MUHz({XpS3hHX;WqP{<(hH3B!Mw~XdAFhk8Z78_j5k;huLN6 z&cM_ms8g(cye)B_HZZ?JP61NmD literal 0 HcmV?d00001 diff --git a/Subsurface/Content/Items/Fabricators/fabricators.xml b/Subsurface/Content/Items/Fabricators/fabricators.xml new file mode 100644 index 000000000..ee84049cd --- /dev/null +++ b/Subsurface/Content/Items/Fabricators/fabricators.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Subsurface/Content/Items/railgun.ogg b/Subsurface/Content/Items/Weapons/railgun.ogg similarity index 100% rename from Subsurface/Content/Items/railgun.ogg rename to Subsurface/Content/Items/Weapons/railgun.ogg diff --git a/Subsurface/Content/Items/railgun.xml b/Subsurface/Content/Items/Weapons/railgun.xml similarity index 100% rename from Subsurface/Content/Items/railgun.xml rename to Subsurface/Content/Items/Weapons/railgun.xml diff --git a/Subsurface/Content/Items/railgunbarrel.png b/Subsurface/Content/Items/Weapons/railgunbarrel.png similarity index 100% rename from Subsurface/Content/Items/railgunbarrel.png rename to Subsurface/Content/Items/Weapons/railgunbarrel.png diff --git a/Subsurface/Content/Items/railgunbase.png b/Subsurface/Content/Items/Weapons/railgunbase.png similarity index 100% rename from Subsurface/Content/Items/railgunbase.png rename to Subsurface/Content/Items/Weapons/railgunbase.png diff --git a/Subsurface/Content/Items/railguncontroller.png b/Subsurface/Content/Items/Weapons/railguncontroller.png similarity index 100% rename from Subsurface/Content/Items/railguncontroller.png rename to Subsurface/Content/Items/Weapons/railguncontroller.png diff --git a/Subsurface/Content/Items/railgunloader.png b/Subsurface/Content/Items/Weapons/railgunloader.png similarity index 100% rename from Subsurface/Content/Items/railgunloader.png rename to Subsurface/Content/Items/Weapons/railgunloader.png diff --git a/Subsurface/Content/Items/railgunshell.png b/Subsurface/Content/Items/Weapons/railgunshell.png similarity index 100% rename from Subsurface/Content/Items/railgunshell.png rename to Subsurface/Content/Items/Weapons/railgunshell.png diff --git a/Subsurface/GUI/GUIComponent.cs b/Subsurface/GUI/GUIComponent.cs index c21a4dd73..a2fbf255c 100644 --- a/Subsurface/GUI/GUIComponent.cs +++ b/Subsurface/GUI/GUIComponent.cs @@ -133,6 +133,16 @@ namespace Subsurface keyboardDispatcher = new KeyboardDispatcher(window); } + public T GetChild() + { + foreach (GUIComponent child in children) + { + if (child is T) return (T)(object)child; + } + + return default(T); + } + public GUIComponent GetChild(object obj) { foreach (GUIComponent child in children) diff --git a/Subsurface/GameSession/GameMode.cs b/Subsurface/GameSession/GameMode.cs index 45ab79427..5be3b8bfa 100644 --- a/Subsurface/GameSession/GameMode.cs +++ b/Subsurface/GameSession/GameMode.cs @@ -1,4 +1,5 @@ -using Microsoft.Xna.Framework.Graphics; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; using System; using System.Collections.Generic; using System.Reflection; @@ -37,12 +38,17 @@ namespace Subsurface { public static List presetList = new List(); - //TimeSpan duration; + TimeSpan duration; protected DateTime startTime; protected DateTime endTime; //public readonly bool IsSinglePlayer; + private GUIProgressBar timerBar; + + + + protected bool isRunning; //protected string name; @@ -85,16 +91,25 @@ namespace Subsurface { this.preset = preset; + //list.Add(this); } public virtual void Draw(SpriteBatch spriteBatch) - { } + { + if (timerBar != null) timerBar.Draw(spriteBatch); + } public virtual void Start(TimeSpan duration) { startTime = DateTime.Now; - endTime = startTime + duration; + if (duration!=TimeSpan.Zero) + { + endTime = startTime + duration; + this.duration = duration; + + timerBar = new GUIProgressBar(new Rectangle(Game1.GraphicsWidth - 120, 20, 100, 25), Color.Gold, 0.0f, null); + } endMessage = "The round has ended!"; @@ -105,10 +120,15 @@ namespace Subsurface { if (!isRunning) return; - if (DateTime.Now >= endTime) + if (duration!=TimeSpan.Zero) { - End(endMessage); + double elapsedTime = (DateTime.Now - startTime).TotalSeconds; + timerBar.BarSize = (float)(elapsedTime / duration.TotalSeconds); } + //if (DateTime.Now >= endTime) + //{ + // End(endMessage); + //} } public virtual void End(string endMessage = "") @@ -119,7 +139,7 @@ namespace Subsurface Game1.GameSession.EndShift(null, null); } - + public static void Init() { new GameModePreset("Single Player", typeof(SinglePlayerMode), true); diff --git a/Subsurface/GameSession/GameSession.cs b/Subsurface/GameSession/GameSession.cs index a1b98ea42..6762a6f45 100644 --- a/Subsurface/GameSession/GameSession.cs +++ b/Subsurface/GameSession/GameSession.cs @@ -15,8 +15,8 @@ namespace Subsurface public readonly TaskManager taskManager; - protected DateTime startTime; - protected DateTime endTime; + //protected DateTime startTime; + //protected DateTime endTime; public readonly GameMode gameMode; @@ -25,23 +25,17 @@ namespace Subsurface private GUIListBox chatBox; private GUITextBox textBox; - private GUIProgressBar timerBar; - - private GUIButton endShiftButton; - private string savePath; - private Map selectedMap; - - + private Map selectedMap; - public GameSession(Map selectedMap, TimeSpan gameDuration, GameModePreset gameModePreset) - :this(selectedMap, gameDuration, gameModePreset.Instantiate()) + public GameSession(Map selectedMap, GameModePreset gameModePreset) + :this(selectedMap, gameModePreset.Instantiate()) { } - public GameSession(Map selectedMap, TimeSpan gameDuration, GameMode gameMode = null) + public GameSession(Map selectedMap, GameMode gameMode = null) { taskManager = new TaskManager(this); @@ -63,23 +57,15 @@ namespace Subsurface Color.White * 0.5f, Color.Black, Alignment.Bottom, Alignment.Left, guiRoot); textBox.OnEnter = EnterChatMessage; } - - if (Game1.Client==null) - { - endShiftButton = new GUIButton(new Rectangle(Game1.GraphicsWidth - 240, 20, 100, 25), "End shift", Color.White, Alignment.Left | Alignment.Top, guiRoot); - endShiftButton.OnClicked = EndShift; - } - - timerBar = new GUIProgressBar(new Rectangle(Game1.GraphicsWidth - 120, 20, 100, 25), Color.Gold, 0.0f, guiRoot); - + this.gameMode = gameMode; //if (gameMode != null && !gameMode.IsSinglePlayer) //{ // gameMode.Start(Game1.NetLobbyScreen.GameDuration); //} - startTime = DateTime.Now; - endTime = startTime + gameDuration; + //startTime = DateTime.Now; + //endTime = startTime + gameDuration; this.selectedMap = selectedMap; @@ -90,7 +76,7 @@ namespace Subsurface } public GameSession(Map selectedMap, string savePath, string filePath) - : this(selectedMap, new TimeSpan(0,0,0,0)) + : this(selectedMap) { XDocument doc = ToolBox.TryLoadXml(filePath); if (doc == null) return; @@ -109,13 +95,13 @@ namespace Subsurface this.savePath = savePath; } - public void StartShift(int scriptedEventCount = 1) + public void StartShift(TimeSpan duration, int scriptedEventCount = 1) { //if (crewManager.characterInfos.Count == 0) return; if (Map.Loaded!=selectedMap) selectedMap.Load(); - gameMode.Start(TimeSpan.Zero); + if (gameMode!=null) gameMode.Start(duration); //crewManager.StartShift(); taskManager.StartShift(scriptedEventCount); @@ -138,7 +124,7 @@ namespace Subsurface } taskManager.EndShift(); - gameMode.End(); + //gameMode.End(); return true; } @@ -194,7 +180,7 @@ namespace Subsurface { taskManager.Update(deltaTime); //if (endShiftButton!=null) endShiftButton.Enabled = !taskManager.CriticalTasks; - endShiftButton.Enabled = true; + //endShiftButton.Enabled = true; guiRoot.Update(deltaTime); @@ -204,9 +190,9 @@ namespace Subsurface if (gameMode != null) gameMode.Update(deltaTime); - double duration = (endTime - startTime).TotalSeconds; - double elapsedTime = (DateTime.Now-startTime).TotalSeconds; - timerBar.BarSize = (float)(elapsedTime / Math.Max(duration, 1.0)); + //double duration = (endTime - startTime).TotalSeconds; + //double elapsedTime = (DateTime.Now-startTime).TotalSeconds; + //timerBar.BarSize = (float)(elapsedTime / Math.Max(duration, 1.0)); if (PlayerInput.KeyHit(Keys.Tab)) { diff --git a/Subsurface/GameSession/SinglePlayerMode.cs b/Subsurface/GameSession/SinglePlayerMode.cs index 678dae8c2..d644d04ae 100644 --- a/Subsurface/GameSession/SinglePlayerMode.cs +++ b/Subsurface/GameSession/SinglePlayerMode.cs @@ -1,4 +1,5 @@ -using Microsoft.Xna.Framework.Graphics; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; using System; using System.Collections.Generic; using System.Linq; @@ -12,6 +13,8 @@ namespace Subsurface public readonly CrewManager crewManager; public readonly HireManager hireManager; + private GUIButton endShiftButton; + private int day; public int Day @@ -28,6 +31,9 @@ namespace Subsurface crewManager = new CrewManager(); hireManager = new HireManager(); + endShiftButton = new GUIButton(new Rectangle(Game1.GraphicsWidth - 240, 20, 100, 25), "End shift", Color.White, Alignment.Left | Alignment.Top); + endShiftButton.OnClicked = EndShift; + hireManager.GenerateCharacters("Content/Characters/Human/human.xml", 10); day = 1; @@ -73,8 +79,11 @@ namespace Subsurface public override void Draw(SpriteBatch spriteBatch) { + base.Draw(spriteBatch); + crewManager.Draw(spriteBatch); + endShiftButton.Draw(spriteBatch); //chatBox.Draw(spriteBatch); //textBox.Draw(spriteBatch); @@ -85,8 +94,12 @@ namespace Subsurface public override void Update(float deltaTime) { + base.Update(deltaTime); + crewManager.Update(deltaTime); + endShiftButton.Update(deltaTime); + if (!crewDead) { if (crewManager.characters.Find(c => !c.IsDead) == null) @@ -102,7 +115,7 @@ namespace Subsurface } } - public override void End(string endMessage = "") + private bool EndShift(GUIButton button, object obj) { StringBuilder sb = new StringBuilder(); List casualties = crewManager.characters.FindAll(c => c.IsDead); @@ -142,6 +155,10 @@ namespace Subsurface { Character.characterList.RemoveAt(i); } + + Game1.GameSession.EndShift(null, null); + + return true; } public void Save(XElement element) diff --git a/Subsurface/GameSession/TraitorMode.cs b/Subsurface/GameSession/TraitorMode.cs index c8f1b066b..f93b5e054 100644 --- a/Subsurface/GameSession/TraitorMode.cs +++ b/Subsurface/GameSession/TraitorMode.cs @@ -25,6 +25,8 @@ namespace Subsurface public override void Update(float deltaTime) { + base.Update(deltaTime); + if (!isRunning) return; if (DateTime.Now >= endTime) diff --git a/Subsurface/Items/Components/Container.cs b/Subsurface/Items/Components/Container.cs index 288470e32..e3aa1a386 100644 --- a/Subsurface/Items/Components/Container.cs +++ b/Subsurface/Items/Components/Container.cs @@ -13,25 +13,13 @@ namespace Subsurface.Items.Components public ItemInventory inventory; //how many items can be contained - private int capacity; - - private bool hideItems; - private bool drawInventory; - - //the position of the first item in the container - private Vector2 itemPos; - - //item[i].Pos = itemPos + itemInterval*i - private Vector2 itemInterval; - - private float itemRotation; - [HasDefaultValue(5, false)] public int Capacity { get { return capacity; } set { capacity = Math.Max(value, 1); } } + private int capacity; [HasDefaultValue(true, false)] public bool HideItems @@ -39,6 +27,7 @@ namespace Subsurface.Items.Components get { return hideItems; } set { hideItems = value; } } + private bool hideItems; [HasDefaultValue(false, false)] public bool DrawInventory @@ -46,6 +35,25 @@ namespace Subsurface.Items.Components get { return drawInventory; } set { drawInventory = value; } } + private bool drawInventory; + + //the position of the first item in the container + [HasDefaultValue("0.0,0.0", false)] + public string ItemPos + { + get { return ToolBox.Vector2ToString(itemPos); } + set { itemPos = ToolBox.ParseToVector2(value); } + } + private Vector2 itemPos; + + //item[i].Pos = itemPos + itemInterval*i + [HasDefaultValue("0.0,0.0", false)] + public string ItemInterval + { + get { return ToolBox.Vector2ToString(itemInterval); } + set { itemInterval = ToolBox.ParseToVector2(value); } + } + private Vector2 itemInterval; [HasDefaultValue(0.0f, false)] public float ItemRotation @@ -53,25 +61,33 @@ namespace Subsurface.Items.Components get { return itemRotation; } set { itemRotation = value; } } + private float itemRotation; - [HasDefaultValue("0.0,0.0", false)] - public string ItemPos - { - get { return ToolBox.Vector2ToString(itemPos); } - set { itemPos = ToolBox.ParseToVector2(value); } - } - [HasDefaultValue("0.0,0.0", false)] - public string ItemInterval + [HasDefaultValue("0.5,0.9", false)] + public string HudPos { - get { return ToolBox.Vector2ToString(itemInterval); } - set { itemInterval = ToolBox.ParseToVector2(value); } + get { return ToolBox.Vector2ToString(hudPos); } + set + { + hudPos = ToolBox.ParseToVector2(value); + //inventory.CenterPos = hudPos; + } } - + private Vector2 hudPos; + + [HasDefaultValue(5, false)] + public int SlotsPerRow + { + get { return slotsPerRow; } + set { slotsPerRow = value; } + } + private int slotsPerRow; + public ItemContainer(Item item, XElement element) : base (item, element) { - inventory = new ItemInventory(this, capacity); + inventory = new ItemInventory(this, capacity, hudPos, slotsPerRow); containableItems = new List(); //itemPos = ToolBox.GetAttributeVector2(element, "ItemPos", Vector2.Zero); @@ -99,6 +115,7 @@ namespace Subsurface.Items.Components public bool CanBeContained(Item item) { + if (containableItems.Count == 0) return true; return (containableItems.Find(x => x.MatchesItem(item)) != null); } @@ -182,10 +199,7 @@ namespace Subsurface.Items.Components public override bool Pick(Character picker) { - if (picker == null) return false; - //picker.SelectedConstruction = item; - - return true; + return (picker != null); } diff --git a/Subsurface/Items/Components/Fabricator.cs b/Subsurface/Items/Components/Fabricator.cs new file mode 100644 index 000000000..398799724 --- /dev/null +++ b/Subsurface/Items/Components/Fabricator.cs @@ -0,0 +1,216 @@ +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Xml.Linq; + +namespace Subsurface.Items.Components +{ + class FabricableItem + { + //public static List list = new List(); + + //public readonly string[] FabricatorTags; + + public readonly ItemPrefab TargetItem; + + public readonly List RequiredItems; + + public readonly float RequiredTime; + + + //ListOrSomething requiredLevels + + public FabricableItem(XElement element) + { + string name = ToolBox.GetAttributeString(element, "name", "").ToLower(); + + TargetItem = ItemPrefab.list.Find(ip => ip.Name.ToLower() == name) as ItemPrefab; + if (TargetItem == null) + { + DebugConsole.ThrowError("Error in Fabricable Item! Item ''" + element.Name + "'' not found."); + return; + } + + RequiredItems = new List(); + + string[] requiredItemNames = ToolBox.GetAttributeString(element, "requireditems", "").Split(','); + foreach (string requiredItemName in requiredItemNames) + { + ItemPrefab requiredItem = ItemPrefab.list.Find(ip => ip.Name.ToLower() == requiredItemName.Trim().ToLower()) as ItemPrefab; + if (requiredItem == null) continue; + RequiredItems.Add(requiredItem); + } + + RequiredTime = ToolBox.GetAttributeFloat(element, "requiredtime", 1.0f); + } + } + + class Fabricator : ItemComponent + { + List fabricableItems; + + GUIListBox itemList; + + GUIFrame selectedItemFrame; + + FabricableItem fabricatedItem; + float timeUntilReady; + + public Fabricator(Item item, XElement element) + : base(item, element) + { + fabricableItems = new List(); + + foreach (XElement subElement in element.Elements()) + { + if (subElement.Name.ToString() != "fabricableitem") continue; + + FabricableItem fabricableItem = new FabricableItem(subElement); + if (fabricableItem.TargetItem != null) fabricableItems.Add(fabricableItem); + + } + + int width = 400, height = 300; + itemList = new GUIListBox(new Rectangle(Game1.GraphicsWidth / 2 - width / 2, Game1.GraphicsHeight / 2 - height / 2, width, height), Color.White * 0.7f); + itemList.OnSelected = SelectItem; + //structureList.CheckSelected = MapEntityPrefab.GetSelected; + + foreach (FabricableItem fi in fabricableItems) + { + Color color = ((itemList.CountChildren % 2) == 0) ? Color.White : Color.LightGray; + + //GUIFrame frame = new GUIFrame(new Rectangle(0, 0, 0, 50), Color.Transparent, itemList); + //frame.UserData = fi; + //frame.Padding = new Vector4(5.0f, 5.0f, 5.0f, 5.0f); + //frame.Color = color; + //frame.HoverColor = Color.Gold * 0.2f; + //frame.SelectedColor = Color.Gold * 0.5f; + + GUITextBlock textBlock = new GUITextBlock( + new Rectangle(0, 0, 0, 25), + fi.TargetItem.Name, + color, Color.Black, + Alignment.Left, + Alignment.Left, + itemList); + textBlock.UserData = fi; + textBlock.Padding = new Vector4(5.0f, 5.0f, 5.0f, 5.0f); + + //if (fi.TargetItem.sprite != null) + //{ + // GUIImage img = new GUIImage(new Rectangle(0, 0, 40, 40), fi.TargetItem.sprite, Alignment.Left, frame); + // img.Scale = Math.Min(Math.Min(40.0f / img.SourceRect.Width, 40.0f / img.SourceRect.Height), 1.0f); + //} + } + } + + private bool SelectItem(object obj) + { + FabricableItem targetItem = obj as FabricableItem; + if (targetItem == null) return false; + + int width = 200, height = 150; + selectedItemFrame = new GUIFrame(new Rectangle(Game1.GraphicsWidth / 2 - width / 2, itemList.Rect.Bottom+20, width, height), Color.Black*0.8f); + selectedItemFrame.Padding = GUI.style.smallPadding; + + if (targetItem.TargetItem.sprite != null) + { + GUIImage img = new GUIImage(new Rectangle(0, 0, 40, 40), targetItem.TargetItem.sprite, Alignment.CenterX, selectedItemFrame); + img.Scale = Math.Min(Math.Min(40.0f / img.SourceRect.Width, 40.0f / img.SourceRect.Height), 1.0f); + + string text = targetItem.TargetItem.Name + "\n"; + text += "Required items:\n"; + foreach (ItemPrefab ip in targetItem.RequiredItems) + { + text += " - " + ip.Name + "\n"; + } + text += "Required time: "+targetItem.RequiredTime+" s"; + + GUITextBlock textBlock = new GUITextBlock( + new Rectangle(0, 0, 0, 25), + text, + Color.Transparent, Color.White, + Alignment.CenterX | Alignment.CenterY, + Alignment.Left, + selectedItemFrame); + + GUIButton button = new GUIButton(new Rectangle(0,0,100,20), "Create", Color.White, Alignment.CenterX | Alignment.Bottom, selectedItemFrame); + button.OnClicked = StartFabricating; + button.UserData = targetItem; + + + } + + return true; + } + + public override bool Pick(Character picker) + { + return (picker != null); + } + + private bool StartFabricating(GUIButton button, object obj) + { + GUIComponent listElement = itemList.GetChild(obj); + + listElement.Color = Color.Green; + itemList.Enabled = false; + + fabricatedItem = obj as FabricableItem; + isActive = true; + + timeUntilReady = fabricatedItem.RequiredTime; + + return true; + } + + public override void Update(float deltaTime, Camera cam) + { + timeUntilReady -= deltaTime; + + if (timeUntilReady > 0.0f) return; + + ItemContainer container = item.GetComponent(); + foreach (ItemPrefab ip in fabricatedItem.RequiredItems) + { + var requiredItem = Array.Find(container.inventory.items, it => it != null && it.Prefab == ip); + container.inventory.RemoveItem(requiredItem); + } + + new Item(fabricatedItem.TargetItem, item.Position); + + isActive = false; + fabricatedItem = null; + } + + public override void DrawHUD(SpriteBatch spriteBatch, Character character) + { + FabricableItem targetItem = itemList.SelectedData as FabricableItem; + if (targetItem != null) + { + selectedItemFrame.GetChild().Enabled = true; + + ItemContainer container = item.GetComponent(); + foreach (ItemPrefab ip in targetItem.RequiredItems) + { + if (Array.Find(container.inventory.items, it => it != null && it.Prefab == ip) != null) continue; + selectedItemFrame.GetChild().Enabled = false; + break; + } + } + + + itemList.Update(0.016f); + itemList.Draw(spriteBatch); + + if (selectedItemFrame != null) + { + selectedItemFrame.Update(0.016f); + selectedItemFrame.Draw(spriteBatch); + } + } + } +} diff --git a/Subsurface/Items/Inventory.cs b/Subsurface/Items/Inventory.cs index 5893628b7..10d19af36 100644 --- a/Subsurface/Items/Inventory.cs +++ b/Subsurface/Items/Inventory.cs @@ -10,20 +10,44 @@ namespace Subsurface { class Inventory : Entity { + public static Item draggingItem; + public static Item doubleClickedItem; + + private int slotsPerRow; + + public int SlotsPerRow + { + set { slotsPerRow = Math.Max(1, value); } + } + protected int capacity; - public static Item draggingItem; + public Vector2 CenterPos + { + get { return centerPos; } + set + { + centerPos = value; + centerPos.X *= Game1.GraphicsWidth; + centerPos.Y *= Game1.GraphicsHeight; + } + } - public static Item doubleClickedItem; + private Vector2 centerPos; protected int selectedSlot; public Item[] items; - public Inventory(int capacity) + public Inventory(int capacity, Vector2? centerPos = null, int slotsPerRow=5) { this.capacity = capacity; + + this.slotsPerRow = slotsPerRow; + items = new Item[capacity]; + + CenterPos = (centerPos==null) ? new Vector2(0.5f, 0.5f) : (Vector2)centerPos; } public int FindIndex(Item item) @@ -132,13 +156,11 @@ namespace Subsurface int rectWidth = 40, rectHeight = 40; int spacing = 10; - - int slotsPerRow = 5; - + int rows = (int)Math.Ceiling((double)capacity / slotsPerRow); - int startX = Game1.GraphicsWidth / 2 - (rectWidth * slotsPerRow + spacing * (slotsPerRow - 1)) / 2; - int startY = (int)(Game1.GraphicsHeight * 0.9) - rows*(spacing+rectHeight); + int startX = (int)centerPos.X - (rectWidth * slotsPerRow + spacing * (slotsPerRow - 1)) / 2; + int startY = (int)centerPos.Y - rows * (spacing + rectHeight); Rectangle slotRect = new Rectangle(startX, startY, rectWidth, rectHeight); Rectangle draggingItemSlot = slotRect; diff --git a/Subsurface/Items/Item.cs b/Subsurface/Items/Item.cs index f1c69953e..3bb86d37c 100644 --- a/Subsurface/Items/Item.cs +++ b/Subsurface/Items/Item.cs @@ -166,6 +166,12 @@ namespace Subsurface } + public Item(ItemPrefab itemPrefab, Vector2 position) + : this(new Rectangle((int)position.X, (int)position.Y, (int)itemPrefab.sprite.size.X, (int)itemPrefab.sprite.size.Y), itemPrefab) + { + + } + public Item(Rectangle newRect, ItemPrefab itemPrefab) { prefab = itemPrefab; diff --git a/Subsurface/Items/ItemInventory.cs b/Subsurface/Items/ItemInventory.cs index 5cdf85cf7..5fd589516 100644 --- a/Subsurface/Items/ItemInventory.cs +++ b/Subsurface/Items/ItemInventory.cs @@ -1,4 +1,5 @@ -using Subsurface.Items.Components; +using Microsoft.Xna.Framework; +using Subsurface.Items.Components; namespace Subsurface { @@ -6,8 +7,8 @@ namespace Subsurface { ItemContainer container; - public ItemInventory(ItemContainer container, int capacity) - : base(capacity) + public ItemInventory(ItemContainer container, int capacity, Vector2? centerPos = null, int slotsPerRow = 5) + : base(capacity, centerPos, slotsPerRow) { this.container = container; } diff --git a/Subsurface/Map/Map.cs b/Subsurface/Map/Map.cs index 05d67c70c..0ac4f41f1 100644 --- a/Subsurface/Map/Map.cs +++ b/Subsurface/Map/Map.cs @@ -524,14 +524,10 @@ namespace Subsurface private void Clear() { - filePath = ""; - if (Game1.GameScreen.Cam != null) Game1.GameScreen.Cam.TargetPos = Vector2.Zero; Entity.RemoveAll(); - if (Game1.GameSession != null) Game1.GameSession.EndShift(null, null); - PhysicsBody.list.Clear(); Ragdoll.list.Clear(); diff --git a/Subsurface/Networking/GameClient.cs b/Subsurface/Networking/GameClient.cs index eae49a78e..e3108b808 100644 --- a/Subsurface/Networking/GameClient.cs +++ b/Subsurface/Networking/GameClient.cs @@ -240,8 +240,8 @@ namespace Subsurface.Networking TimeSpan duration = new TimeSpan(0,(int)durationMinutes,0); //int gameModeIndex = inc.ReadInt32(); - Game1.GameSession = new GameSession(Map.Loaded, duration); - Game1.GameSession.StartShift(1); + Game1.GameSession = new GameSession(Map.Loaded); + Game1.GameSession.StartShift(duration, 1); myCharacter = ReadCharacterData(inc); Character.Controlled = myCharacter; diff --git a/Subsurface/Networking/GameServer.cs b/Subsurface/Networking/GameServer.cs index 8704f091b..d57040920 100644 --- a/Subsurface/Networking/GameServer.cs +++ b/Subsurface/Networking/GameServer.cs @@ -9,7 +9,6 @@ namespace Subsurface.Networking { class GameServer : NetworkMember { - // Server object NetServer Server; // Configuration object @@ -275,8 +274,8 @@ namespace Subsurface.Networking //selectedMap.Load(); - Game1.GameSession = new GameSession(selectedMap, Game1.NetLobbyScreen.GameDuration, Game1.NetLobbyScreen.SelectedMode); - Game1.GameSession.StartShift(1); + Game1.GameSession = new GameSession(selectedMap, Game1.NetLobbyScreen.SelectedMode); + Game1.GameSession.StartShift(Game1.NetLobbyScreen.GameDuration, 1); //EventManager.SelectEvent(Game1.netLobbyScreen.SelectedEvent); foreach (Client client in connectedClients) diff --git a/Subsurface/Screens/LobbyScreen.cs b/Subsurface/Screens/LobbyScreen.cs index 7b573ff33..508569e85 100644 --- a/Subsurface/Screens/LobbyScreen.cs +++ b/Subsurface/Screens/LobbyScreen.cs @@ -3,6 +3,7 @@ using FarseerPhysics.Dynamics; using FarseerPhysics.Factories; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; +using System; namespace Subsurface { @@ -351,7 +352,7 @@ namespace Subsurface private bool StartShift(GUIButton button, object selection) { - Game1.GameSession.StartShift(); + Game1.GameSession.StartShift(TimeSpan.Zero); Game1.GameScreen.Select(); return true; diff --git a/Subsurface/Screens/MainMenu.cs b/Subsurface/Screens/MainMenu.cs index da30e75e1..5e442a034 100644 --- a/Subsurface/Screens/MainMenu.cs +++ b/Subsurface/Screens/MainMenu.cs @@ -176,7 +176,7 @@ namespace Subsurface Map selectedMap = mapList.SelectedData as Map; if (selectedMap == null) return false; - Game1.GameSession = new GameSession(selectedMap, TimeSpan.Zero, GameModePreset.list.Find(gm => gm.Name == "Single Player")); + Game1.GameSession = new GameSession(selectedMap, GameModePreset.list.Find(gm => gm.Name == "Single Player")); Game1.LobbyScreen.Select(); diff --git a/Subsurface/Subsurface.csproj b/Subsurface/Subsurface.csproj index 97d8e02d9..19d88f624 100644 --- a/Subsurface/Subsurface.csproj +++ b/Subsurface/Subsurface.csproj @@ -78,6 +78,7 @@ + @@ -303,6 +304,13 @@ PreserveNewest + + PreserveNewest + + + PreserveNewest + Designer + PreserveNewest @@ -435,22 +443,22 @@ PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest @@ -585,7 +593,7 @@ PreserveNewest - + PreserveNewest diff --git a/Subsurface_Solution.v12.suo b/Subsurface_Solution.v12.suo index 62606192a817994e4cab53434bcefa4f7ce97fb9..dcfebe70664f2612937303845eda5c42152c22dc 100644 GIT binary patch delta 13032 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 delta 18069 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 r3&QzQ^=}