From aa3882a8159c38f02a275e59342e681d75b8787a Mon Sep 17 00:00:00 2001 From: Regalis Date: Sat, 17 Oct 2015 21:24:00 +0300 Subject: [PATCH] Added wire-tag to all wires (to allow using it for fixes even if the name isn't ''Wire''), disconnect networkmember when going to main menu, fixed questmode crashing in multiplayer, fixed too short seeds throwing an error, attachable items aren't attached if secondary key isn't held, update hull when attaching an item, dropping connected wires when detaching items, kicking players with a button click instead of debugconsole --- Subsurface/Content/Items/Door/doors.xml | 14 ++- .../Content/Items/Electricity/signalitems.xml | 8 +- Subsurface/Source/Events/Quests/Quest.cs | 2 + Subsurface/Source/GUI/GUI.cs | 5 + Subsurface/Source/Items/Components/Door.cs | 7 +- .../Items/Components/Holdable/Holdable.cs | 27 +++++ .../Items/Components/Holdable/Pickable.cs | 15 +++ Subsurface/Source/Items/FixRequirement.cs | 2 +- Subsurface/Source/Items/Item.cs | 6 +- Subsurface/Source/Networking/GameClient.cs | 4 +- Subsurface/Source/Networking/NetworkMember.cs | 2 +- Subsurface/Source/Screens/MainMenuScreen.cs | 6 ++ Subsurface/Source/Screens/NetLobbyScreen.cs | 102 +++++++++++------- Subsurface/Source/Utils/ToolBox.cs | 7 ++ Subsurface_Solution.v12.suo | Bin 803328 -> 803328 bytes 15 files changed, 156 insertions(+), 51 deletions(-) diff --git a/Subsurface/Content/Items/Door/doors.xml b/Subsurface/Content/Items/Door/doors.xml index 3fafbebbf..7e1d1e859 100644 --- a/Subsurface/Content/Items/Door/doors.xml +++ b/Subsurface/Content/Items/Door/doors.xml @@ -6,13 +6,18 @@ - + + + + + + @@ -30,7 +35,7 @@ - + @@ -38,6 +43,11 @@ + + + + + diff --git a/Subsurface/Content/Items/Electricity/signalitems.xml b/Subsurface/Content/Items/Electricity/signalitems.xml index 8e64051b4..6f4f3ea07 100644 --- a/Subsurface/Content/Items/Electricity/signalitems.xml +++ b/Subsurface/Content/Items/Electricity/signalitems.xml @@ -4,7 +4,7 @@ (); + if (connectionPanel!=null) + { + foreach (Connection c in connectionPanel.connections) + { + foreach (Wire w in c.Wires) + { + if (w == null) continue; + + w.Item.Drop(picker); + w.Item.SetTransform(item.SimPosition, 0.0f); + } + } + } + ApplyStatusEffects(ActionType.OnPicked, 1.0f, picker); //foreach (StatusEffect effect in item.Prefab.statusEffects) diff --git a/Subsurface/Source/Items/FixRequirement.cs b/Subsurface/Source/Items/FixRequirement.cs index e60892550..4c734809a 100644 --- a/Subsurface/Source/Items/FixRequirement.cs +++ b/Subsurface/Source/Items/FixRequirement.cs @@ -53,7 +53,7 @@ namespace Barotrauma GUIComponent component = reqFrame.children.Find(c => c.UserData as string == itemName); GUITextBlock text = component as GUITextBlock; - Item item = character.Inventory.items.FirstOrDefault(i => i !=null && i.Name == itemName); + Item item = character.Inventory.items.FirstOrDefault(i => i !=null && (i.Name == itemName || i.HasTag(itemName))); bool itemFound = (item != null); if (!itemFound) success = false; diff --git a/Subsurface/Source/Items/Item.cs b/Subsurface/Source/Items/Item.cs index e4004b4c4..993d84ee6 100644 --- a/Subsurface/Source/Items/Item.cs +++ b/Subsurface/Source/Items/Item.cs @@ -339,6 +339,8 @@ namespace Barotrauma rect.X = (int)(displayPos.X - rect.Width / 2.0f); rect.Y = (int)(displayPos.Y + rect.Height / 2.0f); + + FindHull(); } public override void Move(Vector2 amount) @@ -390,7 +392,7 @@ namespace Barotrauma public bool HasTag(string tag) { - return (tags.Contains(tag)); + return (tags.Contains(tag) || tags.Contains(tag.ToLower())); } @@ -863,7 +865,7 @@ namespace Barotrauma { picker.SelectedConstruction = (picker.SelectedConstruction == this) ? null : this; } - + if (!hasRequiredSkills && Character.Controlled==picker) { GUI.AddMessage("Your skills may be insufficient to use the item!", Color.Red, 5.0f); diff --git a/Subsurface/Source/Networking/GameClient.cs b/Subsurface/Source/Networking/GameClient.cs index 3b45763df..dd465b6f3 100644 --- a/Subsurface/Source/Networking/GameClient.cs +++ b/Subsurface/Source/Networking/GameClient.cs @@ -404,7 +404,8 @@ namespace Barotrauma.Networking string msg = inc.ReadString(); new GUIMessageBox("You have been kicked out from the server", msg); - + + Disconnect(); GameMain.MainMenuScreen.Select(); break; @@ -433,7 +434,6 @@ namespace Barotrauma.Networking private IEnumerable StartGame(NetIncomingMessage inc) { - if (this.Character != null) Character.Remove(); int seed = inc.ReadInt32(); diff --git a/Subsurface/Source/Networking/NetworkMember.cs b/Subsurface/Source/Networking/NetworkMember.cs index a283e3e40..bb9d01277 100644 --- a/Subsurface/Source/Networking/NetworkMember.cs +++ b/Subsurface/Source/Networking/NetworkMember.cs @@ -115,7 +115,7 @@ namespace Barotrauma.Networking crewFrame = new GUIFrame(new Rectangle(GameMain.GraphicsWidth / 2 - width / 2, GameMain.GraphicsHeight / 2 - height / 2, width, height), GUI.Style); crewFrame.Padding = new Vector4(10.0f, 10.0f, 10.0f, 10.0f); - GUIListBox crewList = new GUIListBox(new Rectangle(0, 0, 200, 300), Color.White * 0.7f, GUI.Style, crewFrame); + GUIListBox crewList = new GUIListBox(new Rectangle(0, 0, 300, 300), Color.White * 0.7f, GUI.Style, crewFrame); crewList.Padding = new Vector4(10.0f, 10.0f, 10.0f, 10.0f); crewList.OnSelected = SelectCharacter; diff --git a/Subsurface/Source/Screens/MainMenuScreen.cs b/Subsurface/Source/Screens/MainMenuScreen.cs index bf973a0a3..b50efa362 100644 --- a/Subsurface/Source/Screens/MainMenuScreen.cs +++ b/Subsurface/Source/Screens/MainMenuScreen.cs @@ -155,6 +155,12 @@ namespace Barotrauma { base.Select(); + if (GameMain.NetworkMember != null) + { + GameMain.NetworkMember.Disconnect(); + GameMain.NetworkMember = null; + } + Submarine.Unload(); SelectTab(null, 0); diff --git a/Subsurface/Source/Screens/NetLobbyScreen.cs b/Subsurface/Source/Screens/NetLobbyScreen.cs index 669459947..720b5184c 100644 --- a/Subsurface/Source/Screens/NetLobbyScreen.cs +++ b/Subsurface/Source/Screens/NetLobbyScreen.cs @@ -23,12 +23,12 @@ namespace Barotrauma private GUITextBox textBox, seedBox; - //private GUIScrollBar durationBar; - - private GUIFrame playerFrame; + private GUIFrame myPlayerFrame; private GUIFrame jobInfoFrame; + private GUIFrame playerFrame; + private float camAngle; public bool IsServer; @@ -125,11 +125,11 @@ namespace Barotrauma //player info panel ------------------------------------------------------------ - playerFrame = new GUIFrame( + myPlayerFrame = new GUIFrame( new Rectangle((int)(panelRect.Width * 0.7f + 20), 0, (int)(panelRect.Width * 0.3f - 20), (int)(panelRect.Height * 0.6f)), GUI.Style, menu); - playerFrame.Padding = new Vector4(20.0f, 20.0f, 20.0f, 20.0f); + myPlayerFrame.Padding = new Vector4(20.0f, 20.0f, 20.0f, 20.0f); //player list ------------------------------------------------------------------ @@ -139,6 +139,7 @@ namespace Barotrauma GUI.Style, menu); playerList = new GUIListBox(new Rectangle(0,0,0,0), null, GUI.Style, playerListFrame); + playerList.OnSelected = SelectPlayer; //submarine list ------------------------------------------------------------------ @@ -203,16 +204,6 @@ namespace Barotrauma columnX += modeDescription.Rect.Width + 40; - //duration ------------------------------------------------------------------ - - //GUITextBlock durationText = new GUITextBlock(new Rectangle(columnX, 120, columnWidth, 20), - // "Duration: ", GUI.Style, Alignment.Left, Alignment.TopLeft, infoFrame); - //durationText.TextGetter = DurationText; - - //durationBar = new GUIScrollBar(new Rectangle(columnX, 150, columnWidth, 20), - // GUI.Style, 0.1f, infoFrame); - //durationBar.BarSize = 0.1f; - //seed ------------------------------------------------------------------ new GUITextBlock(new Rectangle(columnX, 120, columnWidth, 20), @@ -253,6 +244,7 @@ namespace Barotrauma GameMain.GameScreen.Cam.TargetPos = Vector2.Zero; subList.Enabled = GameMain.Server != null; + playerList.Enabled = GameMain.Server != null; modeList.Enabled = GameMain.Server != null; seedBox.Enabled = GameMain.Server != null; serverMessage.Enabled = GameMain.Server != null; @@ -274,9 +266,9 @@ namespace Barotrauma if (subList.CountChildren > 0 && subList.Selected == null) subList.Select(-1); if (GameModePreset.list.Count > 0 && modeList.Selected == null) modeList.Select(-1); - if (playerFrame.children.Find(c => c.UserData as string == "playyourself") == null) + if (myPlayerFrame.children.Find(c => c.UserData as string == "playyourself") == null) { - var playYourself = new GUITickBox(new Rectangle(-10, -10, 20, 20), "Play yourself", Alignment.TopLeft, playerFrame); + var playYourself = new GUITickBox(new Rectangle(-10, -10, 20, 20), "Play yourself", Alignment.TopLeft, myPlayerFrame); playYourself.Selected = GameMain.Server.CharacterInfo != null; playYourself.OnSelected = TogglePlayYourself; playYourself.UserData = "playyourself"; @@ -292,40 +284,40 @@ namespace Barotrauma private void UpdatePlayerFrame(CharacterInfo characterInfo) { - if (playerFrame.children.Count <= 1) + if (myPlayerFrame.children.Count <= 1) { - playerFrame.ClearChildren(); + myPlayerFrame.ClearChildren(); if (IsServer && GameMain.Server != null) { - var playYourself = new GUITickBox(new Rectangle(-10, -10, 20, 20), "Play yourself", Alignment.TopLeft, playerFrame); + var playYourself = new GUITickBox(new Rectangle(-10, -10, 20, 20), "Play yourself", Alignment.TopLeft, myPlayerFrame); playYourself.Selected = GameMain.Server.CharacterInfo != null; playYourself.OnSelected = TogglePlayYourself; playYourself.UserData = "playyourself"; } - new GUITextBlock(new Rectangle(60, 30, 200, 30), "Name: ", GUI.Style, playerFrame); + new GUITextBlock(new Rectangle(60, 30, 200, 30), "Name: ", GUI.Style, myPlayerFrame); GUITextBox playerName = new GUITextBox(new Rectangle(60, 55, 0, 20), - Alignment.TopLeft, GUI.Style, playerFrame); + Alignment.TopLeft, GUI.Style, myPlayerFrame); playerName.Text = characterInfo.Name; playerName.OnEnter += ChangeCharacterName; - new GUITextBlock(new Rectangle(0, 100, 200, 30), "Gender: ", GUI.Style, playerFrame); + new GUITextBlock(new Rectangle(0, 100, 200, 30), "Gender: ", GUI.Style, myPlayerFrame); GUIButton maleButton = new GUIButton(new Rectangle(70, 100, 60, 20), "Male", - Alignment.TopLeft, GUI.Style, playerFrame); + Alignment.TopLeft, GUI.Style, myPlayerFrame); maleButton.UserData = Gender.Male; maleButton.OnClicked += SwitchGender; GUIButton femaleButton = new GUIButton(new Rectangle(140, 100, 60, 20), "Female", - Alignment.TopLeft, GUI.Style, playerFrame); + Alignment.TopLeft, GUI.Style, myPlayerFrame); femaleButton.UserData = Gender.Female; femaleButton.OnClicked += SwitchGender; - new GUITextBlock(new Rectangle(0, 150, 200, 30), "Job preferences:", GUI.Style, playerFrame); + new GUITextBlock(new Rectangle(0, 150, 200, 30), "Job preferences:", GUI.Style, myPlayerFrame); - jobList = new GUIListBox(new Rectangle(0, 180, 0, 0), GUI.Style, playerFrame); + jobList = new GUIListBox(new Rectangle(0, 180, 0, 0), GUI.Style, myPlayerFrame); jobList.Enabled = false; @@ -366,14 +358,14 @@ namespace Barotrauma } else { - playerFrame.ClearChildren(); + myPlayerFrame.ClearChildren(); if (IsServer && GameMain.Server != null) { GameMain.Server.CharacterInfo = null; GameMain.Server.Character = null; - var playYourself = new GUITickBox(new Rectangle(0, -20, 20, 20), "Play yourself", Alignment.TopLeft, playerFrame); + var playYourself = new GUITickBox(new Rectangle(0, -20, 20, 20), "Play yourself", Alignment.TopLeft, myPlayerFrame); playYourself.OnSelected = TogglePlayYourself; } } @@ -430,11 +422,43 @@ namespace Barotrauma if (child != null) playerList.RemoveChild(child); } - //public void RemovePlayer(Client client) - //{ - // if (client == null) return; - // playerList.RemoveChild(playerList.GetChild(client)); - //} + private bool SelectPlayer(GUIComponent component, object obj) + { + playerFrame = new GUIFrame(new Rectangle(0, 0, 0, 0), Color.Black * 0.3f); + + var playerFrameInner = new GUIFrame(new Rectangle(0,0,300,150), null, Alignment.Center, GUI.Style, playerFrame); + playerFrameInner.Padding = new Vector4(20.0f, 20.0f, 20.0f, 20.0f); + + new GUITextBlock(new Rectangle(0,0,200,20), component.UserData.ToString(), + GUI.Style, Alignment.TopLeft, Alignment.TopLeft, + playerFrameInner, false, GUI.LargeFont); + + var kickButton = new GUIButton(new Rectangle(0, 0, 100, 20), "Kick", Alignment.BottomLeft, GUI.Style, playerFrameInner); + kickButton.UserData = obj; + kickButton.OnClicked += KickPlayer; + kickButton.OnClicked += ClosePlayerFrame; + + var closeButton = new GUIButton(new Rectangle(0, 0, 100, 20), "Close", Alignment.BottomRight, GUI.Style, playerFrameInner); + closeButton.OnClicked = ClosePlayerFrame; + + return true; + } + + private bool ClosePlayerFrame(GUIButton button, object userData) + { + playerFrame = null; + + return true; + } + + private bool KickPlayer(GUIButton button, object userData) + { + if (GameMain.Server == null || userData == null) return false; + + GameMain.Server.KickPlayer(userData.ToString()); + + return false; + } public void ClearPlayers() { @@ -465,6 +489,8 @@ namespace Barotrauma menu.Update((float)deltaTime); if (jobInfoFrame != null) jobInfoFrame.Update((float)deltaTime); + + if (playerFrame != null) playerFrame.Update((float)deltaTime); //durationBar.BarScroll = Math.Max(durationBar.BarScroll, 1.0f / 60.0f); } @@ -483,6 +509,8 @@ namespace Barotrauma //if (previewPlayer!=null) previewPlayer.Draw(spriteBatch); + if (playerFrame != null) playerFrame.Draw(spriteBatch); + GUI.Draw((float)deltaTime, spriteBatch, null); spriteBatch.End(); @@ -522,10 +550,10 @@ namespace Barotrauma private void UpdatePreviewPlayer(CharacterInfo characterInfo) { - GUIComponent existing = playerFrame.FindChild("playerhead"); - if (existing != null) playerFrame.RemoveChild(existing); + GUIComponent existing = myPlayerFrame.FindChild("playerhead"); + if (existing != null) myPlayerFrame.RemoveChild(existing); - GUIImage image = new GUIImage(new Rectangle(0, 40, 30, 30), characterInfo.HeadSprite, Alignment.TopLeft, playerFrame); + GUIImage image = new GUIImage(new Rectangle(0, 40, 30, 30), characterInfo.HeadSprite, Alignment.TopLeft, myPlayerFrame); image.UserData = "playerhead"; } diff --git a/Subsurface/Source/Utils/ToolBox.cs b/Subsurface/Source/Utils/ToolBox.cs index bf8abcf2c..fffb718f4 100644 --- a/Subsurface/Source/Utils/ToolBox.cs +++ b/Subsurface/Source/Utils/ToolBox.cs @@ -301,8 +301,15 @@ namespace Barotrauma { str = str.Substring(0, Math.Min(str.Length, 32)); + str = str.PadLeft(4, 'a'); + byte[] asciiBytes = Encoding.ASCII.GetBytes(str); + for (int i = 4; i < asciiBytes.Length; i++) + { + asciiBytes[i % 4] |= asciiBytes[i]; + } + return BitConverter.ToInt32(asciiBytes, 0); } diff --git a/Subsurface_Solution.v12.suo b/Subsurface_Solution.v12.suo index 4163918879880b3a2eb8e967f0a4bca85dc34609..b611f99c7e5bbc437e76fbec64fe47d2bb40b83a 100644 GIT binary patch delta 3953 zcmd6pd34m(702hk_xoj*3}g~WNG1vSISv6$2w5O%w2%gfDcrY8ZqVcw&a*91-FSH9JW<^=;wJYwX zDmEj+@ZA3C5oUEZ`y=fLo?};%Mc|We{FamIkcLZ_psIID+oZAhSXJbFrjmMx{E%}4 z;+BIkUEq-=*9Ykj85(1# zlrHHG^-j}ANiQJkI6O|sDUjEKdx46!dZ&5b6_=fcs9Z@yDpyFsOiPno?V}y$E_ANb zt?l*E^`zUZdb`$WFuVptqmP_&C`z31(Kxdn8~TaSi|KGs>DxwC?osx4F^|HQK+K5$HT8PvGq{tNVR)*|{a zOmBi(Fa_;Zkas}}*wJ)@C^7X_z>I#`>!Ew5eCCn$R*$qXaN_2AAE$EPar=4 zX6PM|L688xFc=aI*-*}a7r-e5?1a?!CymsD#r>mCp_#xiK3pF|4~R#LXrP*!V-F6G z-$iu+g$0$Qw%GrcAk$?MMAOud-B{hg12CsosSSNyZ=t%~3qurf1 z7itPRx(;S5WWDZ!{uw9$i$Mv91qLt>)PWR(nwxl2fdthAuE3`wAp3%6K@!^f$}Bic zQ_Qp6n8J56cX8WT#V5d6`)>M<%sW&EK+rL6&aD>i)-B(wBUhEWL_R@6ogI zU6%Cw>atlH|CMogF#lw|v8vFaIWnk=UR1s^Y0C4gjZ|;EL#=5`m99emMMEKrRoiTR zgl8Qu7Q1J#Y;kTKcdNVmW(m(r+^>4)ID^ivt|+x;>R93N^I~;3%Mu-aK3;k_yo06O zAFxqh;VmMkaMrWcW^y7TJuIrDo_*Vcry-;aGpbl1eqv0aX{L66D%BZP#U*LZ-qb>M zaUEoN3^(Q`;5BMpS>&{fnyblSa-iGPu&zBGD&}-06UBe#1Jq1r79AccF%cys{8(aLt6M|{ZM0(=z z)r*kl;JXbn8&Y3_n%e4#%iB7PqYlJx|CA#U79ISyT|MbI&DAJ9+jPRI$M639$EyN~)O+zvet zzV(pXz^kALw2S6_lqgPrz;lJ;L!94oq;*z!YAa~GG&juDQ9+0FdXx3H@=x0NQ)IN! zG*NJxmx%n0<~VJ7uJjBAI&p9=a8~W-icnr5WlKJ*Hxtq|L~;w|VM|0*y3ieN2X{)+NqfbRx!uc3~4>t z(yZ^ynz!=3_ijH{SUO?l_)(%@8pVnOL!_aBUCbJK48%GIO7WJSQxTrOPzfvSc}u`x zx)Cu&;c*+tA82Ay^>%Wojy-#SIjD+%-Y!dE(?9kGV zvm@iS#vwnNlEK^h1cove7{w**6>jEIb_H$){cK&+vvc8@#QcF<`N(Rkluq|*gRRnG zs_tYtV)Hpul2*Ko*W$6ukcvh9S##gy*12g5I_6hw`eH_NR`J;Z`hTm?-Jti|Exeyc zjuCDBEGD)7ltufnosvm3-!3O>$rtD#MO{3X@l{*FncB%GTBg@dZdJ4Vv07AspXv9@ zODQk(KU5rOBv+53x`=A{uBh}sTR*p`ntmv%=#5aju;wgK0liSW^g8DjQRcD4idzOS zr?}3--lQi5MY8U|0nX?ly@W=J-w&6qV$DCz>EhvU_+GkSG_2r7qAL*Ti22>uUp|=B z@#)f7Tg^N28-@K0GepBHl&?_}@9rg{%j6u}hL)Jw_q`F>{8H7uIY(FjYfI?-X{9Im z%d|Cv=^K86e;{jgl$Dch>E@BqP2~+su4lz5wb{)vV&O41LOi~J^${6)6eH?oY%G0> z&Z%5bCodJ=r_AwU>J07_Pfz1%qTVLu|F|w1j+oNK_0##@fQz$0C%1+@9(sN+_ju&* zLe|0_4`gr)Y$jCdCFoj%k>6WWFLPd+QvZxD{NMQX*_I%XVf+c6>Mp0B4)YGpx73;v*w2~j zO+|m1Qmgz!9V;dmX7KZC`Nzro{!%%MYiv6OD7?aZHS5nm7O(&6)q=SPMf$l8w@$Bo_WPxw@RYOokHi^pmU4)TTc iqf@8h)IC8ym*jKFK39a#W%RjBK9||&vIJa_7yb>3{-Ems delta 3903 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