diff --git a/Subsurface/Barotrauma.csproj b/Subsurface/Barotrauma.csproj index 23959c65e..8bca4e69c 100644 --- a/Subsurface/Barotrauma.csproj +++ b/Subsurface/Barotrauma.csproj @@ -51,1390 +51,1401 @@ Only *.allowedextension files will be included, which doesn't exist in my case. --> .allowedextension - - prompt - 4 - false - - - Icon.ico - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - False - C:\Program Files (x86)\MonoGame\v3.0\Assemblies\Windows\MonoGame.Framework.dll - - - False - .\NVorbis.dll - - - False - C:\Program Files (x86)\MonoGame\v3.0\Assemblies\DesktopGL\OpenTK.dll - - - - ..\packages\RestSharp.105.1.0\lib\net4\RestSharp.dll - - - - - - - - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - Designer - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - Designer - PreserveNewest - - - PreserveNewest - - - Designer - PreserveNewest - - - PreserveNewest - - - Designer - PreserveNewest - - - Designer - PreserveNewest - - - Designer - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - Designer - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - Designer - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - Designer - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - Designer - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - Designer - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - Designer - - - PreserveNewest - Designer - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - Designer - - - PreserveNewest - - - Designer - PreserveNewest - - - PreserveNewest - - - Designer - PreserveNewest - - - PreserveNewest - - - Designer - PreserveNewest - - - PreserveNewest - Designer - - - PreserveNewest - - - PreserveNewest - Designer - - - PreserveNewest - - - PreserveNewest - Designer - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - Designer - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - Designer - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - Designer - - - PreserveNewest - - - PreserveNewest - Designer - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - Designer - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - Designer - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - Designer - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - Designer - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - Designer - - - PreserveNewest - - - PreserveNewest - Designer - - - PreserveNewest - Designer - - - PreserveNewest - - - PreserveNewest - Designer - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - Designer - - - PreserveNewest - Designer - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - Designer - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - Designer - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - Always - - - PreserveNewest - Designer - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - Designer - - - PreserveNewest - - - PreserveNewest - Designer - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - Designer - - - PreserveNewest - Designer - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - Designer - - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - - - - - - False - Microsoft .NET Framework 4 %28x86 and x64%29 - true - - - False - .NET Framework 3.5 SP1 Client Profile - false - - - False - .NET Framework 3.5 SP1 - false - - - False - Windows Installer 4.5 - true - - - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - - - - - - - - - - - {0aad36e3-51a5-4a07-ab60-5c8a66bd38b7} - Farseer Physics MonoGame - - - {3b8f9edb-6e5e-450c-abc2-ec49075d0b50} - Hyper.ComponentModel - - - {49ba1c69-6104-41ac-a5d8-b54fa9f696e8} - Lidgren.Network - - - + + prompt + 4 + false + + + Icon.ico + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + False + C:\Program Files (x86)\MonoGame\v3.0\Assemblies\Windows\MonoGame.Framework.dll + + + False + .\NVorbis.dll + + + False + C:\Program Files (x86)\MonoGame\v3.0\Assemblies\DesktopGL\OpenTK.dll + + + + ..\packages\RestSharp.105.1.0\lib\net4\RestSharp.dll + + + + + + + + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + Designer + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + Designer + PreserveNewest + + + PreserveNewest + + + Designer + PreserveNewest + + + PreserveNewest + + + Designer + PreserveNewest + + + Designer + PreserveNewest + + + Designer + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + Designer + PreserveNewest + + + Designer + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + Designer + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + Designer + PreserveNewest + + + PreserveNewest + + + PreserveNewest + Designer + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + Designer + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + Designer + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + Designer + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + Designer + + + PreserveNewest + Designer + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + Designer + + + PreserveNewest + + + Designer + PreserveNewest + + + PreserveNewest + + + Designer + PreserveNewest + + + PreserveNewest + + + Designer + PreserveNewest + + + PreserveNewest + Designer + + + PreserveNewest + + + PreserveNewest + Designer + + + PreserveNewest + + + PreserveNewest + Designer + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + Designer + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + Designer + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + Designer + + + PreserveNewest + + + PreserveNewest + Designer + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + Designer + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + Designer + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + Designer + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + Designer + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + Designer + + + PreserveNewest + + + PreserveNewest + Designer + + + PreserveNewest + Designer + + + PreserveNewest + + + PreserveNewest + Designer + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + Designer + + + PreserveNewest + Designer + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + Designer + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + Designer + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + Always + + + PreserveNewest + Designer + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + Designer + + + PreserveNewest + + + PreserveNewest + Designer + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + Designer + + + PreserveNewest + Designer + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + Designer + + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + + + + + + False + Microsoft .NET Framework 4 %28x86 and x64%29 + true + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + false + + + False + Windows Installer 4.5 + true + + + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + + + + + + + + + + + {0aad36e3-51a5-4a07-ab60-5c8a66bd38b7} + Farseer Physics MonoGame + + + {3b8f9edb-6e5e-450c-abc2-ec49075d0b50} + Hyper.ComponentModel + + + {49ba1c69-6104-41ac-a5d8-b54fa9f696e8} + Lidgren.Network + + + - + diff --git a/Subsurface/Content/Characters/Crawler/crawler.xml b/Subsurface/Content/Characters/Crawler/crawler.xml index 42ae65e14..40f74f270 100644 --- a/Subsurface/Content/Characters/Crawler/crawler.xml +++ b/Subsurface/Content/Characters/Crawler/crawler.xml @@ -30,7 +30,7 @@ - + diff --git a/Subsurface/Content/Characters/Endworm/endworm.xml b/Subsurface/Content/Characters/Endworm/endworm.xml index bfcaecdb7..6abd89cdc 100644 --- a/Subsurface/Content/Characters/Endworm/endworm.xml +++ b/Subsurface/Content/Characters/Endworm/endworm.xml @@ -44,12 +44,12 @@ - + - + diff --git a/Subsurface/Content/Characters/Fractalguardian/fractalguardian.xml b/Subsurface/Content/Characters/Fractalguardian/fractalguardian.xml index 32aa58d7c..c7e2aa8ff 100644 --- a/Subsurface/Content/Characters/Fractalguardian/fractalguardian.xml +++ b/Subsurface/Content/Characters/Fractalguardian/fractalguardian.xml @@ -28,12 +28,12 @@ - + - + diff --git a/Subsurface/Content/Characters/Fractalguardian2/fractalguardian2.xml b/Subsurface/Content/Characters/Fractalguardian2/fractalguardian2.xml index 147a5bd7b..e13311179 100644 --- a/Subsurface/Content/Characters/Fractalguardian2/fractalguardian2.xml +++ b/Subsurface/Content/Characters/Fractalguardian2/fractalguardian2.xml @@ -18,7 +18,7 @@ - + @@ -27,7 +27,7 @@ - + diff --git a/Subsurface/Content/Characters/Human/humanhusk.xml b/Subsurface/Content/Characters/Human/humanhusk.xml new file mode 100644 index 000000000..6e8779705 --- /dev/null +++ b/Subsurface/Content/Characters/Human/humanhusk.xml @@ -0,0 +1,118 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Subsurface/Content/Characters/Human/huskappendage.xml b/Subsurface/Content/Characters/Human/huskappendage.xml new file mode 100644 index 000000000..4a8a23841 --- /dev/null +++ b/Subsurface/Content/Characters/Human/huskappendage.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/Subsurface/Content/Characters/Husk/DivingSuit.png b/Subsurface/Content/Characters/Husk/DivingSuit.png index f95c2e62e..076b6f7e8 100644 Binary files a/Subsurface/Content/Characters/Husk/DivingSuit.png and b/Subsurface/Content/Characters/Husk/DivingSuit.png differ diff --git a/Subsurface/Content/Characters/Husk/husk.xml b/Subsurface/Content/Characters/Husk/husk.xml index cad8e14c9..e3cbf0e71 100644 --- a/Subsurface/Content/Characters/Husk/husk.xml +++ b/Subsurface/Content/Characters/Husk/husk.xml @@ -16,12 +16,22 @@ - - + + + + + + + + + + + + - + @@ -66,14 +76,14 @@ - - - + - - + + + + diff --git a/Subsurface/Content/Characters/Mantis/mantis.xml b/Subsurface/Content/Characters/Mantis/mantis.xml index 76d879210..c5c53f194 100644 --- a/Subsurface/Content/Characters/Mantis/mantis.xml +++ b/Subsurface/Content/Characters/Mantis/mantis.xml @@ -46,7 +46,7 @@ - + diff --git a/Subsurface/Content/Characters/Moloch/moloch.xml b/Subsurface/Content/Characters/Moloch/moloch.xml index 6fb293ffc..c375b9689 100644 --- a/Subsurface/Content/Characters/Moloch/moloch.xml +++ b/Subsurface/Content/Characters/Moloch/moloch.xml @@ -11,7 +11,7 @@ - + diff --git a/Subsurface/Content/Characters/TigerThresher/tigerthresher.xml b/Subsurface/Content/Characters/TigerThresher/tigerthresher.xml index c5cf24d6e..8cd6014e6 100644 --- a/Subsurface/Content/Characters/TigerThresher/tigerthresher.xml +++ b/Subsurface/Content/Characters/TigerThresher/tigerthresher.xml @@ -17,7 +17,7 @@ - + diff --git a/Subsurface/Content/Characters/Watcher/watcher.xml b/Subsurface/Content/Characters/Watcher/watcher.xml index dd12088cc..8c7a24fff 100644 --- a/Subsurface/Content/Characters/Watcher/watcher.xml +++ b/Subsurface/Content/Characters/Watcher/watcher.xml @@ -6,6 +6,7 @@ + @@ -13,8 +14,7 @@ - - + diff --git a/Subsurface/Content/InfoTexts.xml b/Subsurface/Content/InfoTexts.xml index 9e8e83c1a..8f2fd415c 100644 --- a/Subsurface/Content/InfoTexts.xml +++ b/Subsurface/Content/InfoTexts.xml @@ -11,6 +11,7 @@ Suffocated Crushed by water pressure Burned to death + Taken over by a parasite Disconnected You have succumbed to your injuries. @@ -19,6 +20,17 @@ You have suffocated. You have been crushed by water pressure. You have burned to death. + The parasite has taken over your body. You have been disconnected from the server. + Your throat feels sore + Your feel feverish + It feels as if something was stuck in your throat + Your muscles are aching + + You feel something moving in your throat. You try to scream but no sound comes out. + + A strange chitinous appendage bursts out from your mouth. Use it to inject eggs into a living body by pressing [Attack]! + + \ No newline at end of file diff --git a/Subsurface/Content/Items/Fabricators/fabricators.xml b/Subsurface/Content/Items/Fabricators/fabricators.xml index 08d3cf413..35644e088 100644 --- a/Subsurface/Content/Items/Fabricators/fabricators.xml +++ b/Subsurface/Content/Items/Fabricators/fabricators.xml @@ -131,7 +131,10 @@ - + + + + diff --git a/Subsurface/Content/Items/Medical/med.png b/Subsurface/Content/Items/Medical/med.png index e7d7adeb6..e873a14dd 100644 Binary files a/Subsurface/Content/Items/Medical/med.png and b/Subsurface/Content/Items/Medical/med.png differ diff --git a/Subsurface/Content/Items/Medical/medical.xml b/Subsurface/Content/Items/Medical/medical.xml index 44b7570a9..439778e0f 100644 --- a/Subsurface/Content/Items/Medical/medical.xml +++ b/Subsurface/Content/Items/Medical/medical.xml @@ -55,7 +55,7 @@ - + @@ -68,9 +68,9 @@ pickdistance="150" description="A mild stimulant which is used as an incredient in the manufacture of various medicines."> - + - + @@ -95,7 +95,7 @@ - + @@ -115,7 +115,7 @@ - + @@ -140,7 +140,7 @@ - + @@ -164,7 +164,7 @@ - + @@ -180,9 +180,9 @@ Tags="smallitem,chem,medical" pickdistance="150"> - + - + @@ -204,9 +204,9 @@ - + - + @@ -224,7 +224,7 @@ - + @@ -242,7 +242,7 @@ - + @@ -260,7 +260,7 @@ - + @@ -278,9 +278,9 @@ Tags="smallitem,chem,medical" pickdistance="150"> - + - + @@ -298,7 +298,7 @@ - + @@ -314,9 +314,9 @@ Tags="smallitem,chem,medical" pickdistance="150"> - + - + @@ -334,7 +334,7 @@ - + @@ -353,7 +353,7 @@ - + @@ -372,7 +372,7 @@ - + @@ -380,6 +380,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Subsurface/Content/Map/StructurePrefabs.xml b/Subsurface/Content/Map/StructurePrefabs.xml index 711353e8f..7fc9df42a 100644 --- a/Subsurface/Content/Map/StructurePrefabs.xml +++ b/Subsurface/Content/Map/StructurePrefabs.xml @@ -78,7 +78,7 @@ width="24" height="32" resizevertical="true"/> + width = "128" height ="49" body="true" health="100"/> diff --git a/Subsurface/Content/Map/testroom.png b/Subsurface/Content/Map/testroom.png index 00f2787d5..3672e0776 100644 Binary files a/Subsurface/Content/Map/testroom.png and b/Subsurface/Content/Map/testroom.png differ diff --git a/Subsurface/Content/Missions.xml b/Subsurface/Content/Missions.xml index 533354ac4..ce39fc913 100644 --- a/Subsurface/Content/Missions.xml +++ b/Subsurface/Content/Missions.xml @@ -8,7 +8,7 @@ radarlabel="Infrasonic signal" failuremessage="Retrieving the artifact failed" successmessage="The artifact has been succesfully retrieved" - spawntype="ruin" + spawntype="ruin" itemname="Skyholder Artifact"> @@ -44,7 +44,7 @@ reward="800" radarlabel="Tiger Thresher" successmessage="The Tiger Thresher has been killed." - monsterfile="Content/Characters/TigerThresher/tigerthresher.xml"> + monsterfile="Content/Characters/Tigerthresher/tigerthresher.xml"> @@ -113,9 +113,10 @@ description="Reseachers of [location1] need someone to deliver some dangerous chemicals to [location2] for a reward of 200 credits." commonness="10" reward="200" - successmessage="The chemicals have been successfully delivered."> + successmessage="The chemicals have been successfully delivered." + requireddeliveryamount="20"> - + @@ -127,6 +128,19 @@ + + + + + + + + - + successmessage="The clown gear has been successfully delivered." + requireddeliveryamount="35"> + diff --git a/Subsurface/Content/randomevents.xml b/Subsurface/Content/randomevents.xml index 083f4dc49..1fbbdd3da 100644 --- a/Subsurface/Content/randomevents.xml +++ b/Subsurface/Content/randomevents.xml @@ -9,7 +9,7 @@ musictype="monster"/> limb.attack.Range) continue; attackingLimb = limb; break; } - return; } - - UpdateLimbAttack(deltaTime, attackingLimb, attackSimPosition); - + if (attackLimb != null) + { + steeringManager.SteeringSeek(attackSimPosition - (attackLimb.SimPosition - SimPosition)); + if (attackingLimb != null) UpdateLimbAttack(deltaTime, attackingLimb, attackSimPosition); + } } private void UpdateCoolDown(Vector2 attackPosition, float deltaTime) @@ -330,84 +333,15 @@ namespace Barotrauma private void UpdateLimbAttack(float deltaTime, Limb limb, Vector2 attackPosition) { - IDamageable damageTarget = null; + var damageTarget = (wallAttackPos != Vector2.Zero && targetEntity != null) ? targetEntity : selectedAiTarget.Entity as IDamageable; - float dist = ConvertUnits.ToDisplayUnits(Vector2.Distance(limb.SimPosition, attackPosition)); + limb.UpdateAttack(deltaTime, attackPosition, damageTarget); - switch (limb.attack.Type) - { - case AttackType.PinchCW: - case AttackType.PinchCCW: - - float dir = (limb.attack.Type == AttackType.PinchCW) ? 1.0f : -1.0f; - - damageTarget = (wallAttackPos != Vector2.Zero && targetEntity != null) ? targetEntity : selectedAiTarget.Entity as IDamageable; - - attackTimer += deltaTime*0.05f; - - if (damageTarget == null) - { - attackTimer = limb.attack.Duration; - break; - } - - if (dist < limb.attack.Range * 0.5f) - { - attackTimer += deltaTime; - limb.body.ApplyTorque(limb.Mass * 50.0f * Character.AnimController.Dir * dir); - - if (attackTimer >= limb.attack.Duration) - { - limb.attack.DoDamage(Character, damageTarget, limb.WorldPosition, 1.0f, (limb.soundTimer <= 0.0f)); - - limb.soundTimer = Limb.SoundInterval; - } - } - - Vector2 diff = attackPosition - limb.SimPosition; - if (diff.LengthSquared() > 0.00001f) - { - limb.body.ApplyLinearImpulse(limb.Mass * 10.0f * - Vector2.Normalize(attackPosition - limb.SimPosition)); - } - - steeringManager.SteeringSeek(attackPosition + (limb.SimPosition-SimPosition), 5.0f); - - break; - case AttackType.Hit: - damageTarget = (wallAttackPos != Vector2.Zero && targetEntity != null) ? targetEntity : selectedAiTarget.Entity as IDamageable; - - if (damageTarget == null) - { - attackTimer = limb.attack.Duration; - break; - } - - if (dist < limb.attack.Range) - { - attackTimer += deltaTime; - limb.body.ApplyForce(limb.Mass * limb.attack.Force * Vector2.Normalize(attackPosition - limb.SimPosition)); - - if (damageTarget is Character && dist= limb.attack.Duration) + if (limb.AttackTimer >= limb.attack.Duration) { wallAttackPos = Vector2.Zero; - attackTimer = 0.0f; - if (Vector2.Distance(limb.SimPosition, attackPosition)<5.0) coolDownTimer = attackCoolDown; - + limb.AttackTimer = 0.0f; + if (Vector2.Distance(limb.SimPosition, attackPosition)<5.0) coolDownTimer = attackCoolDown; } } diff --git a/Subsurface/Source/Characters/AICharacter.cs b/Subsurface/Source/Characters/AICharacter.cs index 0abe6d1bb..174d1a1c4 100644 --- a/Subsurface/Source/Characters/AICharacter.cs +++ b/Subsurface/Source/Characters/AICharacter.cs @@ -49,7 +49,7 @@ namespace Barotrauma if (isDead || health <= 0.0f) return; - if (Controlled == this) return; + if (Controlled == this || !aiController.Enabled) return; if (soundTimer > 0) { diff --git a/Subsurface/Source/Characters/Animation/HumanoidAnimController.cs b/Subsurface/Source/Characters/Animation/HumanoidAnimController.cs index d63e85977..877fe4be4 100644 --- a/Subsurface/Source/Characters/Animation/HumanoidAnimController.cs +++ b/Subsurface/Source/Characters/Animation/HumanoidAnimController.cs @@ -338,13 +338,13 @@ namespace Barotrauma if (!onGround || (LowestLimb.SimPosition.Y - floorY > 0.5f && stairs == null)) return; - float? ceilingY = null; - if (Submarine.PickBody(head.SimPosition, head.SimPosition + Vector2.UnitY, null, Physics.CollisionWall)!=null) - { - ceilingY = Submarine.LastPickedPosition.Y; + //float? ceilingY = null; + //if (Submarine.PickBody(head.SimPosition, head.SimPosition + Vector2.UnitY, null, Physics.CollisionWall)!=null) + //{ + // ceilingY = Submarine.LastPickedPosition.Y; - if (ceilingY - floorY < HeadPosition) Crouching = true; - } + // if (ceilingY - floorY < HeadPosition) Crouching = true; + //} getUpSpeed = getUpSpeed * Math.Max(head.SimPosition.Y - colliderPos.Y, 0.5f); @@ -456,24 +456,20 @@ namespace Barotrauma else { float movementFactor = (movement.X / 4.0f) * movement.X * Math.Sign(movement.X); - - - //MoveLimb(leftFoot, footPos, 2.5f); - - for (int i = -1; i < 2; i+=2 ) + for (int i = -1; i < 2; i += 2) { - Vector2 footPos = new Vector2( - Crouching ? waist.SimPosition.X + Math.Sign(stepSize.X*i)*Dir*0.3f : waist.SimPosition.X, - colliderPos.Y - 0.2f); + Vector2 footPos = new Vector2( + Crouching ? waist.SimPosition.X + Math.Sign(stepSize.X * i) * Dir * 0.3f : GetCenterOfMass().X, + colliderPos.Y - 0.1f); var foot = i == -1 ? rightFoot : leftFoot; - MoveLimb(foot, footPos, Math.Abs(foot.SimPosition.X - footPos.X)*50.0f); + MoveLimb(foot, footPos, Math.Abs(foot.SimPosition.X - footPos.X) * 100.0f, true); } - leftFoot.body.SmoothRotate(Dir * MathHelper.PiOver2, 5.0f); - rightFoot.body.SmoothRotate(Dir * MathHelper.PiOver2, 5.0f); + leftFoot.body.SmoothRotate(Dir * MathHelper.PiOver2, 50.0f); + rightFoot.body.SmoothRotate(Dir * MathHelper.PiOver2, 50.0f); if (!rightHand.Disabled) { @@ -1183,7 +1179,7 @@ namespace Barotrauma Vector2 position = limb.SimPosition; - if (!limb.pullJoint.Enabled && mirror) + if ((limb.pullJoint==null || !limb.pullJoint.Enabled) && mirror) { difference = limb.body.SimPosition - torso.SimPosition; difference = Vector2.Transform(difference, torsoTransform); diff --git a/Subsurface/Source/Characters/Animation/Ragdoll.cs b/Subsurface/Source/Characters/Animation/Ragdoll.cs index 938838203..9420c33de 100644 --- a/Subsurface/Source/Characters/Animation/Ragdoll.cs +++ b/Subsurface/Source/Characters/Animation/Ragdoll.cs @@ -30,8 +30,8 @@ namespace Barotrauma protected float strongestImpact; - float headPosition, headAngle; - float torsoPosition, torsoAngle; + public float headPosition, headAngle; + public float torsoPosition, torsoAngle; protected double onFloorTimer; @@ -231,8 +231,7 @@ namespace Barotrauma byte ID = Convert.ToByte(subElement.Attribute("id").Value); Limb limb = new Limb(character, subElement, scale); - - + limb.body.FarseerBody.OnCollision += OnLimbCollision; Limbs[ID] = limb; @@ -240,38 +239,7 @@ namespace Barotrauma if (!limbDictionary.ContainsKey(limb.type)) limbDictionary.Add(limb.type, limb); break; case "joint": - Byte limb1ID = Convert.ToByte(subElement.Attribute("limb1").Value); - Byte limb2ID = Convert.ToByte(subElement.Attribute("limb2").Value); - - Vector2 limb1Pos = ToolBox.GetAttributeVector2(subElement, "limb1anchor", Vector2.Zero) * scale; - limb1Pos = ConvertUnits.ToSimUnits(limb1Pos); - - Vector2 limb2Pos = ToolBox.GetAttributeVector2(subElement, "limb2anchor", Vector2.Zero) * scale; - limb2Pos = ConvertUnits.ToSimUnits(limb2Pos); - - RevoluteJoint joint = new RevoluteJoint(Limbs[limb1ID].body.FarseerBody, Limbs[limb2ID].body.FarseerBody, limb1Pos, limb2Pos); - - joint.CollideConnected = false; - - if (subElement.Attribute("lowerlimit")!=null) - { - joint.LimitEnabled = true; - joint.LowerLimit = float.Parse(subElement.Attribute("lowerlimit").Value) * ((float)Math.PI / 180.0f); - joint.UpperLimit = float.Parse(subElement.Attribute("upperlimit").Value) * ((float)Math.PI / 180.0f); - } - - joint.MotorEnabled = true; - joint.MaxMotorTorque = 0.25f; - - GameMain.World.AddJoint(joint); - - for (int i = 0; i < limbJoints.Length; i++ ) - { - if (limbJoints[i] != null) continue; - - limbJoints[i] = joint; - break; - } + AddJoint(subElement, scale); break; } @@ -308,6 +276,58 @@ namespace Barotrauma FindLowestLimb(); } + + public void AddJoint(XElement subElement, float scale = 1.0f) + { + byte limb1ID = Convert.ToByte(subElement.Attribute("limb1").Value); + byte limb2ID = Convert.ToByte(subElement.Attribute("limb2").Value); + + Vector2 limb1Pos = ToolBox.GetAttributeVector2(subElement, "limb1anchor", Vector2.Zero) * scale; + limb1Pos = ConvertUnits.ToSimUnits(limb1Pos); + + Vector2 limb2Pos = ToolBox.GetAttributeVector2(subElement, "limb2anchor", Vector2.Zero) * scale; + limb2Pos = ConvertUnits.ToSimUnits(limb2Pos); + + RevoluteJoint joint = new RevoluteJoint(Limbs[limb1ID].body.FarseerBody, Limbs[limb2ID].body.FarseerBody, limb1Pos, limb2Pos); + + joint.CollideConnected = false; + + if (subElement.Attribute("lowerlimit") != null) + { + joint.LimitEnabled = true; + joint.LowerLimit = float.Parse(subElement.Attribute("lowerlimit").Value) * ((float)Math.PI / 180.0f); + joint.UpperLimit = float.Parse(subElement.Attribute("upperlimit").Value) * ((float)Math.PI / 180.0f); + } + + joint.MotorEnabled = true; + joint.MaxMotorTorque = 0.25f; + + GameMain.World.AddJoint(joint); + + for (int i = 0; i < limbJoints.Length; i++) + { + if (limbJoints[i] != null) continue; + + limbJoints[i] = joint; + return; + } + + Array.Resize(ref limbJoints, limbJoints.Length + 1); + limbJoints[limbJoints.Length - 1] = joint; + + } + + public void AddLimb(Limb limb) + { + limb.body.FarseerBody.OnCollision += OnLimbCollision; + + Array.Resize(ref Limbs, Limbs.Length + 1); + + Limbs[Limbs.Length-1] = limb; + + Mass += limb.Mass; + if (!limbDictionary.ContainsKey(limb.type)) limbDictionary.Add(limb.type, limb); + } public bool OnLimbCollision(Fixture f1, Fixture f2, Contact contact) { diff --git a/Subsurface/Source/Characters/Attack.cs b/Subsurface/Source/Characters/Attack.cs index 869daaca4..6489d4347 100644 --- a/Subsurface/Source/Characters/Attack.cs +++ b/Subsurface/Source/Characters/Attack.cs @@ -2,22 +2,18 @@ using Barotrauma.Particles; using System; using System.Xml.Linq; +using System.Collections.Generic; namespace Barotrauma { enum CauseOfDeath { - Damage, Bloodloss, Pressure, Suffocation, Drowning, Burn, Disconnected + Damage, Bloodloss, Pressure, Suffocation, Drowning, Burn, Husk, Disconnected } public enum DamageType { None, Blunt, Slash, Burn } - public enum AttackType - { - None, PinchCW, PinchCCW, Hit - } - struct AttackResult { public readonly float Damage; @@ -36,8 +32,6 @@ namespace Barotrauma class Attack { - - public readonly AttackType Type; public readonly float Range; public readonly float Duration; @@ -47,8 +41,12 @@ namespace Barotrauma private readonly float damage; private readonly float bleedingDamage; + private readonly List statusEffects; + public readonly float Force; + public readonly float Torque; + public readonly float TargetForce; private Sound sound; @@ -74,23 +72,8 @@ namespace Barotrauma return (Duration == 0.0f) ? structureDamage : structureDamage * deltaTime; } - - //public Attack(AttackType type, float range,) - //{ - - //} - public Attack(XElement element) { - try - { - Type = (AttackType)Enum.Parse(typeof(AttackType), element.Attribute("type").Value, true); - } - catch - { - Type = AttackType.None; - } - try { DamageType = (DamageType)Enum.Parse(typeof(DamageType), ToolBox.GetAttributeString(element, "damagetype", "None"), true); @@ -106,9 +89,10 @@ namespace Barotrauma bleedingDamage = ToolBox.GetAttributeFloat(element, "bleedingdamage", 0.0f); Force = ToolBox.GetAttributeFloat(element,"force", 0.0f); - TargetForce = ToolBox.GetAttributeFloat(element, "targetforce", 0.0f); + Torque = ToolBox.GetAttributeFloat(element, "torque", 0.0f); + Stun = ToolBox.GetAttributeFloat(element, "stun", 0.0f); string soundPath = ToolBox.GetAttributeString(element, "sound", ""); @@ -123,10 +107,20 @@ namespace Barotrauma priority = ToolBox.GetAttributeFloat(element, "priority", 1.0f); + statusEffects = new List(); + foreach (XElement subElement in element.Elements()) { - if (subElement.Name.ToString().ToLowerInvariant() != "particleemitter") continue; - particleEmitterPrefab = new ParticleEmitterPrefab(subElement); + switch (subElement.Name.ToString().ToLowerInvariant()) + { + case "particleemitter": + particleEmitterPrefab = new ParticleEmitterPrefab(subElement); + break; + case "statuseffect": + statusEffects.Add(StatusEffect.Load(subElement)); + break; + } + } } @@ -142,9 +136,24 @@ namespace Barotrauma { sound.Play(1.0f, 500.0f, worldPosition); } + + var attackResult = target.AddDamage(attacker, worldPosition, this, deltaTime, playSound); - return target.AddDamage(attacker, worldPosition, this, deltaTime, playSound); + var effectType = attackResult.Damage > 0.0f ? ActionType.OnUse : ActionType.OnFailure; + foreach (StatusEffect effect in statusEffects) + { + if (effect.Targets.HasFlag(StatusEffect.TargetType.This) && attacker is Character) + { + effect.Apply(effectType, deltaTime, (Character)attacker, (Character)attacker); + } + if (effect.Targets.HasFlag(StatusEffect.TargetType.Character) && target is Character) + { + effect.Apply(effectType, deltaTime, (Character)target, (Character)target); + } + } + + return attackResult; } } } diff --git a/Subsurface/Source/Characters/Character.cs b/Subsurface/Source/Characters/Character.cs index 939e784ef..1ac256e32 100644 --- a/Subsurface/Source/Characters/Character.cs +++ b/Subsurface/Source/Characters/Character.cs @@ -112,6 +112,8 @@ namespace Barotrauma //which AIstate each sound is for private AIController.AiState[] soundStates; + private float attackCoolDown; + public Entity ViewTarget { get; @@ -248,6 +250,7 @@ namespace Barotrauma public bool NeedsAir { get { return needsAir; } + set { needsAir = value; } } public float Oxygen @@ -298,6 +301,38 @@ namespace Barotrauma } } + public HuskInfection huskInfection; + public float HuskInfectionState + { + get + { + return huskInfection == null ? 0.0f : huskInfection.IncubationTimer; + } + set + { + if (ConfigPath != humanConfigFile) return; + + if (value <= 0.0f) + { + if (huskInfection != null && huskInfection.State == HuskInfection.InfectionState.Active) return; + huskInfection = null; + } + else + { + if (huskInfection == null) huskInfection = new HuskInfection(this); + huskInfection.IncubationTimer = MathHelper.Clamp(value, 0.0f, 1.0f); + } + } + } + + public bool CanSpeak + { + get + { + return !IsUnconscious && Stun <= 0.0f && (huskInfection == null || huskInfection.CanSpeak); + } + } + public bool DoesBleed { get; @@ -310,7 +345,6 @@ namespace Barotrauma private set; } - public float PressureTimer { get; @@ -474,13 +508,16 @@ namespace Barotrauma Properties = ObjectProperty.GetProperties(this); - if (file == humanConfigFile) + Info = characterInfo; + if (file == humanConfigFile && characterInfo == null) { - Info = characterInfo == null ? new CharacterInfo(file) : characterInfo; + Info = new CharacterInfo(file); } XDocument doc = ToolBox.TryLoadXml(file); if (doc == null || doc.Root == null) return; + + SpeciesName = ToolBox.GetAttributeString(doc.Root, "name", "Unknown"); @@ -696,6 +733,49 @@ namespace Barotrauma } } + if (attackCoolDown >0.0f) + { + attackCoolDown -= deltaTime; + } + else if (IsKeyDown(InputType.Attack)) + { + var attackLimb = AnimController.Limbs.FirstOrDefault(l => l.attack != null); + + if (attackLimb != null) + { + Vector2 attackPos = + attackLimb.SimPosition + Vector2.Normalize(cursorPosition - attackLimb.Position) * ConvertUnits.ToSimUnits(attackLimb.attack.Range); + + var body = Submarine.PickBody( + attackLimb.SimPosition, + attackPos, + AnimController.Limbs.Select(l => l.body.FarseerBody).ToList(), + Physics.CollisionCharacter | Physics.CollisionWall); + + IDamageable attackTarget = null; + if (body != null) + { + if (body.UserData is IDamageable) + { + attackTarget = (IDamageable)body.UserData; + } + else if (body.UserData is Limb) + { + attackTarget = ((Limb)body.UserData).character; + } + attackPos = Submarine.LastPickedPosition; + } + + attackLimb.UpdateAttack(deltaTime, attackPos, attackTarget); + + if (attackLimb.AttackTimer > attackLimb.attack.Duration) + { + attackLimb.AttackTimer = 0.0f; + attackCoolDown = 1.0f; + } + } + } + for (int i = 0; i < selectedItems.Length; i++ ) { if (selectedItems[i] == null) continue; @@ -784,6 +864,14 @@ namespace Barotrauma return owner.isDead || owner.IsUnconscious || owner.Stun > 0.0f || owner.LockHands; } + if (inventory.Owner is Item) + { + var owner = (Item)inventory.Owner; + if (!CanAccessItem(owner)) + { + return false; + } + } return true; } @@ -791,10 +879,22 @@ namespace Barotrauma { if (item.ParentInventory != null) { - if (!CanAccessInventory(item.ParentInventory)) return false; + return CanAccessInventory(item.ParentInventory); } - return true; + float maxDist = item.PickDistance * 1.2f; + if (maxDist <= 0.01f) + { + maxDist = 150.0f; + } + + if (Vector2.Distance(WorldPosition, item.WorldPosition) < maxDist || + item.IsInsideTrigger(WorldPosition)) + { + return true; + } + + return item.GetComponent() != null; } private Item FindClosestItem(Vector2 mouseSimPos, out float distance) @@ -859,7 +959,7 @@ namespace Barotrauma foreach (Limb limb in selectedCharacter.AnimController.Limbs) { - limb.pullJoint.Enabled = false; + if (limb.pullJoint != null) limb.pullJoint.Enabled = false; } selectedCharacter = null; @@ -923,7 +1023,6 @@ namespace Barotrauma } } - if (!LockHands) { //find the closest item if selectkey has been hit, or if the Character is being @@ -1014,9 +1113,9 @@ namespace Barotrauma // new Character(NewCharacterQueue.Dequeue(), Vector2.Zero); //} - foreach (Character c in CharacterList) + for (int i = 0; i 0.05f && IncubationTimer % 0.1f < 0.05f) + { + GUI.AddMessage(InfoTextManager.GetInfoText("HuskDormant"), Color.Red, 4.0f); + } + } + + private void UpdateTransitionState(float deltaTime, Character character) + { + IncubationTimer += deltaTime / IncubationDuration; + + if (state == InfectionState.Dormant && Character.Controlled == character) + { + new GUIMessageBox("", InfoTextManager.GetInfoText("HuskCantSpeak")); + } + + state = InfectionState.Transition; + } + + private void UpdateActiveState(float deltaTime, Character character) + { + if (state != InfectionState.Active) + { + if (Character.Controlled==character) new GUIMessageBox("", InfoTextManager.GetInfoText("HuskActivate")); + ActivateHusk(character); + state = InfectionState.Active; + } + + character.AddDamage(CauseOfDeath.Husk, 0.5f*deltaTime, null); + + if (character.AnimController.limbJoints[0].LimitEnabled && + (character.AnimController.CurrentHull == null || + character.AnimController.CurrentHull.LethalPressure > 50.0f)) + { + character.BreakJoints(); + character.AnimController.limbJoints.Last().LimitEnabled = true; + } + } + + + private void ActivateHusk(Character character) + { + character.NeedsAir = false; + AttachHuskAppendage(character); + } + + private void AttachHuskAppendage(Character character) + { + XDocument doc = ToolBox.TryLoadXml(Path.Combine("Content", "Characters", "Human", "huskappendage.xml")); + if (doc == null || doc.Root == null) return; + + var limbElement = doc.Root.Element("limb"); + if (limbElement == null) + { + DebugConsole.ThrowError("Error in huskappendage.xml - limb element not found"); + return; + } + + var jointElement = doc.Root.Element("joint"); + if (jointElement == null) + { + DebugConsole.ThrowError("Error in huskappendage.xml - joint element not found"); + return; + } + + character.StartStun(0.5f); + if (character.AnimController.Dir < 1.0f) + { + character.AnimController.Flip(); + } + + var torso = character.AnimController.GetLimb(LimbType.Torso); + torso.body.SetTransform(torso.SimPosition, 0.0f); + + var newLimb = new Limb(character, limbElement); + newLimb.body.Submarine = character.Submarine; + newLimb.body.SetTransform(torso.SimPosition, 0.0f); + + character.AnimController.AddLimb(newLimb); + character.AnimController.AddJoint(jointElement); + } + + private void CharacterDead(Character character, CauseOfDeath causeOfDeath) + { + var husk = Character.Create( + Path.Combine("Content", "Characters", "Human", "humanhusk.xml"), + character.WorldPosition, + character.Info, + false, true); + + foreach (Limb limb in husk.AnimController.Limbs) + { + if (limb.type == LimbType.None) + { + limb.body.SetTransform(character.SimPosition, 0.0f); + continue; + } + + var matchingLimb = character.AnimController.GetLimb(limb.type); + limb.body.SetTransform(matchingLimb.SimPosition, matchingLimb.Rotation); + } + + for (int i = 0; i < character.Inventory.Items.Length; i++) + { + if (character.Inventory.Items[i] == null) continue; + husk.Inventory.TryPutItem(character.Inventory.Items[i], i, false, true); + } + + character.Enabled = false; + + husk.SpawnedMidRound = true; + } + } +} diff --git a/Subsurface/Source/Characters/Limb.cs b/Subsurface/Source/Characters/Limb.cs index 185834879..242846285 100644 --- a/Subsurface/Source/Characters/Limb.cs +++ b/Subsurface/Source/Characters/Limb.cs @@ -156,6 +156,8 @@ namespace Barotrauma private float scale; + public float AttackTimer; + //public float Damage //{ // get { return damage; } @@ -223,6 +225,8 @@ namespace Barotrauma refJointIndex = -1; + Vector2 pullJointPos = Vector2.Zero; + if (element.Attribute("type") != null) { try @@ -236,25 +240,26 @@ namespace Barotrauma } - Vector2 jointPos = ToolBox.GetAttributeVector2(element, "pullpos", Vector2.Zero) * scale; - jointPos = ConvertUnits.ToSimUnits(jointPos); + pullJointPos = ToolBox.GetAttributeVector2(element, "pullpos", Vector2.Zero) * scale; + pullJointPos = ConvertUnits.ToSimUnits(pullJointPos); stepOffset = ToolBox.GetAttributeVector2(element, "stepoffset", Vector2.Zero) * scale; stepOffset = ConvertUnits.ToSimUnits(stepOffset); refJointIndex = ToolBox.GetAttributeInt(element, "refjoint", -1); - pullJoint = new FixedMouseJoint(body.FarseerBody, jointPos); - pullJoint.Enabled = false; - pullJoint.MaxForce = ((type == LimbType.LeftHand || type == LimbType.RightHand) ? 400.0f : 150.0f) * body.Mass; - - GameMain.World.AddJoint(pullJoint); } else { type = LimbType.None; } + pullJoint = new FixedMouseJoint(body.FarseerBody, pullJointPos); + pullJoint.Enabled = false; + pullJoint.MaxForce = ((type == LimbType.LeftHand || type == LimbType.RightHand) ? 400.0f : 150.0f) * body.Mass; + + GameMain.World.AddJoint(pullJoint); + steerForce = ToolBox.GetAttributeFloat(element, "steerforce", 0.0f); //maxHealth = Math.Max(ToolBox.GetAttributeFloat(element, "health", 100.0f),1.0f); @@ -484,6 +489,36 @@ namespace Barotrauma //} } + public void ActivateDamagedSprite() + { + damage = 100.0f; + } + + public void UpdateAttack(float deltaTime, Vector2 attackPosition, IDamageable damageTarget) + { + float dist = ConvertUnits.ToDisplayUnits(Vector2.Distance(SimPosition, attackPosition)); + + AttackTimer += deltaTime; + body.ApplyTorque(Mass * character.AnimController.Dir * attack.Torque); + + if (dist < attack.Range * 0.5f) + { + if (AttackTimer >= attack.Duration && damageTarget != null) + { + attack.DoDamage(character, damageTarget, WorldPosition, 1.0f, (soundTimer <= 0.0f)); + + soundTimer = Limb.SoundInterval; + } + } + + Vector2 diff = attackPosition - SimPosition; + if (diff.LengthSquared() > 0.00001f) + { + Vector2 pos = pullJoint == null ? body.SimPosition : pullJoint.WorldAnchorA; + body.ApplyLinearImpulse(Mass * attack.Force * + Vector2.Normalize(attackPosition - SimPosition), pos); + } + } public void Draw(SpriteBatch spriteBatch) { @@ -492,7 +527,9 @@ namespace Barotrauma body.Dir = Dir; - if (wearingItems.Find(w => w != null && w.HideLimb) == null) + bool hideLimb = wearingItems.Any(w => w != null && w.HideLimb); + + if (!hideLimb) { body.Draw(spriteBatch, sprite, color, null, scale); } @@ -526,7 +563,7 @@ namespace Barotrauma scale, spriteEffect, depth); } - if (damage>0.0f && damagedSprite!=null) + if (damage>0.0f && damagedSprite!=null && !hideLimb) { SpriteEffects spriteEffect = (dir == Direction.Right) ? SpriteEffects.None : SpriteEffects.FlipHorizontally; diff --git a/Subsurface/Source/Characters/StatusEffect.cs b/Subsurface/Source/Characters/StatusEffect.cs index a694f926b..94b8b8c64 100644 --- a/Subsurface/Source/Characters/StatusEffect.cs +++ b/Subsurface/Source/Characters/StatusEffect.cs @@ -173,20 +173,8 @@ namespace Barotrauma break; } } - - //oxygen = ToolBox.GetAttributeFloat(element, "oxygen", 0.0f); - - - //deteriorateOnActive = ToolBox.GetAttributeFloat(element, "deteriorateonactive", 0.0f); - //deteriorateOnUse = ToolBox.GetAttributeFloat(element, "deteriorateonuse", 0.0f); } - - //public virtual void Apply(ActionType type, float deltaTime, Item item, Character Character = null) - //{ - // if (this.type == type) Apply(deltaTime, Character, item); - //} - private bool HasRequiredItems(Entity entity) { if (requiredItems == null) return true; diff --git a/Subsurface/Source/CoroutineManager.cs b/Subsurface/Source/CoroutineManager.cs index 58221cc1c..978cad149 100644 --- a/Subsurface/Source/CoroutineManager.cs +++ b/Subsurface/Source/CoroutineManager.cs @@ -56,55 +56,49 @@ namespace Barotrauma { Coroutines.RemoveAll(c => c == handle); } + private static bool IsDone(CoroutineHandle handle) + { + try + { + if (handle.Coroutine.Current != null) + { + WaitForSeconds wfs = handle.Coroutine.Current as WaitForSeconds; + if (wfs != null) + { + if (!wfs.CheckFinished(UnscaledDeltaTime)) return false; + } + else + { + switch ((CoroutineStatus)handle.Coroutine.Current) + { + case CoroutineStatus.Success: + return true; + case CoroutineStatus.Failure: + DebugConsole.ThrowError("Coroutine ''" + handle.Name + "'' has failed"); + return true; + } + } + } + + handle.Coroutine.MoveNext(); + return false; + } + catch (Exception e) + { + DebugConsole.ThrowError("Coroutine " + handle.Name + " threw an exception: " + e.Message); + return true; + } + } // Updating just means stepping through all the coroutines public static void Update(float unscaledDeltaTime, float deltaTime) { UnscaledDeltaTime = unscaledDeltaTime; DeltaTime = deltaTime; - for (int i = Coroutines.Count-1; i>=0; i--) - { - CoroutineHandle handle = Coroutines[i]; - - try - { - if (handle.Coroutine.Current != null) - { - WaitForSeconds wfs = handle.Coroutine.Current as WaitForSeconds; - if (wfs != null) - { - if (!wfs.CheckFinished(unscaledDeltaTime)) continue; - } - else - { - switch ((CoroutineStatus)handle.Coroutine.Current) - { - case CoroutineStatus.Success: - Coroutines.RemoveAt(i); - continue; - case CoroutineStatus.Failure: - DebugConsole.ThrowError("Coroutine ''" + handle.Name + "'' has failed"); - continue; - } - } - } - - handle.Coroutine.MoveNext(); - } - - catch (Exception e) - { - DebugConsole.ThrowError("Coroutine " + handle.Name + " threw an exception: " + e.Message); - -//#if DEBUG -// throw e; -//#endif - - Coroutines.Remove(handle); - } - - } + foreach (var x in Coroutines.ToList()) + if(IsDone(x)) + Coroutines.Remove(x); } } diff --git a/Subsurface/Source/DebugConsole.cs b/Subsurface/Source/DebugConsole.cs index 308dbada2..1135aa8ca 100644 --- a/Subsurface/Source/DebugConsole.cs +++ b/Subsurface/Source/DebugConsole.cs @@ -363,8 +363,47 @@ namespace Barotrauma case "controlcharacter": case "control": if (commands.Length < 2) break; - string name = string.Join(" ", commands.Skip(1)).ToLowerInvariant(); - Character.Controlled = Character.CharacterList.Find(c => !c.IsNetworkPlayer && c.Name.ToLowerInvariant() == name); + + int characterIndex; + string characterName; + if (int.TryParse(commands.Last(), out characterIndex)) + { + characterName = string.Join(" ", commands.Skip(1).Take(commands.Length-2)).ToLowerInvariant(); + } + else + { + characterName = string.Join(" ", commands.Skip(1)).ToLowerInvariant(); + characterIndex = -1; + } + + var matchingCharacters = Character.CharacterList.FindAll(c => !c.IsNetworkPlayer && c.Name.ToLowerInvariant() == characterName); + + if (!matchingCharacters.Any()) + { + ThrowError("Matching characters not found"); + return; + } + + if (characterIndex==-1) + { + Character.Controlled = matchingCharacters.First(); + if (matchingCharacters.Count > 1) + { + NewMessage( + "Found multiple matching characters. "+ + "Use \"control [charactername] [0-"+(matchingCharacters.Count-1)+"]\" to choose which character to control.", + Color.LightGray); + } + } + else if (characterIndex<0 || characterIndex>= matchingCharacters.Count) + { + ThrowError("Character index out of range. Select an index between 0 and " + (matchingCharacters.Count - 1)); + } + else + { + Character.Controlled = matchingCharacters[characterIndex]; + } + break; case "godmode": if (Submarine.MainSub == null) return; diff --git a/Subsurface/Source/Events/ArtifactEvent.cs b/Subsurface/Source/Events/ArtifactEvent.cs index 2ce06c449..70767c0c5 100644 --- a/Subsurface/Source/Events/ArtifactEvent.cs +++ b/Subsurface/Source/Events/ArtifactEvent.cs @@ -31,7 +31,8 @@ namespace Barotrauma protected override void Start() { - Vector2 position = Level.Loaded.GetRandomItemPos(Level.PositionType.Cave, 30.0f); + Vector2 position = Level.Loaded.GetRandomItemPos( + Level.PositionType.Cave | Level.PositionType.MainPath | Level.PositionType.Ruin, 500.0f, 30.0f); item = new Item(itemPrefab, position, null); item.MoveWithLevel = true; diff --git a/Subsurface/Source/Events/Missions/SalvageMission.cs b/Subsurface/Source/Events/Missions/SalvageMission.cs index 5751ee291..74f7b65c7 100644 --- a/Subsurface/Source/Events/Missions/SalvageMission.cs +++ b/Subsurface/Source/Events/Missions/SalvageMission.cs @@ -49,7 +49,7 @@ namespace Barotrauma public override void Start(Level level) { - Vector2 position = Level.Loaded.GetRandomItemPos(spawnPositionType, 30.0f); + Vector2 position = Level.Loaded.GetRandomItemPos(spawnPositionType, 100.0f, 30.0f); item = new Item(itemPrefab, position, null); item.MoveWithLevel = true; diff --git a/Subsurface/Source/GUI/GUITextBlock.cs b/Subsurface/Source/GUI/GUITextBlock.cs index cb5852d16..5e20ad9f7 100644 --- a/Subsurface/Source/GUI/GUITextBlock.cs +++ b/Subsurface/Source/GUI/GUITextBlock.cs @@ -157,7 +157,7 @@ namespace Barotrauma SetTextPos(); - if (rect.Height == 0 && !string.IsNullOrWhiteSpace(Text)) + if (rect.Height == 0 && !string.IsNullOrEmpty(Text)) { this.rect.Height = (int)Font.MeasureString(wrappedText).Y; } diff --git a/Subsurface/Source/GameSession/GameSession.cs b/Subsurface/Source/GameSession/GameSession.cs index 356b69974..beb6e15eb 100644 --- a/Subsurface/Source/GameSession/GameSession.cs +++ b/Subsurface/Source/GameSession/GameSession.cs @@ -7,7 +7,7 @@ namespace Barotrauma { class GameSession { - public enum InfoFrameTab { Crew, Mission }; + public enum InfoFrameTab { Crew, Mission, ManagePlayers }; public readonly TaskManager TaskManager; @@ -244,6 +244,13 @@ namespace Barotrauma missionButton.UserData = InfoFrameTab.Mission; missionButton.OnClicked = SelectInfoFrameTab; + if (GameMain.Server != null) + { + var manageButton = new GUIButton(new Rectangle(200, -30, 130, 20), "Manage players", GUI.Style, infoFrame); + manageButton.UserData = InfoFrameTab.ManagePlayers; + manageButton.OnClicked = SelectInfoFrameTab; + } + var closeButton = new GUIButton(new Rectangle(0, 0, 80, 20), "Close", Alignment.BottomCenter, GUI.Style, infoFrame); closeButton.OnClicked = ToggleInfoFrame; @@ -262,6 +269,9 @@ namespace Barotrauma break; case InfoFrameTab.Mission: CreateMissionInfo(infoFrame); + break; + case InfoFrameTab.ManagePlayers: + GameMain.Server.ManagePlayersFrame(infoFrame); break; } @@ -283,7 +293,7 @@ namespace Barotrauma } - + public void Update(float deltaTime) { TaskManager.Update(deltaTime); diff --git a/Subsurface/Source/GameSession/InfoTextManager.cs b/Subsurface/Source/GameSession/InfoTextManager.cs index 78bca7b25..cd3a1167c 100644 --- a/Subsurface/Source/GameSession/InfoTextManager.cs +++ b/Subsurface/Source/GameSession/InfoTextManager.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.IO; using System.Linq; using System.Xml.Linq; @@ -51,6 +52,11 @@ namespace Barotrauma string text = infoList[Rand.Int(infoList.Count)]; + foreach (InputType inputType in Enum.GetValues(typeof(InputType))) + { + text = text.Replace("[" + inputType.ToString() + "]", GameMain.Config.KeyBind(inputType).ToString()); + } + if (Submarine.MainSub != null) text = text.Replace("[sub]", Submarine.MainSub.Name); if (GameMain.GameSession != null && GameMain.GameSession.Map != null) { diff --git a/Subsurface/Source/GameSettings.cs b/Subsurface/Source/GameSettings.cs index b965a7e8e..3a2caff9a 100644 --- a/Subsurface/Source/GameSettings.cs +++ b/Subsurface/Source/GameSettings.cs @@ -203,6 +203,16 @@ namespace Barotrauma } } + foreach (InputType inputType in Enum.GetValues(typeof(InputType))) + { + if (keyMapping[(int)inputType]==null) + { + DebugConsole.ThrowError("Key binding for the input type ''" + inputType + " not set!"); + keyMapping[(int)inputType] = new KeyOrMouse(Keys.D1); + } + } + + UnsavedSettings = false; } @@ -383,6 +393,7 @@ namespace Barotrauma { new GUITextBlock(new Rectangle(x, y, 100, 20), inputNames[i]+": ", GUI.Style, settingsFrame); var keyBox = new GUITextBox(new Rectangle(x + 100, y, 120, 15), GUI.Style, settingsFrame); + keyBox.Text = keyMapping[i].ToString(); keyBox.UserData = i; keyBox.OnSelected += KeyBoxSelected; diff --git a/Subsurface/Source/Items/Item.cs b/Subsurface/Source/Items/Item.cs index 161e6908e..de9e885c5 100644 --- a/Subsurface/Source/Items/Item.cs +++ b/Subsurface/Source/Items/Item.cs @@ -1,18 +1,18 @@ -using System.Collections.Generic; -using System.Linq; -using System.Xml.Linq; +using Barotrauma.Items.Components; +using Barotrauma.Networking; using FarseerPhysics; +using FarseerPhysics.Dynamics; +using FarseerPhysics.Dynamics.Contacts; using Lidgren.Network; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; -using Barotrauma.Networking; using System; -using Barotrauma.Items.Components; -using System.ComponentModel; +using System.Collections.Generic; using System.Collections.ObjectModel; -using FarseerPhysics.Dynamics; -using FarseerPhysics.Dynamics.Contacts; +using System.ComponentModel; +using System.Linq; +using System.Xml.Linq; namespace Barotrauma { @@ -648,7 +648,7 @@ namespace Barotrauma public AttackResult AddDamage(IDamageable attacker, Vector2 worldPosition, Attack attack, float deltaTime, bool playSound = true) { - float damageAmount = attack.GetDamage(deltaTime); + float damageAmount = attack.GetStructureDamage(deltaTime); Condition -= damageAmount; return new AttackResult(damageAmount, 0.0f, false); diff --git a/Subsurface/Source/Map/Levels/Level.cs b/Subsurface/Source/Map/Levels/Level.cs index 5f30db6fc..2fb7dbe02 100644 --- a/Subsurface/Source/Map/Levels/Level.cs +++ b/Subsurface/Source/Map/Levels/Level.cs @@ -203,11 +203,6 @@ namespace Barotrauma pathNodes.Add(new Vector2(x, Rand.Range(pathBorders.Y, pathBorders.Bottom, false))); } - for (int i = 2; i < pathNodes.Count; i+=3 ) - { - positionsOfInterest.Add(new InterestingPosition(pathNodes[i], PositionType.MainPath)); - } - pathNodes.Add(endPosition); pathNodes.Add(new Vector2(endPosition.X, borders.Height)); @@ -277,6 +272,12 @@ namespace Barotrauma List mainPath = CaveGenerator.GeneratePath(pathNodes, cells, cellGrid, GridCellSize, new Rectangle(pathBorders.X, pathBorders.Y, pathBorders.Width, borders.Height), 0.3f, mirror); + + for (int i = 2; i < mainPath.Count; i += 3) + { + positionsOfInterest.Add(new InterestingPosition(mainPath[i].Center, PositionType.MainPath)); + } + List pathCells = new List(mainPath); EnlargeMainPath(pathCells, minWidth); @@ -734,7 +735,7 @@ namespace Barotrauma return newCells; } - public Vector2 GetRandomItemPos(PositionType spawnPosType, float offsetFromWall = 10.0f) + public Vector2 GetRandomItemPos(PositionType spawnPosType, float randomSpread, float offsetFromWall = 10.0f) { if (!positionsOfInterest.Any()) return Size*0.5f; @@ -746,6 +747,8 @@ namespace Barotrauma do { Vector2 startPos = Level.Loaded.GetRandomInterestingPosition(true, spawnPosType); + + startPos += Rand.Vector(Rand.Range(0.0f, randomSpread, false), false); Vector2 endPos = startPos - Vector2.UnitY * Size.Y; diff --git a/Subsurface/Source/Map/Structure.cs b/Subsurface/Source/Map/Structure.cs index c9319aac4..1a855f010 100644 --- a/Subsurface/Source/Map/Structure.cs +++ b/Subsurface/Source/Map/Structure.cs @@ -104,6 +104,19 @@ namespace Barotrauma { get { return prefab.MaxHealth; } } + + public override Rectangle Rect + { + get + { + return base.Rect; + } + set + { + base.Rect = value; + if (prefab.HasBody) CreateSections(); + } + } public override void Move(Vector2 amount) { @@ -130,15 +143,6 @@ namespace Barotrauma { convexHulls.ForEach(x => x.Move(amount)); } - //if (gaps != null) - //{ - // foreach (Gap g in gaps) - // { - // g.Move(amount); - // //g.position.X += amount.X; - // //g.position.Y -= amount.Y; - // } - //} } public Structure(Rectangle rectangle, StructurePrefab sp, Submarine submarine) @@ -173,37 +177,8 @@ namespace Barotrauma bodies.Add(newBody); WallList.Add(this); - - int xsections = 1; - int ysections = 1; - int width, height; - if (isHorizontal) - { - xsections = (int)Math.Ceiling((float)rect.Width / wallSectionSize); - sections = new WallSection[xsections]; - width = (int)wallSectionSize; - height = rect.Height; - } - else - { - ysections = (int)Math.Ceiling((float)rect.Height / wallSectionSize); - sections = new WallSection[ysections]; - width = rect.Width; - height = (int)wallSectionSize; - } - - for (int x = 0; x < xsections; x++ ) - { - for (int y = 0; y < ysections; y++) - { - Rectangle sectionRect = new Rectangle(rect.X + x * width, rect.Y - y * height, width, height); - sectionRect.Width -= (int)Math.Max((sectionRect.X + sectionRect.Width) - (rect.X + rect.Width), 0.0f); - sectionRect.Height -= (int)Math.Max((rect.Y - rect.Height)-(sectionRect.Y - sectionRect.Height), 0.0f); - - sections[x+y] = new WallSection(sectionRect); - } - } + CreateSections(); } else { @@ -245,6 +220,39 @@ namespace Barotrauma InsertToList(); } + private void CreateSections() + { + int xsections = 1, ysections = 1; + int width, height; + + if (isHorizontal) + { + xsections = (int)Math.Ceiling((float)rect.Width / wallSectionSize); + sections = new WallSection[xsections]; + width = (int)wallSectionSize; + height = rect.Height; + } + else + { + ysections = (int)Math.Ceiling((float)rect.Height / wallSectionSize); + sections = new WallSection[ysections]; + width = rect.Width; + height = (int)wallSectionSize; + } + + for (int x = 0; x < xsections; x++) + { + for (int y = 0; y < ysections; y++) + { + Rectangle sectionRect = new Rectangle(rect.X + x * width, rect.Y - y * height, width, height); + sectionRect.Width -= (int)Math.Max((sectionRect.X + sectionRect.Width) - (rect.X + rect.Width), 0.0f); + sectionRect.Height -= (int)Math.Max((rect.Y - rect.Height) - (sectionRect.Y - sectionRect.Height), 0.0f); + + sections[x + y] = new WallSection(sectionRect); + } + } + } + private void GenerateConvexHull() { // If not null and not empty , remove the hulls from the system @@ -374,11 +382,14 @@ namespace Barotrauma } Vector2 drawOffset = Submarine == null ? Vector2.Zero : Submarine.DrawPosition; - prefab.sprite.DrawTiled(spriteBatch, new Vector2(rect.X + drawOffset.X, -(rect.Y + drawOffset.Y)), new Vector2(rect.Width, rect.Height), Vector2.Zero, color); - + if(sections.Length == 1) + prefab.sprite.DrawTiled(spriteBatch, new Vector2(rect.X + drawOffset.X, -(rect.Y + drawOffset.Y)), new Vector2(rect.Width, rect.Height), Vector2.Zero, color,Point.Zero); foreach (WallSection s in sections) { + Point offset = new Point(Math.Abs(rect.Location.X - s.rect.Location.X), Math.Abs(rect.Location.Y - s.rect.Location.Y)); + if (sections.Length != 1 && s.damage < prefab.MaxHealth) + prefab.sprite.DrawTiled(spriteBatch, new Vector2(s.rect.X + drawOffset.X, -(s.rect.Y + drawOffset.Y)), new Vector2(s.rect.Width, s.rect.Height), Vector2.Zero, color, offset); if (s.isHighLighted) { @@ -390,10 +401,10 @@ namespace Barotrauma s.isHighLighted = false; if (s.damage < 0.01f) continue; - - GUI.DrawRectangle(spriteBatch, + + GUI.DrawRectangle(spriteBatch, new Vector2(s.rect.X + drawOffset.X, -(s.rect.Y + drawOffset.Y)), new Vector2(s.rect.Width, s.rect.Height), - Color.Black * (s.damage / prefab.MaxHealth), true); + Color.Black * (s.damage / prefab.MaxHealth), true); } /* if(_convexHulls == null) return; @@ -592,8 +603,8 @@ namespace Barotrauma } } - if (sections[sectionIndex].gap != null) - sections[sectionIndex].gap.Open = (float)Math.Pow(((damage / prefab.MaxHealth)-0.5)*2.0, 2.0); + if (sections[sectionIndex].gap != null) + sections[sectionIndex].gap.Open = (damage/prefab.MaxHealth - 0.5f)*2; bool hadHole = SectionBodyDisabled(sectionIndex); sections[sectionIndex].damage = MathHelper.Clamp(damage, 0.0f, prefab.MaxHealth); diff --git a/Subsurface/Source/Networking/ChatMessage.cs b/Subsurface/Source/Networking/ChatMessage.cs index e6d0d63e9..f0031c6f8 100644 --- a/Subsurface/Source/Networking/ChatMessage.cs +++ b/Subsurface/Source/Networking/ChatMessage.cs @@ -115,21 +115,46 @@ namespace Barotrauma.Networking public void WriteNetworkMessage(NetOutgoingMessage msg) { - msg.WriteRangedInteger(0, Enum.GetValues(typeof(ChatMessageType)).Length, (byte)Type); - msg.Write(Sender == null ? (ushort)0 : Sender.ID); - msg.Write(SenderName); + msg.WriteRangedInteger(0, Enum.GetValues(typeof(ChatMessageType)).Length, (byte)Type); + if (GameMain.Server != null) + { + msg.Write(Sender == null ? (ushort)0 : Sender.ID); + msg.Write(SenderName); + } msg.Write(Text); } public static ChatMessage ReadNetworkMessage(NetBuffer msg) { - ChatMessageType type = (ChatMessageType)msg.ReadRangedInteger(0, Enum.GetValues(typeof(ChatMessageType)).Length); - ushort senderId = msg.ReadUInt16(); - string senderName = msg.ReadString(); + ChatMessageType type = (ChatMessageType)msg.ReadRangedInteger(0, Enum.GetValues(typeof(ChatMessageType)).Length); + string senderName=""; + Character character = null; + if (GameMain.Server == null) + { + ushort senderId = msg.ReadUInt16(); + character = Entity.FindEntityByID(senderId) as Character; + senderName = msg.ReadString(); + } + else + { + NetIncomingMessage inc = msg as NetIncomingMessage; + if (inc == null) return null; + Client sender = GameMain.Server.ConnectedClients.Find(x => x.Connection == inc.SenderConnection); + if (sender == null) return null; + character = sender.Character; + if (character != null) + { + senderName = character.Name; + } + else + { + senderName = sender.name; + } + } string text = msg.ReadString(); - return new ChatMessage(senderName, text, type, Entity.FindEntityByID(senderId) as Character); + return new ChatMessage(senderName, text, type, character); } } } diff --git a/Subsurface/Source/Networking/Client.cs b/Subsurface/Source/Networking/Client.cs index 1002fd918..41bdbac6d 100644 --- a/Subsurface/Source/Networking/Client.cs +++ b/Subsurface/Source/Networking/Client.cs @@ -29,6 +29,11 @@ namespace Barotrauma.Networking public string version; public bool inGame; + public List ChatMessages = new List(); + public float ChatSpamSpeed; + public float ChatSpamTimer; + public int ChatSpamCount; + private List kickVoters; public bool ReadyToStart; @@ -84,8 +89,21 @@ namespace Barotrauma.Networking { name = name.Substring(0, 20); } + string rName = ""; + for (int i=0;i 126) + { + //TODO: allow safe unicode characters, this is just to prevent players from taking names that look similar but aren't the same + rName += '?'; + } + else + { + rName += name[i]; + } + } - return name; + return rName; } public void SetPermissions(ClientPermissions permissions) @@ -105,7 +123,7 @@ namespace Barotrauma.Networking public bool HasPermission(ClientPermissions permission) { - return Permissions.HasFlag(permission); + return false; //Permissions.HasFlag(permission); } public T GetVote(VoteType voteType) diff --git a/Subsurface/Source/Networking/GameClient.cs b/Subsurface/Source/Networking/GameClient.cs index 7980625b0..7d8449fb9 100644 --- a/Subsurface/Source/Networking/GameClient.cs +++ b/Subsurface/Source/Networking/GameClient.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using FarseerPhysics; using System.IO; using System.Linq; +using System.Text; using Barotrauma.Items.Components; using System.ComponentModel; @@ -165,7 +166,12 @@ namespace Barotrauma.Networking reconnectBox.Buttons[0].OnClicked += reconnectBox.Close; } - CoroutineManager.StartCoroutine(WaitForStartingInfo(password)); + String sendPw = ""; + if (password.Length>0) + { + sendPw = Encoding.UTF8.GetString(NetUtility.ComputeSHAHash(Encoding.UTF8.GetBytes(password))); + } + CoroutineManager.StartCoroutine(WaitForStartingInfo(sendPw)); // Start the timer //update.Start(); @@ -408,43 +414,7 @@ namespace Barotrauma.Networking byte characterCount = inc.ReadByte(); for (int i = 0; i < characterCount; i++) { - bool isAiCharacter = inc.ReadBoolean(); - ushort id = inc.ReadUInt16(); - - if (isAiCharacter) - { - string configPath = inc.ReadString(); - - Vector2 position = new Vector2(inc.ReadFloat(), inc.ReadFloat()); - - var existingEntity = Entity.FindEntityByID(id); - if (existingEntity is AICharacter && existingEntity.ID == id) - { - continue; - } - - var character = Character.Create(configPath, position, null, true); - if (character != null) character.ID = id; - } - else - { - bool hasOwner = inc.ReadBoolean(); - int ownerId = -1; - if (hasOwner) - { - ownerId = inc.ReadByte(); - } - - Character newCharacter = ReadCharacterData(inc, ownerId == myID); - - if (ownerId != myID) - { - var characterOwner = otherClients.Find(c => c.ID == ownerId); - if (characterOwner != null) characterOwner.Character = newCharacter; - } - - crew.Add(newCharacter); - } + ReadCharacterData(inc); } gameStarted = true; @@ -509,7 +479,7 @@ namespace Barotrauma.Networking public bool HasPermission(ClientPermissions permission) { - return permissions.HasFlag(permission); + return false;// permissions.HasFlag(permission); } public override void Draw(Microsoft.Xna.Framework.Graphics.SpriteBatch spriteBatch) @@ -547,15 +517,23 @@ namespace Barotrauma.Networking GUI.DrawRectangle(spriteBatch, new Rectangle(x, y, width, height), Color.Black * 0.7f, true); spriteBatch.DrawString(GUI.Font, "Network statistics:", new Vector2(x + 10, y + 10), Color.White); - spriteBatch.DrawString(GUI.Font, "Ping: " + (int)(client.ServerConnection.AverageRoundtripTime * 1000.0f) + " ms", new Vector2(x + 10, y + 25), Color.White); + if (client.ServerConnection != null) + { + spriteBatch.DrawString(GUI.Font, "Ping: " + (int)(client.ServerConnection.AverageRoundtripTime * 1000.0f) + " ms", new Vector2(x + 10, y + 25), Color.White); - y += 15; + y += 15; - spriteBatch.DrawString(GUI.SmallFont, "Received bytes: " + client.Statistics.ReceivedBytes, new Vector2(x + 10, y + 45), Color.White); - spriteBatch.DrawString(GUI.SmallFont, "Received packets: " + client.Statistics.ReceivedPackets, new Vector2(x + 10, y + 60), Color.White); + spriteBatch.DrawString(GUI.SmallFont, "Received bytes: " + client.Statistics.ReceivedBytes, new Vector2(x + 10, y + 45), Color.White); + spriteBatch.DrawString(GUI.SmallFont, "Received packets: " + client.Statistics.ReceivedPackets, new Vector2(x + 10, y + 60), Color.White); + + spriteBatch.DrawString(GUI.SmallFont, "Sent bytes: " + client.Statistics.SentBytes, new Vector2(x + 10, y + 75), Color.White); + spriteBatch.DrawString(GUI.SmallFont, "Sent packets: " + client.Statistics.SentPackets, new Vector2(x + 10, y + 90), Color.White); + } + else + { + spriteBatch.DrawString(GUI.Font, "Disconnected", new Vector2(x + 10, y + 25), Color.White); + } - spriteBatch.DrawString(GUI.SmallFont, "Sent bytes: " + client.Statistics.SentBytes, new Vector2(x + 10, y + 75), Color.White); - spriteBatch.DrawString(GUI.SmallFont, "Sent packets: " + client.Statistics.SentPackets, new Vector2(x + 10, y + 90), Color.White); } @@ -609,25 +587,6 @@ namespace Barotrauma.Networking return true; } - public void ReadCharacterSpawnMessage(NetIncomingMessage message) - { - string configPath = message.ReadString(); - - if (configPath != Character.HumanConfigFile) - { - ushort id = message.ReadUInt16(); - - Vector2 position = new Vector2(message.ReadFloat(), message.ReadFloat()); - - var character = Character.Create(configPath, position, null, true); - if (character != null) character.ID = id; - } - else - { - ReadCharacterData(message, false, true); - } - } - public void RequestFile(string file, FileTransferMessageType fileType) { if (fileStreamReceiver!=null) @@ -812,35 +771,77 @@ namespace Barotrauma.Networking client.SendMessage(msg, NetDeliveryMethod.ReliableUnordered); } - public Character ReadCharacterData(NetIncomingMessage inc, bool isMyCharacter, bool hasAi = false) + public Character ReadCharacterData(NetIncomingMessage inc) { - string newName = inc.ReadString(); - ushort ID = inc.ReadUInt16(); - bool isFemale = inc.ReadBoolean(); + bool noInfo = inc.ReadBoolean(); + ushort id = inc.ReadUInt16(); + string configPath = inc.ReadString(); - int headSpriteID = inc.ReadByte(); - Vector2 position = new Vector2(inc.ReadFloat(), inc.ReadFloat()); + + bool enabled = inc.ReadBoolean(); - string jobName = inc.ReadString(); - JobPrefab jobPrefab = JobPrefab.List.Find(jp => jp.Name == jobName); + Character character = null; - CharacterInfo ch = new CharacterInfo(Character.HumanConfigFile, newName, isFemale ? Gender.Female : Gender.Male, jobPrefab); - ch.HeadSpriteId = headSpriteID; - - Character character = Character.Create(ch, position, !isMyCharacter, hasAi); - GameMain.GameSession.CrewManager.characters.Add(character); - - character.ID = ID; - - if (isMyCharacter) + if (noInfo) { - myCharacter = character; - Character.Controlled = character; - GameMain.LightManager.LosEnabled = true; + var existingEntity = Entity.FindEntityByID(id); + if (existingEntity is AICharacter && existingEntity.ID == id) + { + return (Character)existingEntity; + } - if (endVoteTickBox != null) endVoteTickBox.Visible = Voting.AllowEndVoting; + character = Character.Create(configPath, position, null, true); + character.ID = id; } + else + { + bool hasOwner = inc.ReadBoolean(); + int ownerId = -1; + if (hasOwner) + { + ownerId = inc.ReadByte(); + } + + string newName = inc.ReadString(); + + bool hasAi = inc.ReadBoolean(); + bool isFemale = inc.ReadBoolean(); + int headSpriteID = inc.ReadByte(); + string jobName = inc.ReadString(); + + JobPrefab jobPrefab = JobPrefab.List.Find(jp => jp.Name == jobName); + + CharacterInfo ch = new CharacterInfo(configPath, newName, isFemale ? Gender.Female : Gender.Male, jobPrefab); + ch.HeadSpriteId = headSpriteID; + + character = Character.Create(configPath, position, ch, ownerId != myID, hasAi); + character.ID = id; + + if (configPath == Character.HumanConfigFile) + { + GameMain.GameSession.CrewManager.characters.Add(character); + } + + Item.Spawner.ReadNetworkData(inc); + + if (ownerId == myID) + { + myCharacter = character; + Character.Controlled = character; + GameMain.LightManager.LosEnabled = true; + + if (endVoteTickBox != null) endVoteTickBox.Visible = Voting.AllowEndVoting; + } + else + { + var characterOwner = otherClients.Find(c => c.ID == ownerId); + if (characterOwner != null) characterOwner.Character = character; + + } + } + + character.Enabled = enabled; return character; } diff --git a/Subsurface/Source/Networking/GameServer.cs b/Subsurface/Source/Networking/GameServer.cs index ca88ac5c9..d96a1fc36 100644 --- a/Subsurface/Source/Networking/GameServer.cs +++ b/Subsurface/Source/Networking/GameServer.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; +using System.Text; using Lidgren.Network; using Microsoft.Xna.Framework; using RestSharp; @@ -54,7 +55,11 @@ namespace Barotrauma.Networking name = name.Replace(";", ""); this.name = name; - this.password = password; + this.password = ""; + if (password.Length>0) + { + this.password = Encoding.UTF8.GetString(NetUtility.ComputeSHAHash(Encoding.UTF8.GetBytes(password))); + } config = new NetPeerConfiguration("barotrauma"); @@ -104,6 +109,10 @@ namespace Barotrauma.Networking return true; }; + GUIButton settingsButton = new GUIButton(new Rectangle(GameMain.GraphicsWidth - 170 - 170 - 170, 20, 150, 20), "Settings", Alignment.TopLeft, GUI.Style, inGameHUD); + settingsButton.OnClicked = ToggleSettingsFrame; + settingsButton.UserData = "settingsButton"; + banList = new BanList(); LoadSettings(); @@ -342,7 +351,13 @@ namespace Barotrauma.Networking foreach (Client c in connectedClients) { - if (c.FileStreamSender != null) UpdateFileTransfer(c, deltaTime); + if (c.FileStreamSender != null) UpdateFileTransfer(c, deltaTime); + + c.ReliableChannel.Update(deltaTime); + + //slowly reset spam timers + c.ChatSpamTimer = Math.Max(0.0f, c.ChatSpamTimer - deltaTime); + c.ChatSpamSpeed = Math.Max(0.0f, c.ChatSpamSpeed - deltaTime); } NetIncomingMessage inc = null; @@ -974,35 +989,7 @@ namespace Barotrauma.Networking msg.Write((byte)characters.Count); foreach (Character c in characters) { - msg.Write(c is AICharacter); - msg.Write(c.ID); - - if (c is AICharacter) - { - msg.Write(c.ConfigPath); - - msg.Write(c.Position.X); - msg.Write(c.Position.Y); - } - else - { - Client client = connectedClients.Find(cl => cl.Character == c); - if (client != null) - { - msg.Write(true); - msg.Write(client.ID); - } - else if (myCharacter == c) - { - msg.Write(true); - msg.Write((byte)0); - } - else - { - msg.Write(false); - } - WriteCharacterData(msg, c.Name, c); - } + WriteCharacterData(msg, c.Name, c); } return msg; @@ -1435,12 +1422,15 @@ namespace Barotrauma.Networking private void ReadChatMessage(NetIncomingMessage inc) { + Client sender = connectedClients.Find(x => x.Connection == inc.SenderConnection); ChatMessage message = ChatMessage.ReadNetworkMessage(inc); + if (message == null) return; List recipients = new List(); foreach (Client c in connectedClients) { + if (!sender.inGame && c.inGame) continue; //people in lobby can't talk to people ingame switch (message.Type) { case ChatMessageType.Dead: @@ -1462,7 +1452,71 @@ namespace Barotrauma.Networking recipients.Add(c); } - AddChatMessage(message); + //SPAM FILTER + if (sender.ChatSpamTimer > 0.0f) + { + //player has already been spamming, stop again + ChatMessage denyMsg = ChatMessage.Create("", "You have been blocked by the spam filter. Try again after 10 seconds.", ChatMessageType.Server, null); + sender.ChatSpamTimer = 10.0f; + SendChatMessage(denyMsg, sender); + + return; + } + + float similarity = 0; + similarity += sender.ChatSpamSpeed * 0.05f; //the faster messages are being sent, the faster the filter will block + for (int i = 0; i < sender.ChatMessages.Count; i++) + { + float closeFactor = 1.0f / (20.0f - i); + + int levenshteinDist = ToolBox.LevenshteinDistance(message.Text, sender.ChatMessages[i]); + similarity += Math.Max((message.Text.Length - levenshteinDist) / message.Text.Length * closeFactor, 0.0f); + } + + if (similarity > 5.0f) + { + sender.ChatSpamCount++; + + if (sender.ChatSpamCount > 3) + { + //kick for spamming too much + KickClient(sender, false); + } + else + { + ChatMessage denyMsg = ChatMessage.Create("", "You have been blocked by the spam filter. Try again after 10 seconds.", ChatMessageType.Server, null); + sender.ChatSpamTimer = 10.0f; + SendChatMessage(denyMsg, sender); + } + return; + } + + sender.ChatMessages.Add(message.Text); + if (sender.ChatMessages.Count > 20) + { + sender.ChatMessages.RemoveAt(0); + } + + if (sender.inGame || (Screen.Selected == GameMain.NetLobbyScreen)) + { + AddChatMessage(message); + } + else + { + GameServer.Log(message.TextWithSender, message.Color); + } + sender.ChatSpamSpeed += 5.0f; + + foreach (Client c in recipients) + { + ReliableMessage msg = c.ReliableChannel.CreateMessage(); + msg.InnerMessage.Write((byte)PacketTypes.Chatmessage); + + message.WriteNetworkMessage(msg.InnerMessage); + + c.ReliableChannel.SendMessage(msg, c.Connection); + } + } public override void SendChatMessage(string message, ChatMessageType? type = null) @@ -1521,6 +1575,16 @@ namespace Barotrauma.Networking SendChatMessage(chatMessage, recipients); } + public void SendChatMessage(ChatMessage chatMessage, Client recipient) + { + ReliableMessage msg = recipient.ReliableChannel.CreateMessage(); + msg.InnerMessage.Write((byte)PacketTypes.Chatmessage); + + chatMessage.WriteNetworkMessage(msg.InnerMessage); + + recipient.ReliableChannel.SendMessage(msg, recipient.Connection); + } + public void SendChatMessage(ChatMessage chatMessage, List recipients) { @@ -1528,6 +1592,9 @@ namespace Barotrauma.Networking private void ReadCharacterData(NetIncomingMessage message) { + Client sender = connectedClients.Find(c => c.Connection == message.SenderConnection); + if (sender == null) return; + string name = ""; Gender gender = Gender.Male; int headSpriteId = 0; @@ -1545,6 +1612,11 @@ namespace Barotrauma.Networking headSpriteId = 0; } + if (sender.characterInfo != null) + { + //clients can't change their character's name once it's been set + name = sender.characterInfo.Name; + } List jobPreferences = new List(); int count = message.ReadByte(); @@ -1555,51 +1627,60 @@ namespace Barotrauma.Networking if (jobPrefab != null) jobPreferences.Add(jobPrefab); } - foreach (Client c in connectedClients) - { - if (c.Connection != message.SenderConnection) continue; - - c.characterInfo = new CharacterInfo(Character.HumanConfigFile, name, gender); - c.characterInfo.HeadSpriteId = headSpriteId; - c.jobPreferences = jobPreferences; - break; - } + sender.characterInfo = new CharacterInfo(Character.HumanConfigFile, name, gender); + sender.characterInfo.HeadSpriteId = headSpriteId; + sender.jobPreferences = jobPreferences; } - public void WriteCharacterData(NetOutgoingMessage message, string name, Character character) + public void WriteCharacterData(NetOutgoingMessage msg, string name, Character c) { - message.Write(name); - message.Write(character.ID); - message.Write(character.Info.Gender == Gender.Female); + msg.Write(c.Info == null); + msg.Write(c.ID); + msg.Write(c.ConfigPath); - message.Write((byte)character.Info.HeadSpriteId); + msg.Write(c.WorldPosition.X); + msg.Write(c.WorldPosition.Y); - message.Write(character.WorldPosition.X); - message.Write(character.WorldPosition.Y); - - message.Write(character.Info.Job.Name); + msg.Write(c.Enabled); + + if (c.Info != null) + { + Client client = connectedClients.Find(cl => cl.Character == c); + if (client != null) + { + msg.Write(true); + msg.Write(client.ID); + } + else if (myCharacter == c) + { + msg.Write(true); + msg.Write((byte)0); + } + else + { + msg.Write(false); + } + + msg.Write(name); + + msg.Write(c is AICharacter); + msg.Write(c.Info.Gender == Gender.Female); + msg.Write((byte)c.Info.HeadSpriteId); + msg.Write(c.Info.Job == null ? "" : c.Info.Job.Name); + Item.Spawner.FillNetworkData(msg, c.SpawnItems); + } } public void SendCharacterSpawnMessage(Character character, List recipients = null) { + if (recipients != null && !recipients.Any()) return; + NetOutgoingMessage message = server.CreateMessage(); message.Write((byte)PacketTypes.NewCharacter); - message.Write(character.ConfigPath); - - if (character.ConfigPath == Character.HumanConfigFile) - { - WriteCharacterData(message, character.Name, character); - } - else - { - message.Write(character.ID); - - message.Write(character.Position.X); - message.Write(character.Position.Y); - } - + WriteCharacterData(message, character.Name, character); + SendMessage(message, NetDeliveryMethod.ReliableUnordered, recipients); } diff --git a/Subsurface/Source/Networking/GameServerLogin.cs b/Subsurface/Source/Networking/GameServerLogin.cs index 8305d883a..8ede07b02 100644 --- a/Subsurface/Source/Networking/GameServerLogin.cs +++ b/Subsurface/Source/Networking/GameServerLogin.cs @@ -61,11 +61,14 @@ namespace Barotrauma.Networking { unauthenticatedClients.Remove(unauthenticatedClient); - NetEncryption algo = new NetXtea(server, password); + string saltedPw = password; + saltedPw = saltedPw + Convert.ToString(unauthenticatedClient.Nonce); + saltedPw = Encoding.UTF8.GetString(NetUtility.ComputeSHAHash(Encoding.UTF8.GetBytes(saltedPw))); + NetEncryption algo = new NetXtea(server, saltedPw); inc.Decrypt(algo); - int nonce = inc.ReadInt32(); - if (nonce != unauthenticatedClient.Nonce) + string rdPw = inc.ReadString(); + if (rdPw != saltedPw) { inc.SenderConnection.Disconnect("Wrong password!"); return; @@ -74,6 +77,13 @@ namespace Barotrauma.Networking else { inc.SenderConnection.Disconnect("Authentication failed"); + return; + } + + if (ConnectedClients.Count>=config.MaximumConnections) + { + inc.SenderConnection.Disconnect("Server full"); + return; } DebugConsole.NewMessage("New player has joined the server", Color.White); diff --git a/Subsurface/Source/Networking/GameServerSettings.cs b/Subsurface/Source/Networking/GameServerSettings.cs index ad6ce7df7..fe6161671 100644 --- a/Subsurface/Source/Networking/GameServerSettings.cs +++ b/Subsurface/Source/Networking/GameServerSettings.cs @@ -646,5 +646,38 @@ namespace Barotrauma.Networking return false; } + + public void ManagePlayersFrame(GUIFrame infoFrame) + { + GUIListBox cList = new GUIListBox(new Rectangle(0, 0, 0, 300), Color.White * 0.7f, GUI.Style, infoFrame); + cList.Padding = new Vector4(10.0f, 10.0f, 10.0f, 10.0f); + //crewList.OnSelected = SelectCrewCharacter; + + foreach (Client c in ConnectedClients) + { + GUIFrame frame = new GUIFrame(new Rectangle(0, 0, 0, 40), Color.Transparent, null, cList); + frame.Padding = new Vector4(5.0f, 5.0f, 5.0f, 5.0f); + frame.Color = (c.inGame && c.Character!=null && !c.Character.IsDead) ? Color.Gold * 0.2f : Color.Transparent; + frame.HoverColor = Color.LightGray * 0.5f; + frame.SelectedColor = Color.Gold * 0.5f; + + GUITextBlock textBlock = new GUITextBlock( + new Rectangle(40, 0, 0, 25), + c.name + " (" + c.Connection.RemoteEndPoint.Address.ToString() + ")", + Color.Transparent, Color.White, + Alignment.Left, Alignment.Left, + null, frame); + + var banButton = new GUIButton(new Rectangle(-120, 0, 100, 20), "Ban", Alignment.Right | Alignment.CenterY, GUI.Style, frame); + banButton.UserData = c.name; + banButton.OnClicked += GameMain.NetLobbyScreen.BanPlayer; + + var kickButton = new GUIButton(new Rectangle(0, 0, 100, 20), "Kick", Alignment.Right | Alignment.CenterY, GUI.Style, frame); + kickButton.UserData = c.name; + kickButton.OnClicked += GameMain.NetLobbyScreen.KickPlayer; + + textBlock.Padding = new Vector4(5.0f, 0.0f, 5.0f, 0.0f); + } + } } } diff --git a/Subsurface/Source/Networking/NetworkMember.cs b/Subsurface/Source/Networking/NetworkMember.cs index 9b6ac1dad..d18587249 100644 --- a/Subsurface/Source/Networking/NetworkMember.cs +++ b/Subsurface/Source/Networking/NetworkMember.cs @@ -264,6 +264,7 @@ namespace Barotrauma.Networking public void AddChatMessage(ChatMessage message) { + if (message.Type == ChatMessageType.Radio && Character.Controlled != null && message.Sender != null && message.Sender != myCharacter) @@ -278,6 +279,8 @@ namespace Barotrauma.Networking return; } + GameServer.Log(message.TextWithSender, message.Color); + string displayedText = message.Text; if (message.Sender != null) @@ -293,8 +296,6 @@ namespace Barotrauma.Networking GameMain.NetLobbyScreen.NewChatMessage(message); - GameServer.Log(message.Text, message.Color); - while (chatBox.CountChildren > 20) { chatBox.RemoveChild(chatBox.children[1]); @@ -304,11 +305,12 @@ namespace Barotrauma.Networking { displayedText = message.SenderName + ": " + displayedText; } - + GUITextBlock msg = new GUITextBlock(new Rectangle(0, 0, 0, 20), displayedText, ((chatBox.CountChildren % 2) == 0) ? Color.Transparent : Color.Black * 0.1f, message.Color, Alignment.Left, null, null, true); msg.Font = GUI.SmallFont; + msg.UserData = message.SenderName; msg.Padding = new Vector4(20.0f, 0, 0, 0); @@ -340,15 +342,12 @@ namespace Barotrauma.Networking { if (gameStarted && Screen.Selected == GameMain.GameScreen) { - chatMsgBox.Visible = Character.Controlled == null || - (!Character.Controlled.IsUnconscious && Character.Controlled.Stun <= 0.0f); + chatMsgBox.Visible = Character.Controlled == null || Character.Controlled.CanSpeak; inGameHUD.Update(deltaTime); GameMain.GameSession.CrewManager.Update(deltaTime); - - //if (crewFrameOpen) crewFrame.Update(deltaTime); - + if (Character.Controlled == null || Character.Controlled.IsDead) { GameMain.GameScreen.Cam.TargetPos = Vector2.Zero; diff --git a/Subsurface/Source/Networking/RespawnManager.cs b/Subsurface/Source/Networking/RespawnManager.cs index df89056fb..3940e64a3 100644 --- a/Subsurface/Source/Networking/RespawnManager.cs +++ b/Subsurface/Source/Networking/RespawnManager.cs @@ -532,7 +532,7 @@ namespace Barotrauma.Networking { byte clientId = inc.ReadByte(); - var character = client.ReadCharacterData(inc, clientId == client.ID); + var character = client.ReadCharacterData(inc); } if (state != newState) diff --git a/Subsurface/Source/Networking/ServerLog.cs b/Subsurface/Source/Networking/ServerLog.cs index a4b3858a8..ecdc5b2d4 100644 --- a/Subsurface/Source/Networking/ServerLog.cs +++ b/Subsurface/Source/Networking/ServerLog.cs @@ -98,10 +98,10 @@ namespace Barotrauma.Networking { float prevSize = listBox.BarSize; - var textBlock = new GUITextBlock(new Rectangle(0, 0, 0, 0), line.Text, GUI.Style, Alignment.TopLeft, Alignment.TopLeft, null, true, GUI.SmallFont); + var textBlock = new GUITextBlock(new Rectangle(0, 0, 0, 0), line.Text, GUI.Style, Alignment.TopLeft, Alignment.TopLeft, listBox, true, GUI.SmallFont); textBlock.Rect = new Rectangle(textBlock.Rect.X, textBlock.Rect.Y, textBlock.Rect.Width, Math.Max(13, textBlock.Rect.Height)); - listBox.AddChild(textBlock); + //listBox.AddChild(textBlock); textBlock.TextColor = line.Color; textBlock.CanBeFocused = false; diff --git a/Subsurface/Source/PlayerInput.cs b/Subsurface/Source/PlayerInput.cs index 8ce5e59c0..99d54c936 100644 --- a/Subsurface/Source/PlayerInput.cs +++ b/Subsurface/Source/PlayerInput.cs @@ -10,6 +10,7 @@ namespace Barotrauma Use, Aim, Up, Down, Left, Right, + Attack, Run, Crouch, Chat, CrewOrders } diff --git a/Subsurface/Source/Screens/NetLobbyScreen.cs b/Subsurface/Source/Screens/NetLobbyScreen.cs index aa205bf1c..309306e04 100644 --- a/Subsurface/Source/Screens/NetLobbyScreen.cs +++ b/Subsurface/Source/Screens/NetLobbyScreen.cs @@ -989,6 +989,7 @@ namespace Barotrauma ((chatBox.CountChildren % 2) == 0) ? Color.Transparent : Color.Black*0.1f, message.Color, Alignment.Left, GUI.Style, null, true); msg.Font = GUI.SmallFont; + msg.UserData = message.SenderName; msg.CanBeFocused = false; msg.Padding = new Vector4(20, 0, 0, 0); diff --git a/Subsurface/Source/Sprite.cs b/Subsurface/Source/Sprite.cs index 7ef5f62d8..e7e6bc4a2 100644 --- a/Subsurface/Source/Sprite.cs +++ b/Subsurface/Source/Sprite.cs @@ -222,7 +222,56 @@ namespace Barotrauma { DrawTiled(spriteBatch, pos, targetSize, Vector2.Zero, color); } + public void DrawTiled(SpriteBatch spriteBatch, Vector2 pos, Vector2 targetSize, Vector2 startOffset, Color color, Point offset) + { + //how many times the texture needs to be drawn on the x-axis + int xTiles = (int)Math.Ceiling((targetSize.X + startOffset.X) / sourceRect.Width); + //how many times the texture needs to be drawn on the y-axis + int yTiles = (int)Math.Ceiling((targetSize.Y + startOffset.Y) / sourceRect.Height); + + Rectangle TexPerspective = sourceRect; + + TexPerspective.Location += offset; + while (TexPerspective.Location.X >= sourceRect.X + sourceRect.Width) + TexPerspective.X = sourceRect.X + (TexPerspective.Location.X - (sourceRect.X + sourceRect.Width)); + while (TexPerspective.Location.Y >= sourceRect.Y + sourceRect.Height) + TexPerspective.Y = sourceRect.Y + (TexPerspective.Location.Y - (sourceRect.Y + sourceRect.Height)); + TexPerspective.Width = (int)Math.Min(targetSize.X, sourceRect.Width); + TexPerspective.Height = (int)Math.Min(targetSize.Y, sourceRect.Height); + for (int y = 0; y < yTiles; y++) + { + TexPerspective.Width = (int)Math.Min(targetSize.X, sourceRect.Width); + TexPerspective.Height = (int)Math.Min(targetSize.Y, sourceRect.Height); + float top = pos.Y + TexPerspective.Height * y; + for (int x = 0; x < xTiles; x++) + { + float left = pos.X + TexPerspective.Width * x; + TexPerspective.Width = Math.Min((int)(targetSize.X - TexPerspective.Width * x), TexPerspective.Width); + TexPerspective.Height = Math.Min((int)(targetSize.Y - TexPerspective.Height * y), TexPerspective.Height); + var movementX = TexPerspective.Width; + var movementY = TexPerspective.Height; + if (TexPerspective.X+TexPerspective.Width > sourceRect.X + sourceRect.Width) + { + float diff = (TexPerspective.X + TexPerspective.Width) - (sourceRect.X + sourceRect.Width); + TexPerspective.Width -= (int)diff; + spriteBatch.Draw(texture, new Vector2(left+ TexPerspective.Width, top), new Rectangle(sourceRect.X, TexPerspective.Y,(int)diff, TexPerspective.Height), color, rotation, Vector2.Zero, 1.0f, effects, depth); + } + else if (TexPerspective.Y + TexPerspective.Height > sourceRect.Y + sourceRect.Height) + { + float diff = (TexPerspective.Y + TexPerspective.Height) - (sourceRect.Y + sourceRect.Height); + TexPerspective.Height -= (int)diff; + spriteBatch.Draw(texture, new Vector2(left, top+ TexPerspective.Height), new Rectangle(TexPerspective.X, sourceRect.Y, TexPerspective.Width, (int)diff), color, rotation, Vector2.Zero, 1.0f, effects, depth); + } + + spriteBatch.Draw(texture, new Vector2(left,top),TexPerspective, color, rotation, Vector2.Zero, 1.0f, effects, depth); + if (TexPerspective.X+ movementX >= sourceRect.X + sourceRect.Width) + TexPerspective.X = sourceRect.X; + if (TexPerspective.Y + movementY >= sourceRect.Y + sourceRect.Height) + TexPerspective.Y = sourceRect.Y; + } + } + } public void DrawTiled(SpriteBatch spriteBatch, Vector2 pos, Vector2 targetSize, Vector2 startOffset, Color color) { //pos.X = (int)pos.X; diff --git a/Subsurface/Source/Utils/ToolBox.cs b/Subsurface/Source/Utils/ToolBox.cs index c13b97ad3..3370e8e84 100644 --- a/Subsurface/Source/Utils/ToolBox.cs +++ b/Subsurface/Source/Utils/ToolBox.cs @@ -365,6 +365,35 @@ namespace Barotrauma return inputType; } + + /// + /// Calculates the minimum number of single-character edits (i.e. insertions, deletions or substitutions) required to change one string into the other + /// + public static int LevenshteinDistance(string s, string t) + { + int n = s.Length; + int m = t.Length; + int[,] d = new int[n + 1, m + 1]; + + if (n == 0 || m == 0) return 0; + + for (int i = 0; i <= n; d[i, 0] = i++); + for (int j = 0; j <= m; d[0, j] = j++); + + for (int i = 1; i <= n; i++) + { + for (int j = 1; j <= m; j++) + { + int cost = (t[j - 1] == s[i - 1]) ? 0 : 1; + + d[i, j] = Math.Min( + Math.Min(d[i - 1, j] + 1, d[i, j - 1] + 1), + d[i - 1, j - 1] + cost); + } + } + + return d[n, m]; + } public static string WrapText(string text, float lineLength, SpriteFont font) { diff --git a/Subsurface/Submarines/Aegir Mark III.sub b/Subsurface/Submarines/Aegir Mark III.sub index 1bd371c82..2d0af9d3e 100644 Binary files a/Subsurface/Submarines/Aegir Mark III.sub and b/Subsurface/Submarines/Aegir Mark III.sub differ diff --git a/Subsurface/Submarines/Nehalennia.sub b/Subsurface/Submarines/Nehalennia.sub index 5eff334a3..2f0998ed3 100644 Binary files a/Subsurface/Submarines/Nehalennia.sub and b/Subsurface/Submarines/Nehalennia.sub differ diff --git a/Subsurface/Submarines/Vellamo.sub b/Subsurface/Submarines/Vellamo.sub index 41789877e..210ca0dfe 100644 Binary files a/Subsurface/Submarines/Vellamo.sub and b/Subsurface/Submarines/Vellamo.sub differ diff --git a/Subsurface/changelog.txt b/Subsurface/changelog.txt index 7ed628057..261fa063d 100644 --- a/Subsurface/changelog.txt +++ b/Subsurface/changelog.txt @@ -1,3 +1,31 @@ +--------------------------------------------------------------------------------------------------------- +v0.5.1.1 +--------------------------------------------------------------------------------------------------------- + +- fixed non-password protected servers being impossible to join to +- some more security checks + +--------------------------------------------------------------------------------------------------------- +v0.5.1.0 +--------------------------------------------------------------------------------------------------------- + +- getting attacked by a husk will slowly turn the victim into a husk + +- spam filter +- added server options to the ingame HUD +- fixed tiger thresher spawning on Linux +- a more secure password authentication method (again) +- ingame players can't receive messages from lobby players anymore +- more server-side security checks + +- medical doctors always have a high enough medical skill to fabricate any drug +- ai-controlled crew can be spawned using the console in multiplayer +- it's possible to manually attack when controlling a creature +- randomly spawned artifacts are spread out better throughout the level +- characters won't let go of a person they're dragging when entering/exiting the sub +- respawned players get the same ID card tags they would've gotten if they had spawned inside the main sub +- highlighted characters glow in the dark + --------------------------------------------------------------------------------------------------------- v0.5.0.3 --------------------------------------------------------------------------------------------------------- diff --git a/Subsurface/config.xml b/Subsurface/config.xml index 12baf166c..32c3373d6 100644 --- a/Subsurface/config.xml +++ b/Subsurface/config.xml @@ -2,5 +2,5 @@ - + \ No newline at end of file