Merge branch 'dedicated-server' (TODO: make sure I didn't break anything)

Conflicts:
	Barotrauma/Barotrauma.csproj
	Barotrauma/BarotraumaShared/Source/Characters/AI/AIController.cs
	Barotrauma/BarotraumaShared/Source/Characters/AI/EnemyAIController.cs
	Barotrauma/BarotraumaShared/Source/Characters/AICharacter.cs
	Barotrauma/BarotraumaShared/Source/Characters/Animation/Ragdoll.cs
	Barotrauma/BarotraumaShared/Source/Characters/Attack.cs
	Barotrauma/BarotraumaShared/Source/Characters/Character.cs
	Barotrauma/BarotraumaShared/Source/Characters/CharacterNetworking.cs
	Barotrauma/BarotraumaShared/Source/Characters/Limb.cs
	Barotrauma/BarotraumaShared/Source/Events/MonsterEvent.cs
	Barotrauma/BarotraumaShared/Source/Map/Explosion.cs
This commit is contained in:
Joonas Rikkonen
2017-06-30 21:02:52 +03:00
1311 changed files with 22015 additions and 91216 deletions

1
.gitignore vendored
View File

@@ -16,4 +16,3 @@ bld/
#performance reports & sessions
*.vsp
*.psess
/packages/MonoGame.Framework.WindowsDX.3.4.0.459/lib/net40

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,305 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{008C0F83-E914-4966-9135-EA885059EDD8}</ProjectGuid>
<OutputType>WinExe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Barotrauma</RootNamespace>
<AssemblyName>Barotrauma</AssemblyName>
<FileAlignment>512</FileAlignment>
<IsWebBootstrapper>false</IsWebBootstrapper>
<PublishUrl>publish\</PublishUrl>
<Install>true</Install>
<InstallFrom>Disk</InstallFrom>
<UpdateEnabled>false</UpdateEnabled>
<UpdateMode>Foreground</UpdateMode>
<UpdateInterval>7</UpdateInterval>
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
<UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>0.1.0.%2a</ApplicationVersion>
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<PlatformTarget>x86</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>..\bin\Windows\Debug\</OutputPath>
<DefineConstants>TRACE;DEBUG;WINDOWS;CLIENT</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<PlatformTarget>x86</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>..\bin\Windows\Release\</OutputPath>
<DefineConstants>TRACE;WINDOWS;CLIENT</DefineConstants>
<AllowedReferenceRelatedFileExtensions>
<!-- Prevent default XML and PDB files copied to output in RELEASE.
Only *.allowedextension files will be included, which doesn't exist in my case.
-->
.allowedextension
</AllowedReferenceRelatedFileExtensions>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup>
<ApplicationIcon>..\BarotraumaShared\Icon.ico</ApplicationIcon>
</PropertyGroup>
<ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Source\Camera.cs" />
<Compile Include="Source\Characters\AICharacter.cs" />
<Compile Include="Source\Characters\AI\AIController.cs" />
<Compile Include="Source\Characters\AI\AITarget.cs" />
<Compile Include="Source\Characters\AI\CrewCommander.cs" />
<Compile Include="Source\Characters\AI\EnemyAIController.cs" />
<Compile Include="Source\Characters\AI\HumanAIController.cs" />
<Compile Include="Source\Characters\Animation\Ragdoll.cs" />
<Compile Include="Source\Characters\Attack.cs" />
<Compile Include="Source\Characters\BackgroundSprite\BackgroundCreature.cs" />
<Compile Include="Source\Characters\BackgroundSprite\BackgroundCreatureManager.cs" />
<Compile Include="Source\Characters\BackgroundSprite\BackgroundCreaturePrefab.cs" />
<Compile Include="Source\Characters\BackgroundSprite\BackgroundSpriteManager.cs" />
<Compile Include="Source\Characters\BackgroundSprite\BackgroundSpritePrefab.cs" />
<Compile Include="Source\Characters\Character.cs" />
<Compile Include="Source\Characters\CharacterHUD.cs" />
<Compile Include="Source\Characters\CharacterInfo.cs" />
<Compile Include="Source\Characters\CharacterNetworking.cs" />
<Compile Include="Source\Characters\CharacterSound.cs" />
<Compile Include="Source\Characters\HUDProgressBar.cs" />
<Compile Include="Source\Characters\HuskInfection.cs" />
<Compile Include="Source\Characters\Jobs\JobPrefab.cs" />
<Compile Include="Source\Characters\Limb.cs" />
<Compile Include="Source\DebugConsole.cs" />
<Compile Include="Source\EventInput\EventInput.cs" />
<Compile Include="Source\EventInput\KeyboardDispatcher.cs" />
<Compile Include="Source\Events\Missions\Mission.cs" />
<Compile Include="Source\Events\Missions\MissionMode.cs" />
<Compile Include="Source\Fonts\ScalableFont.cs" />
<Compile Include="Source\GameMain.cs" />
<Compile Include="Source\GameSession\CrewManager.cs" />
<Compile Include="Source\GameSession\GameMode.cs" />
<Compile Include="Source\GameSession\GameModes\SinglePlayerMode.cs" />
<Compile Include="Source\GameSession\GameModes\TraitorManager.cs" />
<Compile Include="Source\GameSession\GameModes\Tutorials\BasicTutorial.cs" />
<Compile Include="Source\GameSession\GameModes\Tutorials\EditorTutorial.cs" />
<Compile Include="Source\GameSession\GameModes\Tutorials\TutorialMode.cs" />
<Compile Include="Source\GameSession\GameModes\Tutorials\TutorialType.cs" />
<Compile Include="Source\GameSession\GameSession.cs" />
<Compile Include="Source\GameSession\HireManager.cs" />
<Compile Include="Source\GameSession\ShiftSummary.cs" />
<Compile Include="Source\GameSettings.cs" />
<Compile Include="Source\GUI\ComponentStyle.cs" />
<Compile Include="Source\GUI\GUI.cs" />
<Compile Include="Source\GUI\GUIButton.cs" />
<Compile Include="Source\GUI\GUIComponent.cs" />
<Compile Include="Source\GUI\GUIDropDown.cs" />
<Compile Include="Source\GUI\GUIFrame.cs" />
<Compile Include="Source\GUI\GUIImage.cs" />
<Compile Include="Source\GUI\GUIListBox.cs" />
<Compile Include="Source\GUI\GUIMessage.cs" />
<Compile Include="Source\GUI\GUIMessageBox.cs" />
<Compile Include="Source\GUI\GUIProgressBar.cs" />
<Compile Include="Source\GUI\GUIScrollBar.cs" />
<Compile Include="Source\GUI\GUIStyle.cs" />
<Compile Include="Source\GUI\GUITextBlock.cs" />
<Compile Include="Source\GUI\GUITextBox.cs" />
<Compile Include="Source\GUI\GUITickBox.cs" />
<Compile Include="Source\GUI\LoadingScreen.cs" />
<Compile Include="Source\Items\CharacterInventory.cs" />
<Compile Include="Source\Items\Components\Door.cs" />
<Compile Include="Source\Items\Components\ItemComponent.cs" />
<Compile Include="Source\Items\Components\ItemContainer.cs" />
<Compile Include="Source\Items\Components\ItemLabel.cs" />
<Compile Include="Source\Items\Components\LightComponent.cs" />
<Compile Include="Source\Items\Components\Machines\Deconstructor.cs" />
<Compile Include="Source\Items\Components\Machines\Engine.cs" />
<Compile Include="Source\Items\Components\Machines\Fabricator.cs" />
<Compile Include="Source\Items\Components\Machines\MiniMap.cs" />
<Compile Include="Source\Items\Components\Machines\Pump.cs" />
<Compile Include="Source\Items\Components\Machines\Radar.cs" />
<Compile Include="Source\Items\Components\Machines\Reactor.cs" />
<Compile Include="Source\Items\Components\Machines\Steering.cs" />
<Compile Include="Source\Items\Components\Power\PowerContainer.cs" />
<Compile Include="Source\Items\Components\Power\Powered.cs" />
<Compile Include="Source\Items\Components\Power\PowerTransfer.cs" />
<Compile Include="Source\Items\Components\Signal\Connection.cs" />
<Compile Include="Source\Items\Components\Signal\ConnectionPanel.cs" />
<Compile Include="Source\Items\Components\Signal\Wire.cs" />
<Compile Include="Source\Items\Components\StatusHUD.cs" />
<Compile Include="Source\Items\Components\Turret.cs" />
<Compile Include="Source\Items\DockingPort.cs" />
<Compile Include="Source\Items\FixRequirement.cs" />
<Compile Include="Source\Items\Inventory.cs" />
<Compile Include="Source\Items\Item.cs" />
<Compile Include="Source\Items\ItemPrefab.cs" />
<Compile Include="Source\Items\Rope.cs" />
<Compile Include="Source\Map\Explosion.cs" />
<Compile Include="Source\Map\FireSource.cs" />
<Compile Include="Source\Map\Gap.cs" />
<Compile Include="Source\Map\Hull.cs" />
<Compile Include="Source\Map\Levels\CaveGenerator.cs" />
<Compile Include="Source\Map\Levels\Level.cs" />
<Compile Include="Source\Map\Levels\LevelRenderer.cs" />
<Compile Include="Source\Map\Levels\Ruins\RuinGenerator.cs" />
<Compile Include="Source\Map\Levels\WaterRenderer.cs" />
<Compile Include="Source\Map\Levels\WrappingWall.cs" />
<Compile Include="Source\Map\Lights\ConvexHull.cs" />
<Compile Include="Source\Map\Lights\LightManager.cs" />
<Compile Include="Source\Map\Lights\LightSource.cs" />
<Compile Include="Source\Map\LinkedSubmarine.cs" />
<Compile Include="Source\Map\Map\Location.cs" />
<Compile Include="Source\Map\Map.cs" />
<Compile Include="Source\Map\MapEntity.cs" />
<Compile Include="Source\Map\MapEntityPrefab.cs" />
<Compile Include="Source\Map\Structure.cs" />
<Compile Include="Source\Map\StructurePrefab.cs" />
<Compile Include="Source\Map\Submarine.cs" />
<Compile Include="Source\Map\WayPoint.cs" />
<Compile Include="Source\Networking\BanList.cs" />
<Compile Include="Source\Networking\EntitySpawner.cs" />
<Compile Include="Source\Networking\FileTransfer\FileReceiver.cs" />
<Compile Include="Source\Networking\GameClient.cs" />
<Compile Include="Source\Networking\GameServer.cs" />
<Compile Include="Source\Networking\GameServerSettings.cs" />
<Compile Include="Source\Networking\NetEntityEvent\ClientEntityEventManager.cs" />
<Compile Include="Source\Networking\NetEntityEvent\NetEntityEvent.cs" />
<Compile Include="Source\Networking\NetStats.cs" />
<Compile Include="Source\Networking\NetworkMember.cs" />
<Compile Include="Source\Networking\ServerLog.cs" />
<Compile Include="Source\Networking\Voting.cs" />
<Compile Include="Source\Networking\WhiteList.cs" />
<Compile Include="Source\Particles\Particle.cs" />
<Compile Include="Source\Particles\ParticleEmitter.cs" />
<Compile Include="Source\Particles\ParticleManager.cs" />
<Compile Include="Source\Particles\ParticlePrefab.cs" />
<Compile Include="Source\Physics\PhysicsBody.cs" />
<Compile Include="Source\PlayerInput.cs" />
<Compile Include="Source\Program.cs" />
<Compile Include="Source\Screens\BlurEffect.cs" />
<Compile Include="Source\Screens\EditCharacterScreen.cs" />
<Compile Include="Source\Screens\EditMapScreen.cs" />
<Compile Include="Source\Screens\GameScreen.cs" />
<Compile Include="Source\Screens\LobbyScreen.cs" />
<Compile Include="Source\Screens\MainMenuScreen.cs" />
<Compile Include="Source\Screens\NetLobbyScreen.cs" />
<Compile Include="Source\Screens\Screen.cs" />
<Compile Include="Source\Screens\ServerListScreen.cs" />
<Compile Include="Source\Sounds\OggSound.cs" />
<Compile Include="Source\Sounds\OggStream.cs" />
<Compile Include="Source\Sounds\Sound.cs" />
<Compile Include="Source\Sounds\SoundManager.cs" />
<Compile Include="Source\Sounds\SoundPlayer.cs" />
<Compile Include="Source\Sprite\Sprite.cs" />
<Compile Include="Source\Sprite\SpriteSheet.cs" />
<Compile Include="Source\Utils\MathUtils.cs" />
<Compile Include="Source\Utils\SaveUtil.cs" />
<Compile Include="Source\Utils\TextureLoader.cs" />
<Compile Include="Source\Utils\ToolBox.cs" />
</ItemGroup>
<ItemGroup>
<Reference Include="MonoGame.Framework, Version=3.6.0.1625, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\Libraries\NuGet\MonoGame.Framework.WindowsDX.3.6.0.1625\lib\net40\MonoGame.Framework.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="NVorbis, Version=0.8.4.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\Libraries\NuGet\NVorbis.0.8.5.0\lib\NVorbis.dll</HintPath>
</Reference>
<Reference Include="OpenTK, Version=1.1.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\Libraries\NuGet\OpenTK.2.0.0\lib\net20\OpenTK.dll</HintPath>
</Reference>
<Reference Include="PresentationCore" />
<Reference Include="RestSharp">
<HintPath>..\..\Libraries\NuGet\RestSharp.105.2.3\lib\net45\RestSharp.dll</HintPath>
</Reference>
<Reference Include="SharpDX, Version=2.6.3.0, Culture=neutral, PublicKeyToken=b4dcf0f35e5521f1, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\Libraries\NuGet\MonoGame.Framework.WindowsDX.3.6.0.1625\lib\net40\SharpDX.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.XML" />
<Reference Include="System.Xml.Linq" />
</ItemGroup>
<ItemGroup>
<Content Include="freetype6.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="OpenAL32.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="wrap_oal.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include=".NETFramework,Version=v4.0">
<Visible>False</Visible>
<ProductName>Microsoft .NET Framework 4 %28x86 and x64%29</ProductName>
<Install>true</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Client.3.5">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
<Install>false</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1</ProductName>
<Install>false</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Windows.Installer.4.5">
<Visible>False</Visible>
<ProductName>Windows Installer 4.5</ProductName>
<Install>true</Install>
</BootstrapperPackage>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Libraries\Farseer Physics Engine 3.5\Farseer Physics MonoGame.csproj">
<Project>{0aad36e3-51a5-4a07-ab60-5c8a66bd38b7}</Project>
<Name>Farseer Physics MonoGame</Name>
</ProjectReference>
<ProjectReference Include="..\..\Libraries\Hyper.ComponentModel\Hyper.ComponentModel.csproj">
<Project>{3b8f9edb-6e5e-450c-abc2-ec49075d0b50}</Project>
<Name>Hyper.ComponentModel</Name>
</ProjectReference>
<ProjectReference Include="..\..\Libraries\Lidgren.Network\Lidgren.Network.csproj">
<Project>{49ba1c69-6104-41ac-a5d8-b54fa9f696e8}</Project>
<Name>Lidgren.Network</Name>
</ProjectReference>
<ProjectReference Include="..\..\Libraries\SharpFont\Source\SharpFont\SharpFont.csproj">
<Project>{c293db32-fa42-486d-b128-5a12522fae4e}</Project>
<Name>SharpFont</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="OpenTK.dll.config" />
<None Include="packages.config" />
</ItemGroup>
<Import Project="..\BarotraumaShared\BarotraumaShared.projitems" Label="Shared" />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@@ -0,0 +1,25 @@
<configuration>
<dllmap os="linux" dll="opengl32.dll" target="libGL.so.1"/>
<dllmap os="linux" dll="glu32.dll" target="libGLU.so.1"/>
<dllmap os="linux" dll="openal32.dll" target="libopenal.so.1"/>
<dllmap os="linux" dll="alut.dll" target="libalut.so.0"/>
<dllmap os="linux" dll="opencl.dll" target="libOpenCL.so"/>
<dllmap os="linux" dll="libX11" target="libX11.so.6"/>
<dllmap os="linux" dll="libXi" target="libXi.so.6"/>
<dllmap os="linux" dll="SDL2.dll" target="libSDL2-2.0.so.0"/>
<dllmap os="osx" dll="opengl32.dll" target="/System/Library/Frameworks/OpenGL.framework/OpenGL"/>
<dllmap os="osx" dll="openal32.dll" target="/System/Library/Frameworks/OpenAL.framework/OpenAL" />
<dllmap os="osx" dll="alut.dll" target="/System/Library/Frameworks/OpenAL.framework/OpenAL" />
<dllmap os="osx" dll="libGLES.dll" target="/System/Library/Frameworks/OpenGLES.framework/OpenGLES" />
<dllmap os="osx" dll="libGLESv1_CM.dll" target="/System/Library/Frameworks/OpenGLES.framework/OpenGLES" />
<dllmap os="osx" dll="libGLESv2.dll" target="/System/Library/Frameworks/OpenGLES.framework/OpenGLES" />
<dllmap os="osx" dll="opencl.dll" target="/System/Library/Frameworks/OpenCL.framework/OpenCL"/>
<dllmap os="osx" dll="SDL2.dll" target="libSDL2.dylib"/>
<!-- XQuartz compatibility (X11 on Mac) -->
<dllmap os="osx" dll="libGL.so.1" target="/usr/X11/lib/libGL.dylib"/>
<dllmap os="osx" dll="libX11" target="/usr/X11/lib/libX11.dylib"/>
<dllmap os="osx" dll="libXcursor.so.1" target="/usr/X11/lib/libXcursor.dylib"/>
<dllmap os="osx" dll="libXi" target="/usr/X11/lib/libXi.dylib"/>
<dllmap os="osx" dll="libXinerama" target="/usr/X11/lib/libXinerama.dylib"/>
<dllmap os="osx" dll="libXrandr.so.2" target="/usr/X11/lib/libXrandr.dylib"/>
</configuration>

View File

@@ -31,5 +31,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("0.6.0.2")]
[assembly: AssemblyFileVersion("0.6.0.2")]
[assembly: AssemblyVersion("0.6.0.1000")]
[assembly: AssemblyFileVersion("0.6.0.1000")]

View File

@@ -0,0 +1,11 @@
using Lidgren.Network;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace Barotrauma
{
partial class AIController : ISteerable
{
public virtual void DebugDraw(SpriteBatch spriteBatch) { }
}
}

View File

@@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace Barotrauma
{
partial class AITarget
{
public static bool ShowAITargets;
public void Draw(SpriteBatch spriteBatch)
{
if (!ShowAITargets) return;
var rangeSprite = GUI.SubmarineIcon;
if (soundRange > 0.0f)
rangeSprite.Draw(spriteBatch,
new Vector2(WorldPosition.X, -WorldPosition.Y),
Color.Cyan * 0.1f, rangeSprite.Origin,
0.0f, soundRange / rangeSprite.size.X);
if (sightRange > 0.0f)
rangeSprite.Draw(spriteBatch,
new Vector2(WorldPosition.X, -WorldPosition.Y),
Color.Orange * 0.1f, rangeSprite.Origin,
0.0f, sightRange / rangeSprite.size.X);
}
}
}

View File

@@ -0,0 +1,70 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Xml.Linq;
using FarseerPhysics;
using Lidgren.Network;
using Microsoft.Xna.Framework;
using FarseerPhysics.Dynamics;
using Microsoft.Xna.Framework.Graphics;
namespace Barotrauma
{
partial class EnemyAIController : AIController
{
public override void DebugDraw(SpriteBatch spriteBatch)
{
if (Character.IsDead) return;
Vector2 pos = Character.WorldPosition;
pos.Y = -pos.Y;
if (selectedAiTarget != null)
{
GUI.DrawLine(spriteBatch, pos, new Vector2(selectedAiTarget.WorldPosition.X, -selectedAiTarget.WorldPosition.Y), Color.Red);
if (wallAttackPos != Vector2.Zero)
{
GUI.DrawRectangle(spriteBatch, ConvertUnits.ToDisplayUnits(new Vector2(wallAttackPos.X, -wallAttackPos.Y)) - new Vector2(10.0f, 10.0f), new Vector2(20.0f, 20.0f), Color.Red, false);
}
GUI.Font.DrawString(spriteBatch, targetValue.ToString(), pos - Vector2.UnitY * 20.0f, Color.Red);
}
if (selectedAiTarget != null)
{
GUI.DrawLine(spriteBatch,
new Vector2(Character.DrawPosition.X, -Character.DrawPosition.Y),
new Vector2(selectedAiTarget.WorldPosition.X, -selectedAiTarget.WorldPosition.Y), Color.Red);
}
GUI.Font.DrawString(spriteBatch, targetValue.ToString(), pos - Vector2.UnitY * 80.0f, Color.Red);
GUI.Font.DrawString(spriteBatch, "updatetargets: " + updateTargetsTimer, pos - Vector2.UnitY * 100.0f, Color.Red);
GUI.Font.DrawString(spriteBatch, "cooldown: " + coolDownTimer, pos - Vector2.UnitY * 120.0f, Color.Red);
IndoorsSteeringManager pathSteering = steeringManager as IndoorsSteeringManager;
if (pathSteering == null || pathSteering.CurrentPath == null || pathSteering.CurrentPath.CurrentNode == null) return;
GUI.DrawLine(spriteBatch,
new Vector2(Character.DrawPosition.X, -Character.DrawPosition.Y),
new Vector2(pathSteering.CurrentPath.CurrentNode.DrawPosition.X, -pathSteering.CurrentPath.CurrentNode.DrawPosition.Y),
Color.LightGreen);
for (int i = 1; i < pathSteering.CurrentPath.Nodes.Count; i++)
{
GUI.DrawLine(spriteBatch,
new Vector2(pathSteering.CurrentPath.Nodes[i].DrawPosition.X, -pathSteering.CurrentPath.Nodes[i].DrawPosition.Y),
new Vector2(pathSteering.CurrentPath.Nodes[i - 1].DrawPosition.X, -pathSteering.CurrentPath.Nodes[i - 1].DrawPosition.Y),
Color.LightGreen);
GUI.SmallFont.DrawString(spriteBatch,
pathSteering.CurrentPath.Nodes[i].ID.ToString(),
new Vector2(pathSteering.CurrentPath.Nodes[i].DrawPosition.X, -pathSteering.CurrentPath.Nodes[i].DrawPosition.Y - 10),
Color.LightGreen);
}
}
}
}

View File

@@ -0,0 +1,55 @@
using Microsoft.Xna.Framework;
using System;
namespace Barotrauma
{
partial class HumanAIController : AIController
{
partial void InitProjSpecific()
{
if (GameMain.GameSession != null && GameMain.GameSession.CrewManager != null)
{
CurrentOrder = Order.PrefabList.Find(o => o.Name.ToLowerInvariant() == "dismissed");
objectiveManager.SetOrder(CurrentOrder, "");
GameMain.GameSession.CrewManager.SetCharacterOrder(Character, CurrentOrder);
}
}
partial void SetOrderProjSpecific(Order order)
{
GameMain.GameSession.CrewManager.SetCharacterOrder(Character, order);
}
public override void DebugDraw(Microsoft.Xna.Framework.Graphics.SpriteBatch spriteBatch)
{
if (selectedAiTarget != null)
{
GUI.DrawLine(spriteBatch,
new Vector2(Character.DrawPosition.X, -Character.DrawPosition.Y),
new Vector2(selectedAiTarget.WorldPosition.X, -selectedAiTarget.WorldPosition.Y), Color.Red);
}
IndoorsSteeringManager pathSteering = steeringManager as IndoorsSteeringManager;
if (pathSteering == null || pathSteering.CurrentPath == null || pathSteering.CurrentPath.CurrentNode == null) return;
GUI.DrawLine(spriteBatch,
new Vector2(Character.DrawPosition.X, -Character.DrawPosition.Y),
new Vector2(pathSteering.CurrentPath.CurrentNode.DrawPosition.X, -pathSteering.CurrentPath.CurrentNode.DrawPosition.Y),
Color.LightGreen);
for (int i = 1; i < pathSteering.CurrentPath.Nodes.Count; i++)
{
GUI.DrawLine(spriteBatch,
new Vector2(pathSteering.CurrentPath.Nodes[i].DrawPosition.X, -pathSteering.CurrentPath.Nodes[i].DrawPosition.Y),
new Vector2(pathSteering.CurrentPath.Nodes[i - 1].DrawPosition.X, -pathSteering.CurrentPath.Nodes[i - 1].DrawPosition.Y),
Color.LightGreen);
GUI.SmallFont.DrawString(spriteBatch,
pathSteering.CurrentPath.Nodes[i].ID.ToString(),
new Vector2(pathSteering.CurrentPath.Nodes[i].DrawPosition.X, -pathSteering.CurrentPath.Nodes[i].DrawPosition.Y - 10),
Color.LightGreen);
}
}
}
}

View File

@@ -0,0 +1,42 @@
using Microsoft.Xna.Framework;
using System;
namespace Barotrauma
{
partial class AICharacter : Character
{
partial void InitProjSpecific()
{
soundTimer = Rand.Range(0.0f, soundInterval);
}
partial void SoundUpdate(float deltaTime)
{
if (soundTimer > 0)
{
soundTimer -= deltaTime;
}
else
{
switch (aiController.State)
{
case AIController.AIState.Attack:
PlaySound(CharacterSound.SoundType.Attack);
break;
default:
PlaySound(CharacterSound.SoundType.Idle);
break;
}
soundTimer = soundInterval;
}
}
public override void DrawFront(Microsoft.Xna.Framework.Graphics.SpriteBatch spriteBatch, Camera cam)
{
base.DrawFront(spriteBatch, cam);
if (GameMain.DebugDraw && !IsDead) aiController.DebugDraw(spriteBatch);
}
}
}

View File

@@ -0,0 +1,152 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using FarseerPhysics;
using FarseerPhysics.Dynamics;
using FarseerPhysics.Dynamics.Contacts;
using FarseerPhysics.Dynamics.Joints;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace Barotrauma
{
partial class Ragdoll
{
partial void ImpactProjSpecific(float impact, Body body)
{
float volume = Math.Min(impact - 3.0f, 1.0f);
if (body.UserData is Limb)
{
Limb limb = (Limb)body.UserData;
if (impact > 3.0f && limb.HitSound != null && limb.SoundTimer <= 0.0f)
{
limb.SoundTimer = Limb.SoundInterval;
limb.HitSound.Play(volume, impact * 100.0f, limb.WorldPosition);
}
}
else if (body == Collider.FarseerBody)
{
if (!character.IsRemotePlayer || GameMain.Server != null)
{
if (impact > ImpactTolerance)
{
SoundPlayer.PlayDamageSound(DamageSoundType.LimbBlunt, strongestImpact, Collider);
}
}
if (Character.Controlled == character) GameMain.GameScreen.Cam.Shake = strongestImpact;
}
}
partial void Splash(Limb limb, Hull limbHull)
{
//create a splash particle
GameMain.ParticleManager.CreateParticle("watersplash",
new Vector2(limb.Position.X, limbHull.Surface) + limbHull.Submarine.Position,
new Vector2(0.0f, Math.Abs(-limb.LinearVelocity.Y * 20.0f)),
0.0f, limbHull);
GameMain.ParticleManager.CreateParticle("bubbles",
new Vector2(limb.Position.X, limbHull.Surface) + limbHull.Submarine.Position,
limb.LinearVelocity * 0.001f,
0.0f, limbHull);
//if the Character dropped into water, create a wave
if (limb.LinearVelocity.Y < 0.0f)
{
if (splashSoundTimer <= 0.0f)
{
SoundPlayer.PlaySplashSound(limb.WorldPosition, Math.Abs(limb.LinearVelocity.Y) + Rand.Range(-5.0f, 0.0f));
splashSoundTimer = 0.5f;
}
}
}
public virtual void Draw(SpriteBatch spriteBatch)
{
if (simplePhysicsEnabled) return;
Collider.UpdateDrawPosition();
foreach (Limb limb in Limbs)
{
limb.Draw(spriteBatch);
}
}
public void DebugDraw(SpriteBatch spriteBatch)
{
if (!GameMain.DebugDraw || !character.Enabled) return;
if (simplePhysicsEnabled) return;
foreach (Limb limb in Limbs)
{
if (limb.pullJoint != null)
{
Vector2 pos = ConvertUnits.ToDisplayUnits(limb.pullJoint.WorldAnchorA);
if (currentHull != null) pos += currentHull.Submarine.DrawPosition;
pos.Y = -pos.Y;
GUI.DrawRectangle(spriteBatch, new Rectangle((int)pos.X, (int)pos.Y, 5, 5), Color.Red, true, 0.01f);
}
limb.body.DebugDraw(spriteBatch, inWater ? Color.Cyan : Color.White);
}
Collider.DebugDraw(spriteBatch, frozen ? Color.Red : (inWater ? Color.SkyBlue : Color.Gray));
GUI.Font.DrawString(spriteBatch, Collider.LinearVelocity.X.ToString(), new Vector2(Collider.DrawPosition.X, -Collider.DrawPosition.Y), Color.Orange);
foreach (RevoluteJoint joint in LimbJoints)
{
Vector2 pos = ConvertUnits.ToDisplayUnits(joint.WorldAnchorA);
GUI.DrawRectangle(spriteBatch, new Rectangle((int)pos.X, (int)-pos.Y, 5, 5), Color.White, true);
pos = ConvertUnits.ToDisplayUnits(joint.WorldAnchorB);
GUI.DrawRectangle(spriteBatch, new Rectangle((int)pos.X, (int)-pos.Y, 5, 5), Color.White, true);
}
foreach (Limb limb in Limbs)
{
if (limb.body.TargetPosition != null)
{
Vector2 pos = ConvertUnits.ToDisplayUnits((Vector2)limb.body.TargetPosition);
if (currentHull != null) pos += currentHull.Submarine.DrawPosition;
pos.Y = -pos.Y;
GUI.DrawRectangle(spriteBatch, new Rectangle((int)pos.X - 10, (int)pos.Y - 10, 20, 20), Color.Cyan, false, 0.01f);
GUI.DrawLine(spriteBatch, pos, new Vector2(limb.WorldPosition.X, -limb.WorldPosition.Y), Color.Cyan);
}
}
if (character.MemState.Count > 1)
{
Vector2 prevPos = ConvertUnits.ToDisplayUnits(character.MemState[0].Position);
if (currentHull != null) prevPos += currentHull.Submarine.DrawPosition;
prevPos.Y = -prevPos.Y;
for (int i = 1; i < character.MemState.Count; i++)
{
Vector2 currPos = ConvertUnits.ToDisplayUnits(character.MemState[i].Position);
if (currentHull != null) currPos += currentHull.Submarine.DrawPosition;
currPos.Y = -currPos.Y;
GUI.DrawRectangle(spriteBatch, new Rectangle((int)currPos.X - 3, (int)currPos.Y - 3, 6, 6), Color.Cyan * 0.6f, true, 0.01f);
GUI.DrawLine(spriteBatch, prevPos, currPos, Color.Cyan * 0.6f, 0, 3);
prevPos = currPos;
}
}
if (ignorePlatforms)
{
GUI.DrawLine(spriteBatch,
new Vector2(Collider.DrawPosition.X, -Collider.DrawPosition.Y),
new Vector2(Collider.DrawPosition.X, -Collider.DrawPosition.Y + 50),
Color.Orange, 0, 5);
}
}
}
}

View File

@@ -0,0 +1,50 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using Microsoft.Xna.Framework;
using Barotrauma.Particles;
namespace Barotrauma
{
partial class Attack
{
private Sound sound;
private ParticleEmitterPrefab particleEmitterPrefab;
partial void InitProjSpecific(XElement element)
{
string soundPath = ToolBox.GetAttributeString(element, "sound", "");
if (!string.IsNullOrWhiteSpace(soundPath))
{
sound = Sound.Load(soundPath);
}
foreach (XElement subElement in element.Elements())
{
switch (subElement.Name.ToString().ToLowerInvariant())
{
case "particleemitter":
particleEmitterPrefab = new ParticleEmitterPrefab(subElement);
break;
}
}
}
partial void DamageParticles(Vector2 worldPosition)
{
if (particleEmitterPrefab != null)
{
particleEmitterPrefab.Emit(worldPosition);
}
if (sound != null)
{
sound.Play(1.0f, 500.0f, worldPosition);
}
}
}
}

View File

@@ -64,14 +64,14 @@ namespace Barotrauma
var wayPoints = WayPoint.WayPointList.FindAll(wp => wp.Submarine==null);
if (wayPoints.Any())
{
WayPoint wp = wayPoints[Rand.Int(wayPoints.Count, false)];
WayPoint wp = wayPoints[Rand.Int(wayPoints.Count, Rand.RandSync.ClientOnly)];
pos = new Vector2(wp.Rect.X, wp.Rect.Y);
pos += Rand.Vector(200.0f, false);
pos += Rand.Vector(200.0f, Rand.RandSync.ClientOnly);
}
else
{
pos = Rand.Vector(2000.0f, false);
pos = Rand.Vector(2000.0f, Rand.RandSync.ClientOnly);
}
}
else
@@ -80,9 +80,9 @@ namespace Barotrauma
}
var prefab = prefabs[Rand.Int(prefabs.Count, false)];
var prefab = prefabs[Rand.Int(prefabs.Count, Rand.RandSync.ClientOnly)];
int amount = Rand.Range(prefab.SwarmMin, prefab.SwarmMax, false);
int amount = Rand.Range(prefab.SwarmMin, prefab.SwarmMax, Rand.RandSync.ClientOnly);
List<BackgroundCreature> swarmMembers = new List<BackgroundCreature>();
for (int n = 0; n < amount; n++)
@@ -103,7 +103,7 @@ namespace Barotrauma
activeSprites.Clear();
}
public void Update(Camera cam, float deltaTime)
public void Update(float deltaTime, Camera cam)
{
if (checkActiveTimer<0.0f)
{

View File

@@ -101,10 +101,10 @@ namespace Barotrauma
rotation = MathUtils.VectorToAngle(new Vector2(edgeNormal.Y, edgeNormal.X));
}
rotation += Rand.Range(prefab.RandomRotation.X, prefab.RandomRotation.Y, false);
rotation += Rand.Range(prefab.RandomRotation.X, prefab.RandomRotation.Y, Rand.RandSync.ClientOnly);
var newSprite = new BackgroundSprite(prefab,
new Vector3((Vector2)pos, Rand.Range(prefab.DepthRange.X, prefab.DepthRange.Y, false)), Rand.Range(prefab.Scale.X, prefab.Scale.Y, false), rotation);
new Vector3((Vector2)pos, Rand.Range(prefab.DepthRange.X, prefab.DepthRange.Y, Rand.RandSync.ClientOnly)), Rand.Range(prefab.Scale.X, prefab.Scale.Y, Rand.RandSync.ClientOnly), rotation);
//calculate the positions of the corners of the rotated sprite
Vector2 halfSize = newSprite.Prefab.Sprite.size * newSprite.Scale / 2;
@@ -155,8 +155,8 @@ namespace Barotrauma
edgeNormal = Vector2.One;
Vector2 randomPos = new Vector2(
Rand.Range(0.0f, level.Size.X, false),
Rand.Range(0.0f, level.Size.Y, false));
Rand.Range(0.0f, level.Size.X, Rand.RandSync.ClientOnly),
Rand.Range(0.0f, level.Size.Y, Rand.RandSync.ClientOnly));
if (!prefab.SpawnOnWalls) return randomPos;
@@ -167,7 +167,7 @@ namespace Barotrauma
if (cells.Any())
{
VoronoiCell cell = cells[Rand.Int(cells.Count, false)];
VoronoiCell cell = cells[Rand.Int(cells.Count, Rand.RandSync.ClientOnly)];
foreach (GraphEdge edge in cell.edges)
{
@@ -220,13 +220,13 @@ namespace Barotrauma
if (!edges.Any()) return null;
int index = Rand.Int(edges.Count, false);
int index = Rand.Int(edges.Count, Rand.RandSync.ClientOnly);
closestEdge = edges[index];
edgeNormal = normals[index];
float length = Vector2.Distance(closestEdge.point1, closestEdge.point2);
Vector2 dir = (closestEdge.point1 - closestEdge.point2) / length;
Vector2 pos = closestEdge.point2 + dir * Rand.Range(prefab.Sprite.size.X / 2.0f, length - prefab.Sprite.size.X / 2.0f, false);
Vector2 pos = closestEdge.point2 + dir * Rand.Range(prefab.Sprite.size.X / 2.0f, length - prefab.Sprite.size.X / 2.0f, Rand.RandSync.ClientOnly);
return pos;
}
@@ -331,7 +331,7 @@ namespace Barotrauma
totalCommonness += prefab.GetCommonness(levelType);
}
float randomNumber = Rand.Int(totalCommonness+1, false);
float randomNumber = Rand.Int(totalCommonness+1, Rand.RandSync.ClientOnly);
foreach (BackgroundSpritePrefab prefab in prefabs)
{

View File

@@ -0,0 +1,442 @@
using FarseerPhysics;
using FarseerPhysics.Dynamics;
using FarseerPhysics.Dynamics.Joints;
using Barotrauma.Networking;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Barotrauma.Particles;
namespace Barotrauma
{
partial class Character : Entity, IDamageable, IPropertyObject, IClientSerializable, IServerSerializable
{
protected float soundTimer;
protected float soundInterval;
private List<CharacterSound> sounds;
//the Character that the player is currently controlling
private static Character controlled;
public static Character Controlled
{
get { return controlled; }
set
{
if (controlled == value) return;
controlled = value;
CharacterHUD.Reset();
if (controlled != null)
{
controlled.Enabled = true;
}
}
}
private Dictionary<object, HUDProgressBar> hudProgressBars;
public Dictionary<object, HUDProgressBar> HUDProgressBars
{
get { return hudProgressBars; }
}
partial void InitProjSpecific(XDocument doc)
{
soundInterval = ToolBox.GetAttributeFloat(doc.Root, "soundinterval", 10.0f);
keys = new Key[Enum.GetNames(typeof(InputType)).Length];
for (int i = 0; i < Enum.GetNames(typeof(InputType)).Length; i++)
{
keys[i] = new Key(GameMain.Config.KeyBind((InputType)i));
}
var soundElements = doc.Root.Elements("sound").ToList();
sounds = new List<CharacterSound>();
foreach (XElement soundElement in soundElements)
{
sounds.Add(new CharacterSound(soundElement));
}
hudProgressBars = new Dictionary<object, HUDProgressBar>();
}
/// <summary>
/// Control the Character according to player input
/// </summary>
public void ControlLocalPlayer(float deltaTime, Camera cam, bool moveCam = true)
{
if (!DisableControls)
{
for (int i = 0; i < keys.Length; i++)
{
keys[i].SetState();
}
}
else
{
foreach (Key key in keys)
{
if (key == null) continue;
key.Reset();
}
}
if (moveCam)
{
if (needsAir &&
pressureProtection < 80.0f &&
(AnimController.CurrentHull == null || AnimController.CurrentHull.LethalPressure > 50.0f))
{
float pressure = AnimController.CurrentHull == null ? 100.0f : AnimController.CurrentHull.LethalPressure;
cam.Zoom = MathHelper.Lerp(cam.Zoom,
(pressure / 50.0f) * Rand.Range(1.0f, 1.05f),
(pressure - 50.0f) / 50.0f);
}
if (IsHumanoid)
{
cam.OffsetAmount = MathHelper.Lerp(cam.OffsetAmount, 250.0f, deltaTime);
}
else
{
//increased visibility range when controlling large a non-humanoid
cam.OffsetAmount = MathHelper.Lerp(cam.OffsetAmount, MathHelper.Clamp(Mass, 250.0f, 800.0f), deltaTime);
}
}
cursorPosition = cam.ScreenToWorld(PlayerInput.MousePosition);
if (AnimController.CurrentHull != null && AnimController.CurrentHull.Submarine != null)
{
cursorPosition -= AnimController.CurrentHull.Submarine.Position;
}
Vector2 mouseSimPos = ConvertUnits.ToSimUnits(cursorPosition);
if (Lights.LightManager.ViewTarget == this && Vector2.DistanceSquared(AnimController.Limbs[0].SimPosition, mouseSimPos) > 1.0f)
{
Body body = Submarine.PickBody(AnimController.Limbs[0].SimPosition, mouseSimPos);
Structure structure = null;
if (body != null) structure = body.UserData as Structure;
if (structure != null)
{
if (!structure.CastShadow && moveCam)
{
cam.OffsetAmount = MathHelper.Lerp(cam.OffsetAmount, 500.0f, 0.05f);
}
}
}
if (!LockHands)
{
//find the closest item if selectkey has been hit, or if the Character is being
//controlled by the player (in order to highlight it)
if (findClosestTimer <= 0.0f || Screen.Selected == GameMain.EditMapScreen)
{
closestCharacter = FindClosestCharacter(mouseSimPos);
if (closestCharacter != null && closestCharacter.info == null)
{
closestCharacter = null;
}
float closestItemDist = 0.0f;
closestItem = FindClosestItem(mouseSimPos, out closestItemDist);
if (closestCharacter != null && closestItem != null)
{
if (Vector2.DistanceSquared(closestCharacter.SimPosition, mouseSimPos) < ConvertUnits.ToSimUnits(closestItemDist) * ConvertUnits.ToSimUnits(closestItemDist))
{
if (selectedConstruction != closestItem) closestItem = null;
}
else
{
closestCharacter = null;
}
}
findClosestTimer = 0.1f;
}
else
{
findClosestTimer -= deltaTime;
}
if (selectedCharacter == null && closestItem != null)
{
closestItem.IsHighlighted = true;
if (!LockHands && closestItem.Pick(this))
{
}
}
if (IsKeyHit(InputType.Select))
{
if (selectedCharacter != null)
{
DeselectCharacter();
}
else if (closestCharacter != null && closestCharacter.IsHumanoid && closestCharacter.CanBeSelected)
{
SelectCharacter(closestCharacter);
}
}
}
else
{
if (selectedCharacter != null) DeselectCharacter();
selectedConstruction = null;
closestItem = null;
closestCharacter = null;
}
DisableControls = false;
}
partial void UpdateControlled(float deltaTime,Camera cam)
{
if (controlled != this) return;
ControlLocalPlayer(deltaTime, cam);
Lights.LightManager.ViewTarget = this;
CharacterHUD.Update(deltaTime, this);
foreach (HUDProgressBar progressBar in hudProgressBars.Values)
{
progressBar.Update(deltaTime);
}
foreach (var pb in hudProgressBars.Where(pb => pb.Value.FadeTimer <= 0.0f).ToList())
{
hudProgressBars.Remove(pb.Key);
}
}
partial void DamageHUD(float amount)
{
if (controlled == this) CharacterHUD.TakeDamage(amount);
}
partial void UpdateOxygenProjSpecific(float prevOxygen)
{
if (prevOxygen > 0.0f && Oxygen <= 0.0f && controlled == this)
{
SoundPlayer.PlaySound("drown");
}
}
partial void KillProjSpecific()
{
if (GameMain.NetworkMember != null && Character.controlled == this)
{
string chatMessage = InfoTextManager.GetInfoText("Self_CauseOfDeath." + causeOfDeath.ToString());
if (GameMain.Client != null) chatMessage += " Your chat messages will only be visible to other dead players.";
GameMain.NetworkMember.AddChatMessage(chatMessage, ChatMessageType.Dead);
GameMain.LightManager.LosEnabled = false;
controlled = null;
}
PlaySound(CharacterSound.SoundType.Die);
}
partial void DisposeProjSpecific()
{
if (controlled == this) controlled = null;
if (GameMain.GameSession?.CrewManager != null &&
GameMain.GameSession.CrewManager.characters.Contains(this))
{
GameMain.GameSession.CrewManager.characters.Remove(this);
}
if (GameMain.Client != null && GameMain.Client.Character == this) GameMain.Client.Character = null;
if (Lights.LightManager.ViewTarget == this) Lights.LightManager.ViewTarget = null;
}
public static void AddAllToGUIUpdateList()
{
for (int i = 0; i < CharacterList.Count; i++)
{
CharacterList[i].AddToGUIUpdateList();
}
}
public virtual void AddToGUIUpdateList()
{
if (controlled == this)
{
CharacterHUD.AddToGUIUpdateList(this);
}
}
public void Draw(SpriteBatch spriteBatch)
{
if (!Enabled) return;
AnimController.Draw(spriteBatch);
}
public void DrawHUD(SpriteBatch spriteBatch, Camera cam)
{
CharacterHUD.Draw(spriteBatch, this, cam);
}
public virtual void DrawFront(SpriteBatch spriteBatch, Camera cam)
{
if (!Enabled) return;
if (GameMain.DebugDraw)
{
AnimController.DebugDraw(spriteBatch);
if (aiTarget != null) aiTarget.Draw(spriteBatch);
}
/*if (memPos != null && memPos.Count > 0 && controlled == this)
{
PosInfo serverPos = memPos.Last();
Vector2 remoteVec = ConvertUnits.ToDisplayUnits(serverPos.Position);
if (Submarine != null)
{
remoteVec += Submarine.DrawPosition;
}
remoteVec.Y = -remoteVec.Y;
PosInfo localPos = memLocalPos.Find(m => m.ID == serverPos.ID);
int mpind = memLocalPos.FindIndex(lp => lp.ID == localPos.ID);
PosInfo localPos1 = mpind > 0 ? memLocalPos[mpind - 1] : null;
PosInfo localPos2 = mpind < memLocalPos.Count-1 ? memLocalPos[mpind + 1] : null;
Vector2 localVec = ConvertUnits.ToDisplayUnits(localPos.Position);
Vector2 localVec1 = localPos1 != null ? ConvertUnits.ToDisplayUnits(((PosInfo)localPos1).Position) : Vector2.Zero;
Vector2 localVec2 = localPos2 != null ? ConvertUnits.ToDisplayUnits(((PosInfo)localPos2).Position) : Vector2.Zero;
if (Submarine != null)
{
localVec += Submarine.DrawPosition;
localVec1 += Submarine.DrawPosition;
localVec2 += Submarine.DrawPosition;
}
localVec.Y = -localVec.Y;
localVec1.Y = -localVec1.Y;
localVec2.Y = -localVec2.Y;
//GUI.DrawLine(spriteBatch, remoteVec, localVec, Color.Yellow, 0, 10);
if (localPos1 != null) GUI.DrawLine(spriteBatch, remoteVec, localVec1, Color.Lime, 0, 2);
if (localPos2 != null) GUI.DrawLine(spriteBatch, remoteVec + Vector2.One, localVec2 + Vector2.One, Color.Red, 0, 2);
}
Vector2 mouseDrawPos = CursorWorldPosition;
mouseDrawPos.Y = -mouseDrawPos.Y;
GUI.DrawLine(spriteBatch, mouseDrawPos - new Vector2(0, 5), mouseDrawPos + new Vector2(0, 5), Color.Red, 0, 10);
Vector2 closestItemPos = closestItem != null ? closestItem.DrawPosition : Vector2.Zero;
closestItemPos.Y = -closestItemPos.Y;
GUI.DrawLine(spriteBatch, closestItemPos - new Vector2(0, 5), closestItemPos + new Vector2(0, 5), Color.Lime, 0, 10);*/
if (this == controlled || GUI.DisableHUD) return;
Vector2 pos = DrawPosition;
pos.Y = -pos.Y;
if (speechBubbleTimer > 0.0f)
{
GUI.SpeechBubbleIcon.Draw(spriteBatch, pos - Vector2.UnitY * 100.0f,
speechBubbleColor * Math.Min(speechBubbleTimer, 1.0f), 0.0f,
Math.Min((float)speechBubbleTimer, 1.0f));
}
if (this == controlled) return;
if (info != null)
{
Vector2 namePos = new Vector2(pos.X, pos.Y - 110.0f - (5.0f / cam.Zoom)) - GUI.Font.MeasureString(Info.Name) * 0.5f / cam.Zoom;
Color nameColor = Color.White;
if (Character.Controlled != null && TeamID != Character.Controlled.TeamID)
{
nameColor = Color.Red;
}
GUI.Font.DrawString(spriteBatch, Info.Name, namePos + new Vector2(1.0f / cam.Zoom, 1.0f / cam.Zoom), Color.Black, 0.0f, Vector2.Zero, 1.0f / cam.Zoom, SpriteEffects.None, 0.001f);
GUI.Font.DrawString(spriteBatch, Info.Name, namePos, nameColor, 0.0f, Vector2.Zero, 1.0f / cam.Zoom, SpriteEffects.None, 0.0f);
if (GameMain.DebugDraw)
{
GUI.Font.DrawString(spriteBatch, ID.ToString(), namePos - new Vector2(0.0f, 20.0f), Color.White);
}
}
if (isDead) return;
if (health < maxHealth * 0.98f)
{
Vector2 healthBarPos = new Vector2(pos.X - 50, DrawPosition.Y + 100.0f);
GUI.DrawProgressBar(spriteBatch, healthBarPos, new Vector2(100.0f, 15.0f), health / maxHealth, Color.Lerp(Color.Red, Color.Green, health / maxHealth) * 0.8f);
}
}
/// <summary>
/// Creates a progress bar that's "linked" to the specified object (or updates an existing one if there's one already linked to the object)
/// The progress bar will automatically fade out after 1 sec if the method hasn't been called during that time
/// </summary>
public HUDProgressBar UpdateHUDProgressBar(object linkedObject, Vector2 worldPosition, float progress, Color emptyColor, Color fullColor)
{
if (controlled != this) return null;
HUDProgressBar progressBar = null;
if (!hudProgressBars.TryGetValue(linkedObject, out progressBar))
{
progressBar = new HUDProgressBar(worldPosition, Submarine, emptyColor, fullColor);
hudProgressBars.Add(linkedObject, progressBar);
}
progressBar.WorldPosition = worldPosition;
progressBar.FadeTimer = Math.Max(progressBar.FadeTimer, 1.0f);
progressBar.Progress = progress;
return progressBar;
}
public void PlaySound(CharacterSound.SoundType soundType)
{
if (sounds == null || sounds.Count == 0) return;
var matchingSounds = sounds.FindAll(s => s.Type == soundType);
if (matchingSounds.Count == 0) return;
var selectedSound = matchingSounds[Rand.Int(matchingSounds.Count)];
selectedSound.Sound.Play(1.0f, selectedSound.Range, AnimController.WorldPosition);
}
partial void ImplodeFX()
{
Vector2 centerOfMass = AnimController.GetCenterOfMass();
SoundPlayer.PlaySound("implode", 1.0f, 150.0f, WorldPosition);
for (int i = 0; i < 10; i++)
{
Particle p = GameMain.ParticleManager.CreateParticle("waterblood",
ConvertUnits.ToDisplayUnits(centerOfMass) + Rand.Vector(5.0f),
Rand.Vector(10.0f));
if (p != null) p.Size *= 2.0f;
GameMain.ParticleManager.CreateParticle("bubbles",
ConvertUnits.ToDisplayUnits(centerOfMass) + Rand.Vector(5.0f),
new Vector2(Rand.Range(-50f, 50f), Rand.Range(-100f, 50f)));
}
}
}
}

View File

@@ -0,0 +1,75 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml.Linq;
namespace Barotrauma
{
partial class CharacterInfo
{
public GUIFrame CreateInfoFrame(Rectangle rect)
{
GUIFrame frame = new GUIFrame(rect, Color.Transparent);
frame.Padding = new Vector4(10.0f, 10.0f, 10.0f, 10.0f);
return CreateInfoFrame(frame);
}
public GUIFrame CreateInfoFrame(GUIFrame frame)
{
new GUIImage(new Rectangle(0, 0, 30, 30), HeadSprite, Alignment.TopLeft, frame);
ScalableFont font = frame.Rect.Width < 280 ? GUI.SmallFont : GUI.Font;
int x = 0, y = 0;
new GUITextBlock(new Rectangle(x + 60, y, 200, 20), Name, "", frame, font);
y += 20;
if (Job != null)
{
new GUITextBlock(new Rectangle(x + 60, y, 200, 20), Job.Name, "", frame, font);
y += 30;
var skills = Job.Skills;
skills.Sort((s1, s2) => -s1.Level.CompareTo(s2.Level));
new GUITextBlock(new Rectangle(x, y, 200, 20), "Skills:", "", frame, font);
y += 20;
foreach (Skill skill in skills)
{
Color textColor = Color.White * (0.5f + skill.Level / 200.0f);
new GUITextBlock(new Rectangle(x, y, 200, 20), skill.Name, Color.Transparent, textColor, Alignment.Left, "", frame).Font = font;
new GUITextBlock(new Rectangle(x, y, 200, 20), skill.Level.ToString(), Color.Transparent, textColor, Alignment.Right, "", frame).Font = font;
y += 20;
}
}
return frame;
}
public GUIFrame CreateCharacterFrame(GUIComponent parent, string text, object userData)
{
GUIFrame frame = new GUIFrame(new Rectangle(0, 0, 0, 40), Color.Transparent, "ListBoxElement", parent);
frame.UserData = userData;
GUITextBlock textBlock = new GUITextBlock(
new Rectangle(40, 0, 0, 25),
text,
null, null,
Alignment.Left, Alignment.Left,
"", frame, false);
textBlock.Font = GUI.SmallFont;
textBlock.Padding = new Vector4(5.0f, 0.0f, 5.0f, 0.0f);
new GUIImage(new Rectangle(-5, -5, 0, 0), HeadSprite, Alignment.Left, frame);
return frame;
}
}
}

View File

@@ -0,0 +1,296 @@
using Barotrauma.Networking;
using Lidgren.Network;
using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
using System.Linq;
namespace Barotrauma
{
partial class Character
{
public virtual void ClientWrite(NetBuffer msg, object[] extraData = null)
{
if (GameMain.Server != null) return;
if (extraData != null)
{
switch ((NetEntityEvent.Type)extraData[0])
{
case NetEntityEvent.Type.InventoryState:
msg.WriteRangedInteger(0, 2, 0);
inventory.ClientWrite(msg, extraData);
break;
case NetEntityEvent.Type.Repair:
msg.WriteRangedInteger(0, 2, 1);
msg.Write(AnimController.Anim == AnimController.Animation.CPR);
break;
case NetEntityEvent.Type.Status:
msg.WriteRangedInteger(0, 2, 2);
break;
}
}
else
{
msg.Write((byte)ClientNetObject.CHARACTER_INPUT);
if (memInput.Count > 60)
{
memInput.RemoveRange(60, memInput.Count - 60);
}
msg.Write(LastNetworkUpdateID);
byte inputCount = Math.Min((byte)memInput.Count, (byte)60);
msg.Write(inputCount);
for (int i = 0; i < inputCount; i++)
{
msg.WriteRangedInteger(0, (int)InputNetFlags.MaxVal, (int)memInput[i].states);
if (memInput[i].states.HasFlag(InputNetFlags.Aim))
{
msg.Write(memInput[i].intAim);
}
if (memInput[i].states.HasFlag(InputNetFlags.Select) || memInput[i].states.HasFlag(InputNetFlags.Use))
{
msg.Write(memInput[i].interact);
}
}
}
msg.WritePadBits();
}
public virtual void ClientRead(ServerNetObject type, NetBuffer msg, float sendingTime)
{
if (GameMain.Server != null) return;
switch (type)
{
case ServerNetObject.ENTITY_POSITION:
bool facingRight = AnimController.Dir > 0.0f;
lastRecvPositionUpdateTime = (float)NetTime.Now;
AnimController.Frozen = false;
Enabled = true;
UInt16 networkUpdateID = 0;
if (msg.ReadBoolean())
{
networkUpdateID = msg.ReadUInt16();
}
else
{
bool aimInput = msg.ReadBoolean();
keys[(int)InputType.Aim].Held = aimInput;
keys[(int)InputType.Aim].SetState(false, aimInput);
bool useInput = msg.ReadBoolean();
keys[(int)InputType.Use].Held = useInput;
keys[(int)InputType.Use].SetState(false, useInput);
bool hasAttackLimb = msg.ReadBoolean();
if (hasAttackLimb)
{
bool attackInput = msg.ReadBoolean();
keys[(int)InputType.Attack].Held = attackInput;
keys[(int)InputType.Attack].SetState(false, attackInput);
}
if (aimInput)
{
double aimAngle = ((double)msg.ReadUInt16() / 65535.0) * 2.0 * Math.PI;
cursorPosition = (ViewTarget == null ? AnimController.Collider.Position : ViewTarget.Position)
+ new Vector2((float)Math.Cos(aimAngle), (float)Math.Sin(aimAngle)) * 60.0f;
TransformCursorPos();
}
facingRight = msg.ReadBoolean();
}
bool entitySelected = msg.ReadBoolean();
Entity selectedEntity = null;
AnimController.Animation animation = AnimController.Animation.None;
if (entitySelected)
{
ushort entityID = msg.ReadUInt16();
selectedEntity = FindEntityByID(entityID);
if (selectedEntity is Character)
{
bool doingCpr = msg.ReadBoolean();
if (doingCpr && selectedCharacter != null)
{
animation = AnimController.Animation.CPR;
}
}
}
Vector2 pos = new Vector2(
msg.ReadFloat(),
msg.ReadFloat());
int index = 0;
if (GameMain.NetworkMember.Character == this && AllowInput)
{
var posInfo = new CharacterStateInfo(pos, networkUpdateID, facingRight ? Direction.Right : Direction.Left, selectedEntity, animation);
while (index < memState.Count && NetIdUtils.IdMoreRecent(posInfo.ID, memState[index].ID))
index++;
memState.Insert(index, posInfo);
}
else
{
var posInfo = new CharacterStateInfo(pos, sendingTime, facingRight ? Direction.Right : Direction.Left, selectedEntity, animation);
while (index < memState.Count && posInfo.Timestamp > memState[index].Timestamp)
index++;
memState.Insert(index, posInfo);
}
break;
case ServerNetObject.ENTITY_EVENT:
int eventType = msg.ReadRangedInteger(0, 2);
switch (eventType)
{
case 0:
inventory.ClientRead(type, msg, sendingTime);
break;
case 1:
byte ownerID = msg.ReadByte();
ResetNetState();
if (ownerID == GameMain.Client.ID)
{
if (controlled != null)
{
LastNetworkUpdateID = controlled.LastNetworkUpdateID;
}
controlled = this;
IsRemotePlayer = false;
GameMain.Client.Character = this;
}
else if (controlled == this)
{
controlled = null;
IsRemotePlayer = ownerID > 0;
}
break;
case 2:
ReadStatus(msg);
break;
}
break;
}
}
public static Character ReadSpawnData(NetBuffer inc, bool spawn = true)
{
DebugConsole.NewMessage("READING CHARACTER SPAWN DATA", Color.Cyan);
if (GameMain.Server != null) return null;
bool noInfo = inc.ReadBoolean();
ushort id = inc.ReadUInt16();
string configPath = inc.ReadString();
Vector2 position = new Vector2(inc.ReadFloat(), inc.ReadFloat());
bool enabled = inc.ReadBoolean();
DebugConsole.Log("Received spawn data for " + configPath);
Character character = null;
if (noInfo)
{
if (!spawn) return null;
character = Character.Create(configPath, position, null, true);
character.ID = id;
}
else
{
bool hasOwner = inc.ReadBoolean();
int ownerId = hasOwner ? inc.ReadByte() : -1;
string newName = inc.ReadString();
byte teamID = inc.ReadByte();
bool hasAi = inc.ReadBoolean();
bool isFemale = inc.ReadBoolean();
int headSpriteID = inc.ReadByte();
string jobName = inc.ReadString();
JobPrefab jobPrefab = null;
Dictionary<string, int> skillLevels = new Dictionary<string, int>();
if (!string.IsNullOrEmpty(jobName))
{
jobPrefab = JobPrefab.List.Find(jp => jp.Name == jobName);
int skillCount = inc.ReadByte();
for (int i = 0; i < skillCount; i++)
{
string skillName = inc.ReadString();
int skillLevel = inc.ReadRangedInteger(0, 100);
skillLevels.Add(skillName, skillLevel);
}
}
if (!spawn) return null;
CharacterInfo ch = new CharacterInfo(configPath, newName, isFemale ? Gender.Female : Gender.Male, jobPrefab);
ch.HeadSpriteId = headSpriteID;
System.Diagnostics.Debug.Assert(skillLevels.Count == ch.Job.Skills.Count);
if (ch.Job != null)
{
foreach (KeyValuePair<string, int> skill in skillLevels)
{
Skill matchingSkill = ch.Job.Skills.Find(s => s.Name == skill.Key);
if (matchingSkill == null)
{
DebugConsole.ThrowError("Skill \"" + skill.Key + "\" not found in character \"" + newName + "\"");
continue;
}
matchingSkill.Level = skill.Value;
}
}
character = Create(configPath, position, ch, GameMain.Client.ID != ownerId, hasAi);
character.ID = id;
character.TeamID = teamID;
if (GameMain.Client.ID == ownerId)
{
GameMain.Client.Character = character;
Controlled = character;
GameMain.LightManager.LosEnabled = true;
character.memInput.Clear();
character.memState.Clear();
character.memLocalState.Clear();
}
else
{
var ownerClient = GameMain.Client.ConnectedClients.Find(c => c.ID == ownerId);
if (ownerClient != null)
{
ownerClient.Character = character;
}
}
if (configPath == Character.HumanConfigFile)
{
GameMain.GameSession.CrewManager.characters.Add(character);
}
}
character.Enabled = Controlled == character || enabled;
return character;
}
}
}

View File

@@ -0,0 +1,36 @@
using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
namespace Barotrauma
{
partial class HuskInfection
{
partial void UpdateProjSpecific(float prevTimer, Character character)
{
if (IncubationTimer < 0.5f)
{
if (prevTimer % 0.1f > 0.05f && IncubationTimer % 0.1f < 0.05f)
{
GUI.AddMessage(InfoTextManager.GetInfoText("HuskDormant"), Color.Red, 4.0f);
}
}
else if (IncubationTimer < 1.0f)
{
if (state == InfectionState.Dormant && Character.Controlled == character)
{
new GUIMessageBox("", InfoTextManager.GetInfoText("HuskCantSpeak"));
}
}
else
{
if (Character.Controlled == character) new GUIMessageBox("", InfoTextManager.GetInfoText("HuskActivate"));
}
}
}
}

View File

@@ -0,0 +1,57 @@
using Microsoft.Xna.Framework;
using System.Collections.Generic;
using System.Globalization;
using System.Xml.Linq;
using System.Linq;
namespace Barotrauma
{
partial class JobPrefab
{
public GUIFrame CreateInfoFrame()
{
int width = 500, height = 400;
GUIFrame backFrame = new GUIFrame(Rectangle.Empty, Color.Black * 0.5f);
backFrame.Padding = Vector4.Zero;
GUIFrame frame = new GUIFrame(new Rectangle(GameMain.GraphicsWidth / 2 - width / 2, GameMain.GraphicsHeight / 2 - height / 2, width, height), "", backFrame);
frame.Padding = new Vector4(30.0f, 30.0f, 30.0f, 30.0f);
new GUITextBlock(new Rectangle(0, 0, 100, 20), Name, "", Alignment.TopLeft, Alignment.TopLeft, frame, false, GUI.LargeFont);
var descriptionBlock = new GUITextBlock(new Rectangle(0, 40, 0, 0), Description, "", Alignment.TopLeft, Alignment.TopLeft, frame, true, GUI.SmallFont);
new GUITextBlock(new Rectangle(0, 40 + descriptionBlock.Rect.Height + 20, 100, 20), "Skills: ", "", Alignment.TopLeft, Alignment.TopLeft, frame, false, GUI.LargeFont);
int y = 40 + descriptionBlock.Rect.Height + 50;
foreach (SkillPrefab skill in Skills)
{
string skillDescription = Skill.GetLevelName((int)skill.LevelRange.X);
string skillDescription2 = Skill.GetLevelName((int)skill.LevelRange.Y);
if (skillDescription2 != skillDescription)
{
skillDescription += "/" + skillDescription2;
}
new GUITextBlock(new Rectangle(0, y, 100, 20),
" - " + skill.Name + ": " + skillDescription, "", Alignment.TopLeft, Alignment.TopLeft, frame, false, GUI.SmallFont);
y += 20;
}
new GUITextBlock(new Rectangle(250, 40 + descriptionBlock.Rect.Height + 20, 0, 20), "Items: ", "", Alignment.TopLeft, Alignment.TopLeft, frame, false, GUI.LargeFont);
y = 40 + descriptionBlock.Rect.Height + 50;
foreach (string itemName in ItemNames)
{
new GUITextBlock(new Rectangle(250, y, 100, 20),
" - " + itemName, "", Alignment.TopLeft, Alignment.TopLeft, frame, false, GUI.SmallFont);
y += 20;
}
return backFrame;
}
}
}

View File

@@ -0,0 +1,136 @@
using System;
using System.Xml.Linq;
using FarseerPhysics;
using FarseerPhysics.Dynamics;
using FarseerPhysics.Dynamics.Joints;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Barotrauma.Items.Components;
using System.Collections.Generic;
using Barotrauma.Lights;
using System.Linq;
using System.IO;
namespace Barotrauma
{
partial class Limb
{
public LightSource LightSource
{
get;
private set;
}
Sound hitSound;
public Sound HitSound
{
get { return hitSound; }
}
partial void InitProjSpecific(XElement element)
{
foreach (XElement subElement in element.Elements())
{
switch (subElement.Name.ToString().ToLowerInvariant())
{
case "lightsource":
LightSource = new LightSource(subElement);
break;
case "sound":
hitSound = Sound.Load(ToolBox.GetAttributeString(subElement, "file", ""));
break;
}
}
}
partial void UpdateProjSpecific()
{
if (LightSource != null)
{
LightSource.ParentSub = body.Submarine;
}
}
public void Draw(SpriteBatch spriteBatch)
{
float brightness = 1.0f - (burnt / 100.0f) * 0.5f;
Color color = new Color(brightness, brightness, brightness);
if (isSevered)
{
if (severedFadeOutTimer > SeveredFadeOutTime)
{
return;
}
else if (severedFadeOutTimer > SeveredFadeOutTime - 1.0f)
{
color *= SeveredFadeOutTime - severedFadeOutTimer;
}
}
body.Dir = Dir;
bool hideLimb = wearingItems.Any(w => w != null && w.HideLimb);
if (!hideLimb)
{
body.Draw(spriteBatch, sprite, color, null, scale);
}
else
{
body.UpdateDrawPosition();
}
if (LightSource != null)
{
LightSource.Position = body.DrawPosition;
}
foreach (WearableSprite wearable in wearingItems)
{
SpriteEffects spriteEffect = (dir == Direction.Right) ? SpriteEffects.None : SpriteEffects.FlipHorizontally;
Vector2 origin = wearable.Sprite.Origin;
if (body.Dir == -1.0f) origin.X = wearable.Sprite.SourceRect.Width - origin.X;
float depth = sprite.Depth - 0.000001f;
if (wearable.DepthLimb != LimbType.None)
{
Limb depthLimb = character.AnimController.GetLimb(wearable.DepthLimb);
if (depthLimb != null)
{
depth = depthLimb.sprite.Depth - 0.000001f;
}
}
wearable.Sprite.Draw(spriteBatch,
new Vector2(body.DrawPosition.X, -body.DrawPosition.Y),
color, origin,
-body.DrawRotation,
scale, spriteEffect, depth);
}
if (damage > 0.0f && damagedSprite != null && !hideLimb)
{
SpriteEffects spriteEffect = (dir == Direction.Right) ? SpriteEffects.None : SpriteEffects.FlipHorizontally;
float depth = sprite.Depth - 0.0000015f;
damagedSprite.Draw(spriteBatch,
new Vector2(body.DrawPosition.X, -body.DrawPosition.Y),
color * Math.Min(damage / 50.0f, 1.0f), sprite.Origin,
-body.DrawRotation,
1.0f, spriteEffect, depth);
}
if (!GameMain.DebugDraw) return;
if (pullJoint != null)
{
Vector2 pos = ConvertUnits.ToDisplayUnits(pullJoint.WorldAnchorB);
GUI.DrawRectangle(spriteBatch, new Rectangle((int)pos.X, (int)-pos.Y, 5, 5), Color.Red, true);
}
}
}
}

View File

@@ -0,0 +1,491 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Barotrauma.Networking;
using Barotrauma.Items.Components;
using System.Text;
using FarseerPhysics;
namespace Barotrauma
{
static partial class DebugConsole
{
static bool isOpen;
//used for keeping track of the message entered when pressing up/down
static int selectedIndex;
public static bool IsOpen
{
get
{
return isOpen;
}
}
static GUIFrame frame;
static GUIListBox listBox;
static GUITextBox textBox;
public static void Init(GameWindow window)
{
int x = 20, y = 20;
int width = 800, height = 500;
frame = new GUIFrame(new Rectangle(x, y, width, height), new Color(0.4f, 0.4f, 0.4f, 0.8f));
frame.Padding = new Vector4(5.0f, 5.0f, 5.0f, 5.0f);
listBox = new GUIListBox(new Rectangle(0, 0, 0, frame.Rect.Height - 40), Color.Black, "", frame);
//listBox.Color = Color.Black * 0.7f;
textBox = new GUITextBox(new Rectangle(0, 0, 0, 20), Color.Black, Color.White, Alignment.BottomLeft, Alignment.Left, "", frame);
//textBox.Color = Color.Black * 0.7f;
//messages already added before initialization -> add them to the listbox
List<ColoredText> unInitializedMessages = new List<ColoredText>(Messages);
Messages.Clear();
foreach (ColoredText msg in unInitializedMessages)
{
NewMessage(msg.Text, msg.Color);
}
NewMessage("Press F3 to open/close the debug console", Color.Cyan);
NewMessage("Enter \"help\" for a list of available console commands", Color.Cyan);
}
public static void AddToGUIUpdateList()
{
if (isOpen)
{
frame.AddToGUIUpdateList();
}
}
public static void Update(GameMain game, float deltaTime)
{
if (PlayerInput.KeyHit(Keys.F3))
{
isOpen = !isOpen;
if (isOpen)
{
textBox.Select();
AddToGUIUpdateList();
}
else
{
GUIComponent.ForceMouseOn(null);
textBox.Deselect();
}
//keyboardDispatcher.Subscriber = (isOpen) ? textBox : null;
}
if (isOpen)
{
frame.Update(deltaTime);
Character.DisableControls = true;
if (PlayerInput.KeyHit(Keys.Up))
{
SelectMessage(-1);
}
else if (PlayerInput.KeyHit(Keys.Down))
{
SelectMessage(1);
}
//textBox.Update(deltaTime);
if (PlayerInput.KeyDown(Keys.Enter) && textBox.Text != "")
{
ExecuteCommand(textBox.Text, game);
textBox.Text = "";
//selectedIndex = messages.Count;
}
}
}
private static void SelectMessage(int direction)
{
int messageCount = listBox.children.Count;
if (messageCount == 0) return;
direction = Math.Min(Math.Max(-1, direction), 1);
selectedIndex += direction;
if (selectedIndex < 0) selectedIndex = messageCount - 1;
selectedIndex = selectedIndex % messageCount;
textBox.Text = (listBox.children[selectedIndex] as GUITextBlock).Text;
}
public static void Draw(SpriteBatch spriteBatch)
{
if (!isOpen) return;
frame.Draw(spriteBatch);
}
private static bool IsCommandPermitted(string command, GameClient client)
{
switch (command)
{
case "kick":
return client.HasPermission(ClientPermissions.Kick);
case "ban":
case "banip":
return client.HasPermission(ClientPermissions.Ban);
case "netstats":
case "help":
case "dumpids":
case "admin":
case "entitylist":
return true;
default:
return false;
}
}
private static bool ExecProjSpecific(string[] commands)
{
switch (commands[0].ToLowerInvariant())
{
case "startclient":
if (commands.Length == 1) return true;
if (GameMain.Client == null)
{
GameMain.NetworkMember = new GameClient("Name");
GameMain.Client.ConnectToServer(commands[1]);
}
break;
case "mainmenuscreen":
case "mainmenu":
case "menu":
GameMain.GameSession = null;
List<Character> characters = new List<Character>(Character.CharacterList);
foreach (Character c in characters)
{
c.Remove();
}
GameMain.MainMenuScreen.Select();
break;
case "gamescreen":
case "game":
GameMain.GameScreen.Select();
break;
case "editmapscreen":
case "editmap":
case "edit":
if (commands.Length > 1)
{
Submarine.Load(string.Join(" ", commands.Skip(1)), true);
}
GameMain.EditMapScreen.Select();
break;
case "editcharacter":
case "editchar":
GameMain.EditCharacterScreen.Select();
break;
case "controlcharacter":
case "control":
{
if (commands.Length < 2) break;
var character = FindMatchingCharacter(commands, true);
if (character != null)
{
Character.Controlled = character;
}
}
break;
case "setclientcharacter":
{
if (GameMain.Server == null) break;
int separatorIndex = Array.IndexOf(commands, ";");
if (separatorIndex == -1 || commands.Length < 4)
{
ThrowError("Invalid parameters. The command should be formatted as \"setclientcharacter [client] ; [character]\"");
break;
}
string[] commandsLeft = commands.Take(separatorIndex).ToArray();
string[] commandsRight = commands.Skip(separatorIndex).ToArray();
string clientName = String.Join(" ", commandsLeft.Skip(1));
var client = GameMain.Server.ConnectedClients.Find(c => c.name == clientName);
if (client == null)
{
ThrowError("Client \"" + clientName + "\" not found.");
}
var character = FindMatchingCharacter(commandsRight, false);
GameMain.Server.SetClientCharacter(client, character);
}
break;
case "test":
Submarine.Load("aegir mark ii", true);
GameMain.DebugDraw = true;
GameMain.LightManager.LosEnabled = false;
GameMain.EditMapScreen.Select();
break;
case "shake":
GameMain.GameScreen.Cam.Shake = 10.0f;
break;
case "losenabled":
case "los":
case "drawlos":
GameMain.LightManager.LosEnabled = !GameMain.LightManager.LosEnabled;
break;
case "lighting":
case "lightingenabled":
case "light":
case "lights":
GameMain.LightManager.LightingEnabled = !GameMain.LightManager.LightingEnabled;
break;
case "tutorial":
TutorialMode.StartTutorial(Tutorials.TutorialType.TutorialTypes[0]);
break;
case "editortutorial":
GameMain.EditMapScreen.Select();
GameMain.EditMapScreen.StartTutorial();
break;
case "lobbyscreen":
case "lobby":
GameMain.LobbyScreen.Select();
break;
case "savemap":
case "savesub":
case "save":
if (commands.Length < 2) break;
if (GameMain.EditMapScreen.CharacterMode)
{
GameMain.EditMapScreen.ToggleCharacterMode();
}
string fileName = string.Join(" ", commands.Skip(1));
if (fileName.Contains("../"))
{
DebugConsole.ThrowError("Illegal symbols in filename (../)");
return true;
}
if (Submarine.SaveCurrent(System.IO.Path.Combine(Submarine.SavePath, fileName + ".sub")))
{
NewMessage("Sub saved", Color.Green);
//Submarine.Loaded.First().CheckForErrors();
}
break;
case "loadmap":
case "loadsub":
case "load":
if (commands.Length < 2) break;
Submarine.Load(string.Join(" ", commands.Skip(1)), true);
break;
case "cleansub":
for (int i = MapEntity.mapEntityList.Count - 1; i >= 0; i--)
{
MapEntity me = MapEntity.mapEntityList[i];
if (me.SimPosition.Length() > 2000.0f)
{
DebugConsole.NewMessage("Removed " + me.Name + " (simposition " + me.SimPosition + ")", Color.Orange);
MapEntity.mapEntityList.RemoveAt(i);
}
else if (me.MoveWithLevel)
{
DebugConsole.NewMessage("Removed " + me.Name + " (MoveWithLevel==true)", Color.Orange);
MapEntity.mapEntityList.RemoveAt(i);
}
else if (me is Item)
{
Item item = me as Item;
var wire = item.GetComponent<Wire>();
if (wire == null) continue;
if (wire.GetNodes().Count > 0 && !wire.Connections.Any(c => c != null))
{
wire.Item.Drop(null);
DebugConsole.NewMessage("Dropped wire (ID: " + wire.Item.ID + ") - attached on wall but no connections found", Color.Orange);
}
}
}
break;
case "messagebox":
if (commands.Length < 3) break;
new GUIMessageBox(commands[1], commands[2]);
break;
case "debugdraw":
GameMain.DebugDraw = !GameMain.DebugDraw;
break;
case "disablehud":
case "hud":
GUI.DisableHUD = !GUI.DisableHUD;
GameMain.Instance.IsMouseVisible = !GameMain.Instance.IsMouseVisible;
break;
case "followsub":
Camera.FollowSub = !Camera.FollowSub;
break;
case "drawaitargets":
case "showaitargets":
AITarget.ShowAITargets = !AITarget.ShowAITargets;
break;
#if DEBUG
case "spamevents":
foreach (Item item in Item.ItemList)
{
for (int i = 0; i<item.components.Count; i++)
{
if (item.components[i] is IServerSerializable)
{
GameMain.Server.CreateEntityEvent(item, new object[] { NetEntityEvent.Type.ComponentState, i });
}
var itemContainer = item.GetComponent<ItemContainer>();
if (itemContainer != null)
{
GameMain.Server.CreateEntityEvent(item, new object[] { NetEntityEvent.Type.InventoryState });
}
GameMain.Server.CreateEntityEvent(item, new object[] { NetEntityEvent.Type.Status });
item.NeedsPositionUpdate = true;
}
}
foreach (Character c in Character.CharacterList)
{
GameMain.Server.CreateEntityEvent(c, new object[] { NetEntityEvent.Type.Status });
}
foreach (Structure wall in Structure.WallList)
{
GameMain.Server.CreateEntityEvent(wall);
}
break;
case "spamchatmessages":
int msgCount = 1000;
if (commands.Length > 1) int.TryParse(commands[1], out msgCount);
int msgLength = 50;
if (commands.Length > 2) int.TryParse(commands[2], out msgLength);
for (int i = 0; i < msgCount; i++)
{
if (GameMain.Server != null)
{
GameMain.Server.SendChatMessage(ToolBox.RandomSeed(msgLength), ChatMessageType.Default);
}
else
{
GameMain.Client.SendChatMessage(ToolBox.RandomSeed(msgLength));
}
}
break;
#endif
case "cleanbuild":
GameMain.Config.MusicVolume = 0.5f;
GameMain.Config.SoundVolume = 0.5f;
DebugConsole.NewMessage("Music and sound volume set to 0.5", Color.Green);
GameMain.Config.GraphicsWidth = 0;
GameMain.Config.GraphicsHeight = 0;
GameMain.Config.WindowMode = WindowMode.Fullscreen;
DebugConsole.NewMessage("Resolution set to 0 x 0 (screen resolution will be used)", Color.Green);
DebugConsole.NewMessage("Fullscreen enabled", Color.Green);
GameSettings.VerboseLogging = false;
if (GameMain.Config.MasterServerUrl != "http://www.undertowgames.com/baromaster")
{
DebugConsole.ThrowError("MasterServerUrl \"" + GameMain.Config.MasterServerUrl + "\"!");
}
GameMain.Config.Save("config.xml");
var saveFiles = System.IO.Directory.GetFiles(SaveUtil.SaveFolder);
foreach (string saveFile in saveFiles)
{
System.IO.File.Delete(saveFile);
DebugConsole.NewMessage("Deleted " + saveFile, Color.Green);
}
if (System.IO.Directory.Exists(System.IO.Path.Combine(SaveUtil.SaveFolder, "temp")))
{
System.IO.Directory.Delete(System.IO.Path.Combine(SaveUtil.SaveFolder, "temp"), true);
DebugConsole.NewMessage("Deleted temp save folder", Color.Green);
}
if (System.IO.Directory.Exists(ServerLog.SavePath))
{
var logFiles = System.IO.Directory.GetFiles(ServerLog.SavePath);
foreach (string logFile in logFiles)
{
System.IO.File.Delete(logFile);
DebugConsole.NewMessage("Deleted " + logFile, Color.Green);
}
}
if (System.IO.File.Exists("filelist.xml"))
{
System.IO.File.Delete("filelist.xml");
DebugConsole.NewMessage("Deleted filelist", Color.Green);
}
if (System.IO.File.Exists("Submarines/TutorialSub.sub"))
{
System.IO.File.Delete("Submarines/TutorialSub.sub");
DebugConsole.NewMessage("Deleted TutorialSub from the submarine folder", Color.Green);
}
if (System.IO.File.Exists(GameServer.SettingsFile))
{
System.IO.File.Delete(GameServer.SettingsFile);
DebugConsole.NewMessage("Deleted server settings", Color.Green);
}
if (System.IO.File.Exists(GameServer.ClientPermissionsFile))
{
System.IO.File.Delete(GameServer.ClientPermissionsFile);
DebugConsole.NewMessage("Deleted client permission file", Color.Green);
}
if (System.IO.File.Exists("crashreport.txt"))
{
System.IO.File.Delete("crashreport.txt");
DebugConsole.NewMessage("Deleted crashreport.txt", Color.Green);
}
if (!System.IO.File.Exists("Content/Map/TutorialSub.sub"))
{
DebugConsole.ThrowError("TutorialSub.sub not found!");
}
break;
default:
return false; //command not found
break;
}
return true; //command found
}
}
}

View File

@@ -0,0 +1,25 @@
using Barotrauma.Networking;
using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Xml.Linq;
namespace Barotrauma
{
partial class Mission
{
public void ShowMessage(int index)
{
if (index >= headers.Count && index >= messages.Count) return;
string header = index < headers.Count ? headers[index] : "";
string message = index < messages.Count ? messages[index] : "";
GameServer.Log("Mission info: " + header + " - " + message, ServerLog.MessageType.ServerMessage);
new GUIMessageBox(header, message);
}
}
}

View File

@@ -0,0 +1,18 @@
using Microsoft.Xna.Framework;
namespace Barotrauma
{
partial class MissionMode : GameMode
{
public override void MsgBox()
{
if (mission == null) return;
var missionMsg = new GUIMessageBox(mission.Name, mission.Description, 400, 400);
missionMsg.UserData = "missionstartmessage";
Networking.GameServer.Log("Mission: " + mission.Name, Networking.ServerLog.MessageType.ServerMessage);
Networking.GameServer.Log(mission.Description, Networking.ServerLog.MessageType.ServerMessage);
}
}
}

View File

@@ -6,15 +6,6 @@ using System.Collections.Generic;
namespace Barotrauma
{
[Flags]
public enum Alignment
{
CenterX = 1, Left = 2, Right = 4, CenterY = 8, Top = 16, Bottom = 32,
TopLeft = (Top | Left), TopCenter = (CenterX | Top), TopRight = (Top | Right),
CenterLeft = (Left | CenterY), Center = (CenterX | CenterY), CenterRight = (Right | CenterY),
BottomLeft = (Bottom | Left), BottomCenter = (CenterX | Bottom), BottomRight = (Bottom | Right),
}
public enum GUISoundType
{
Message,

View File

@@ -44,6 +44,7 @@ namespace Barotrauma
set
{
loadState = value;
DebugConsole.NewMessage("Loading: " + value.ToString() + "%",Color.Yellow);
DrawLoadingText = true;
}
}

View File

@@ -3,11 +3,11 @@ using System.Diagnostics;
using System.Reflection;
using FarseerPhysics;
using FarseerPhysics.Dynamics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Barotrauma.Networking;
using Barotrauma.Particles;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
namespace Barotrauma
@@ -106,7 +106,7 @@ namespace Barotrauma
{
GraphicsDeviceManager = new GraphicsDeviceManager(this);
Window.Title = "Barotrauma";
Instance = this;
Config = new GameSettings("config.xml");
@@ -141,6 +141,12 @@ namespace Barotrauma
GraphicsHeight = Config.GraphicsHeight;
GraphicsDeviceManager.SynchronizeWithVerticalRetrace = Config.VSyncEnabled;
//for whatever reason, window isn't centered automatically
//since MonoGame 3.6 (nuget package might be broken), so
//let's do it manually
Window.Position = new Point((GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Width - GraphicsWidth) / 2,
(GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Height - GraphicsHeight) / 2);
GraphicsDeviceManager.HardwareModeSwitch = Config.WindowMode != WindowMode.BorderlessWindowed;
GraphicsDeviceManager.IsFullScreen = Config.WindowMode == WindowMode.Fullscreen || Config.WindowMode == WindowMode.BorderlessWindowed;
@@ -192,6 +198,7 @@ namespace Barotrauma
private IEnumerable<object> Load()
{
DebugConsole.NewMessage("LOADING COROUTINE", Color.Lime);
GUI.GraphicsDevice = base.GraphicsDevice;
GUI.Init(Content);
@@ -274,6 +281,7 @@ namespace Barotrauma
TitleScreen.LoadState = 100.0f;
hasLoaded = true;
DebugConsole.NewMessage("LOADING COROUTINE FINISHED", Color.Lime);
yield return CoroutineStatus.Success;
}
@@ -365,7 +373,7 @@ namespace Barotrauma
}
GUI.Update((float)Timing.Step);
}
}
CoroutineManager.Update((float)Timing.Step, paused ? 0.0f : (float)Timing.Step);
@@ -418,6 +426,5 @@ namespace Barotrauma
base.OnExiting(sender, args);
}
}
}
}

View File

@@ -281,7 +281,7 @@ namespace Barotrauma
listBox.ClearChildren();
characters.Clear();
WayPoint[] waypoints = WayPoint.SelectCrewSpawnPoints(characterInfos, Submarine.MainSub);
WayPoint[] waypoints = WayPoint.SelectCrewSpawnPoints(characterInfos, Submarine.MainSub, false);
for (int i = 0; i < waypoints.Length; i++)
{

View File

@@ -0,0 +1,10 @@
using Microsoft.Xna.Framework.Graphics;
namespace Barotrauma
{
partial class GameMode
{
public virtual void Draw(SpriteBatch spriteBatch)
{
}
}
}

View File

@@ -0,0 +1,15 @@
using Barotrauma.Networking;
using System.Collections.Generic;
namespace Barotrauma
{
partial class TraitorManager
{
public static void CreateStartPopUp(string targetName)
{
new GUIMessageBox("You are the Traitor!",
"Your secret task is to assassinate " + targetName + "! Discretion is an utmost concern; sinking the submarine and killing the entire crew "
+ "will arouse suspicion amongst the Fleet. If possible, make the death look like an accident.", 400, 350);
}
}
}

View File

@@ -0,0 +1,197 @@
using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System.Xml.Linq;
namespace Barotrauma
{
partial class GameSession
{
private InfoFrameTab selectedTab;
private GUIButton infoButton;
private GUIFrame infoFrame;
public Map Map
{
get
{
SinglePlayerMode mode = (gameMode as SinglePlayerMode);
return (mode == null) ? null : mode.Map;
}
}
private ShiftSummary shiftSummary;
public ShiftSummary ShiftSummary
{
get { return shiftSummary; }
}
public bool LoadPrevious(GUIButton button, object obj)
{
Submarine.Unload();
SaveUtil.LoadGame(saveFile);
GameMain.LobbyScreen.Select();
return true;
}
private bool ToggleInfoFrame(GUIButton button, object obj)
{
if (infoFrame == null)
{
if (CrewManager != null && CrewManager.CrewCommander != null && CrewManager.CrewCommander.IsOpen)
{
CrewManager.CrewCommander.ToggleGUIFrame();
}
CreateInfoFrame();
SelectInfoFrameTab(null, selectedTab);
}
else
{
infoFrame = null;
}
return true;
}
public void CreateInfoFrame()
{
int width = 600, height = 400;
infoFrame = new GUIFrame(
Rectangle.Empty, Color.Black * 0.8f, null);
var innerFrame = new GUIFrame(
new Rectangle(GameMain.GraphicsWidth / 2 - width / 2, GameMain.GraphicsHeight / 2 - height / 2, width, height), "", infoFrame);
innerFrame.Padding = new Vector4(10.0f, 10.0f, 10.0f, 10.0f);
var crewButton = new GUIButton(new Rectangle(0, -30, 100, 20), "Crew", "", innerFrame);
crewButton.UserData = InfoFrameTab.Crew;
crewButton.OnClicked = SelectInfoFrameTab;
var missionButton = new GUIButton(new Rectangle(100, -30, 100, 20), "Mission", "", innerFrame);
missionButton.UserData = InfoFrameTab.Mission;
missionButton.OnClicked = SelectInfoFrameTab;
if (GameMain.Server != null)
{
var manageButton = new GUIButton(new Rectangle(200, -30, 130, 20), "Manage players", "", innerFrame);
manageButton.UserData = InfoFrameTab.ManagePlayers;
manageButton.OnClicked = SelectInfoFrameTab;
}
var closeButton = new GUIButton(new Rectangle(0, 0, 80, 20), "Close", Alignment.BottomCenter, "", innerFrame);
closeButton.OnClicked = ToggleInfoFrame;
}
private bool SelectInfoFrameTab(GUIButton button, object userData)
{
selectedTab = (InfoFrameTab)userData;
CreateInfoFrame();
switch (selectedTab)
{
case InfoFrameTab.Crew:
CrewManager.CreateCrewFrame(CrewManager.characters, infoFrame.children[0] as GUIFrame);
break;
case InfoFrameTab.Mission:
CreateMissionInfo(infoFrame.children[0] as GUIFrame);
break;
case InfoFrameTab.ManagePlayers:
GameMain.Server.ManagePlayersFrame(infoFrame.children[0] as GUIFrame);
break;
}
return true;
}
private void CreateMissionInfo(GUIFrame infoFrame)
{
if (Mission == null)
{
new GUITextBlock(new Rectangle(0, 0, 0, 50), "No mission", "", infoFrame, true);
return;
}
new GUITextBlock(new Rectangle(0, 0, 0, 40), Mission.Name, "", infoFrame, GUI.LargeFont);
new GUITextBlock(new Rectangle(0, 50, 0, 20), "Reward: " + Mission.Reward, "", infoFrame, true);
new GUITextBlock(new Rectangle(0, 70, 0, 50), Mission.Description, "", infoFrame, true);
}
public void AddToGUIUpdateList()
{
infoButton.AddToGUIUpdateList();
if (gameMode != null) gameMode.AddToGUIUpdateList();
if (infoFrame != null) infoFrame.AddToGUIUpdateList();
}
public void Update(float deltaTime)
{
TaskManager.Update(deltaTime);
if (GUI.DisableHUD) return;
//guiRoot.Update(deltaTime);
infoButton.Update(deltaTime);
if (gameMode != null) gameMode.Update(deltaTime);
if (Mission != null) Mission.Update(deltaTime);
if (infoFrame != null)
{
infoFrame.Update(deltaTime);
if (CrewManager != null && CrewManager.CrewCommander != null && CrewManager.CrewCommander.IsOpen)
{
infoFrame = null;
}
}
}
public void Draw(SpriteBatch spriteBatch)
{
if (GUI.DisableHUD) return;
infoButton.Draw(spriteBatch);
if (gameMode != null) gameMode.Draw(spriteBatch);
if (infoFrame != null) infoFrame.Draw(spriteBatch);
}
public void Save(string filePath)
{
XDocument doc = new XDocument(
new XElement("Gamesession"));
var now = DateTime.Now;
doc.Root.Add(new XAttribute("savetime", now.ToShortTimeString() + ", " + now.ToShortDateString()));
doc.Root.Add(new XAttribute("submarine", submarine == null ? "" : submarine.Name));
doc.Root.Add(new XAttribute("mapseed", Map.Seed));
((SinglePlayerMode)gameMode).Save(doc.Root);
try
{
doc.Save(filePath);
}
catch
{
DebugConsole.ThrowError("Saving gamesession to \"" + filePath + "\" failed!");
}
}
}
}

View File

@@ -14,11 +14,11 @@ namespace Barotrauma
Windowed, Fullscreen, BorderlessWindowed
}
public class GameSettings
public partial class GameSettings
{
private GUIFrame settingsFrame;
private GUIButton applyButton;
private float soundVolume, musicVolume;
private WindowMode windowMode;
@@ -28,10 +28,10 @@ namespace Barotrauma
private KeyOrMouse[] keyMapping;
private bool unsavedSettings;
public GUIFrame SettingsFrame
{
get
get
{
if (settingsFrame == null) CreateSettingsFrame();
return settingsFrame;
@@ -43,11 +43,13 @@ namespace Barotrauma
return keyMapping[(int)inputType];
}
public int GraphicsWidth { get; set; }
public int GraphicsHeight { get; set; }
public int GraphicsWidth { get; set; }
public int GraphicsHeight { get; set; }
public bool VSyncEnabled { get; set; }
public bool EnableSplashScreen { get; set; }
//public bool FullScreenEnabled { get; set; }
public WindowMode WindowMode
@@ -55,9 +57,7 @@ namespace Barotrauma
get { return windowMode; }
set { windowMode = value; }
}
public ContentPackage SelectedContentPackage { get; set; }
public List<string> JobNamePreferences
{
get { return jobNamePreferences; }
@@ -70,15 +70,7 @@ namespace Barotrauma
jobNamePreferences = value;
}
}
public string MasterServerUrl { get; set; }
public bool AutoCheckUpdates { get; set; }
public bool WasGameUpdated { get; set; }
public static bool VerboseLogging { get; set; }
public bool EnableSplashScreen { get; set; }
public bool UnsavedSettings
{
get
@@ -100,7 +92,7 @@ namespace Barotrauma
public float SoundVolume
{
get { return soundVolume; }
get { return soundVolume; }
set
{
soundVolume = MathHelper.Clamp(value, 0.0f, 1.0f);
@@ -118,24 +110,13 @@ namespace Barotrauma
}
}
public GameSettings(string filePath)
partial void InitProjSpecific(XDocument doc)
{
ContentPackage.LoadAll(ContentPackage.Folder);
Load(filePath);
}
public void Load(string filePath)
{
XDocument doc = ToolBox.TryLoadXml(filePath);
if (doc == null)
{
DebugConsole.ThrowError("No config file found");
GraphicsWidth = 1024;
GraphicsHeight = 678;
MasterServerUrl = "";
SelectedContentPackage = ContentPackage.list.Any() ? ContentPackage.list[0] : new ContentPackage("");
@@ -145,16 +126,15 @@ namespace Barotrauma
{
JobNamePreferences.Add(job.Name);
}
return;
}
XElement graphicsMode = doc.Root.Element("graphicsmode");
GraphicsWidth = ToolBox.GetAttributeInt(graphicsMode, "width", 0);
GraphicsHeight = ToolBox.GetAttributeInt(graphicsMode, "height", 0);
VSyncEnabled = ToolBox.GetAttributeBool(graphicsMode, "vsync", true);
if (GraphicsWidth==0 || GraphicsHeight==0)
if (GraphicsWidth == 0 || GraphicsHeight == 0)
{
GraphicsWidth = GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Width;
GraphicsHeight = GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Height;
@@ -168,46 +148,31 @@ namespace Barotrauma
windowMode = WindowMode.Fullscreen;
}
MasterServerUrl = ToolBox.GetAttributeString(doc.Root, "masterserverurl", "");
AutoCheckUpdates = ToolBox.GetAttributeBool(doc.Root, "autocheckupdates", true);
WasGameUpdated = ToolBox.GetAttributeBool(doc.Root, "wasgameupdated", false);
SoundVolume = ToolBox.GetAttributeFloat(doc.Root, "soundvolume", 1.0f);
MusicVolume = ToolBox.GetAttributeFloat(doc.Root, "musicvolume", 0.3f);
VerboseLogging = ToolBox.GetAttributeBool(doc.Root, "verboselogging", false);
EnableSplashScreen = ToolBox.GetAttributeBool(doc.Root, "enablesplashscreen", true);
keyMapping = new KeyOrMouse[Enum.GetNames(typeof(InputType)).Length];
keyMapping[(int)InputType.Up] = new KeyOrMouse(Keys.W);
keyMapping[(int)InputType.Down] = new KeyOrMouse(Keys.S);
keyMapping[(int)InputType.Left] = new KeyOrMouse(Keys.A);
keyMapping[(int)InputType.Right] = new KeyOrMouse(Keys.D);
keyMapping[(int)InputType.Run] = new KeyOrMouse(Keys.LeftShift);
keyMapping[(int)InputType.Up] = new KeyOrMouse(Keys.W);
keyMapping[(int)InputType.Down] = new KeyOrMouse(Keys.S);
keyMapping[(int)InputType.Left] = new KeyOrMouse(Keys.A);
keyMapping[(int)InputType.Right] = new KeyOrMouse(Keys.D);
keyMapping[(int)InputType.Run] = new KeyOrMouse(Keys.LeftShift);
keyMapping[(int)InputType.Chat] = new KeyOrMouse(Keys.Tab);
keyMapping[(int)InputType.CrewOrders] = new KeyOrMouse(Keys.C);
keyMapping[(int)InputType.Chat] = new KeyOrMouse(Keys.Tab);
keyMapping[(int)InputType.CrewOrders] = new KeyOrMouse(Keys.C);
keyMapping[(int)InputType.Select] = new KeyOrMouse(Keys.E);
keyMapping[(int)InputType.Select] = new KeyOrMouse(Keys.E);
keyMapping[(int)InputType.Use] = new KeyOrMouse(0);
keyMapping[(int)InputType.Aim] = new KeyOrMouse(1);
foreach (XElement subElement in doc.Root.Elements())
{
switch (subElement.Name.ToString().ToLowerInvariant())
{
case "contentpackage":
string path = ToolBox.GetAttributeString(subElement, "path", "");
SelectedContentPackage = ContentPackage.list.Find(cp => cp.Path == path);
if (SelectedContentPackage == null) SelectedContentPackage = new ContentPackage(path);
break;
case "keymapping":
foreach (XAttribute attribute in subElement.Attributes())
{
@@ -222,7 +187,7 @@ namespace Barotrauma
else
{
Keys key;
if (Enum.TryParse(attribute.Value.ToString(), true, out key))
if (Enum.TryParse(attribute.Value.ToString(), true, out key))
{
keyMapping[(int)inputType] = new KeyOrMouse(key);
}
@@ -241,12 +206,12 @@ namespace Barotrauma
}
foreach (InputType inputType in Enum.GetValues(typeof(InputType)))
{
if (keyMapping[(int)inputType]==null)
{
if (keyMapping[(int)inputType] == null)
{
DebugConsole.ThrowError("Key binding for the input type \"" + inputType + " not set!");
keyMapping[(int)inputType] = new KeyOrMouse(Keys.D1);
}
}
}
@@ -257,7 +222,7 @@ namespace Barotrauma
{
UnsavedSettings = false;
XDocument doc = new XDocument();
XDocument doc = new XDocument();
if (doc.Root == null)
{
@@ -275,7 +240,7 @@ namespace Barotrauma
if (WasGameUpdated)
{
doc.Root.Add(new XAttribute("wasgameupdated", true));
}
}
XElement gMode = doc.Root.Element("graphicsmode");
if (gMode == null)
@@ -284,7 +249,7 @@ namespace Barotrauma
doc.Root.Add(gMode);
}
if (GraphicsWidth==0 || GraphicsHeight==0)
if (GraphicsWidth == 0 || GraphicsHeight == 0)
{
gMode.ReplaceAttributes(new XAttribute("displaymode", windowMode));
}
@@ -300,15 +265,15 @@ namespace Barotrauma
if (SelectedContentPackage != null)
{
doc.Root.Add(new XElement("contentpackage",
doc.Root.Add(new XElement("contentpackage",
new XAttribute("path", SelectedContentPackage.Path)));
}
var keyMappingElement = new XElement("keymapping");
doc.Root.Add(keyMappingElement);
for (int i = 0; i<keyMapping.Length;i++)
doc.Root.Add(keyMappingElement);
for (int i = 0; i < keyMapping.Length; i++)
{
if (keyMapping[i].MouseButton==null)
if (keyMapping[i].MouseButton == null)
{
keyMappingElement.Add(new XAttribute(((InputType)i).ToString(), keyMapping[i].Key));
}
@@ -349,7 +314,7 @@ namespace Barotrauma
return true;
}
public void ResetSettingsFrame()
{
settingsFrame = null;
@@ -401,7 +366,7 @@ namespace Barotrauma
y += 70;
GUITickBox vsyncTickBox = new GUITickBox(new Rectangle(0, y, 20, 20), "Enable vertical sync",Alignment.CenterY | Alignment.Left,settingsFrame);
GUITickBox vsyncTickBox = new GUITickBox(new Rectangle(0, y, 20, 20), "Enable vertical sync", Alignment.CenterY | Alignment.Left, settingsFrame);
vsyncTickBox.OnSelected = (GUITickBox box) =>
{
VSyncEnabled = !VSyncEnabled;
@@ -444,10 +409,10 @@ namespace Barotrauma
new GUITextBlock(new Rectangle(x, y, 100, 20), "Controls:", "", settingsFrame);
y += 30;
var inputNames = Enum.GetNames(typeof(InputType));
for (int i = 0; i< inputNames.Length; i++)
for (int i = 0; i < inputNames.Length; i++)
{
new GUITextBlock(new Rectangle(x, y, 100, 18), inputNames[i]+": ", "", Alignment.TopLeft, Alignment.CenterLeft, settingsFrame);
var keyBox = new GUITextBox(new Rectangle(x + 100, y, 120, 18), null,null, Alignment.TopLeft, Alignment.CenterLeft, "", settingsFrame);
new GUITextBlock(new Rectangle(x, y, 100, 18), inputNames[i] + ": ", "", Alignment.TopLeft, Alignment.CenterLeft, settingsFrame);
var keyBox = new GUITextBox(new Rectangle(x + 100, y, 120, 18), null, null, Alignment.TopLeft, Alignment.CenterLeft, "", settingsFrame);
keyBox.Text = keyMapping[i].ToString();
keyBox.UserData = i;
@@ -502,7 +467,7 @@ namespace Barotrauma
{
yield return CoroutineStatus.Running;
while (keyBox.Selected && PlayerInput.GetKeyboardState.GetPressedKeys().Length==0
while (keyBox.Selected && PlayerInput.GetKeyboardState.GetPressedKeys().Length == 0
&& !PlayerInput.LeftButtonClicked() && !PlayerInput.RightButtonClicked())
{
if (Screen.Selected != GameMain.MainMenuScreen && !GUI.SettingsMenuOpen) yield return CoroutineStatus.Success;
@@ -534,7 +499,7 @@ namespace Barotrauma
{
yield return CoroutineStatus.Success;
}
keyBox.Deselect();
yield return CoroutineStatus.Success;

View File

@@ -0,0 +1,169 @@
using System;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Barotrauma.Networking;
using Lidgren.Network;
using System.Collections.Generic;
using Barotrauma.Items.Components;
namespace Barotrauma
{
partial class CharacterInventory : Inventory
{
private static Texture2D icons;
public Vector2[] SlotPositions;
private GUIButton[] useOnSelfButton;
partial void InitProjSpecific()
{
useOnSelfButton = new GUIButton[2];
if (icons == null) icons = TextureLoader.FromFile("Content/UI/inventoryIcons.png");
SlotPositions = new Vector2[limbSlots.Length];
int rectWidth = 40, rectHeight = 40;
int spacing = 10;
for (int i = 0; i < SlotPositions.Length; i++)
{
switch (i)
{
//head, torso, legs
case 0:
case 1:
case 2:
SlotPositions[i] = new Vector2(
spacing,
GameMain.GraphicsHeight - (spacing + rectHeight) * (3 - i));
break;
//lefthand, righthand
case 3:
case 4:
SlotPositions[i] = new Vector2(
spacing * 2 + rectWidth + (spacing + rectWidth) * (i - 2),
GameMain.GraphicsHeight - (spacing + rectHeight) * 3);
useOnSelfButton[i - 3] = new GUIButton(
new Rectangle((int)SlotPositions[i].X, (int)(SlotPositions[i].Y - spacing - rectHeight),
rectWidth, rectHeight), "Use", "")
{
UserData = i,
OnClicked = UseItemOnSelf
};
break;
case 5:
SlotPositions[i] = new Vector2(
spacing * 2 + rectWidth + (spacing + rectWidth) * (i - 5),
GameMain.GraphicsHeight - (spacing + rectHeight) * 3);
break;
default:
SlotPositions[i] = new Vector2(
spacing * 2 + rectWidth + (spacing + rectWidth) * ((i - 6) % 5),
GameMain.GraphicsHeight - (spacing + rectHeight) * ((i > 10) ? 2 : 1));
break;
}
}
}
private bool UseItemOnSelf(GUIButton button, object obj)
{
if (!(obj is int)) return false;
int slotIndex = (int)obj;
return UseItemOnSelf(slotIndex);
}
protected override void CreateSlots()
{
if (slots == null) slots = new InventorySlot[capacity];
int rectWidth = 40, rectHeight = 40;
Rectangle slotRect = new Rectangle(0, 0, rectWidth, rectHeight);
for (int i = 0; i < capacity; i++)
{
if (slots[i] == null) slots[i] = new InventorySlot(slotRect);
slots[i].Disabled = false;
slotRect.X = (int)(SlotPositions[i].X + DrawOffset.X);
slotRect.Y = (int)(SlotPositions[i].Y + DrawOffset.Y);
slots[i].Rect = slotRect;
slots[i].Color = limbSlots[i] == InvSlotType.Any ? Color.White * 0.2f : Color.White * 0.4f;
}
MergeSlots();
}
public void DrawOwn(SpriteBatch spriteBatch)
{
if (slots == null) CreateSlots();
Rectangle slotRect = new Rectangle(0, 0, 40, 40);
for (int i = 0; i < capacity; i++)
{
slotRect.X = (int)(SlotPositions[i].X + DrawOffset.X);
slotRect.Y = (int)(SlotPositions[i].Y + DrawOffset.Y);
if (i == 1) //head
{
spriteBatch.Draw(icons, new Vector2(slotRect.Center.X, slotRect.Center.Y),
new Rectangle(0, 0, 56, 128), Color.White * 0.7f, 0.0f,
new Vector2(28.0f, 64.0f), Vector2.One,
SpriteEffects.None, 0.1f);
}
else if (i == 3 || i == 4)
{
spriteBatch.Draw(icons, new Vector2(slotRect.Center.X, slotRect.Center.Y),
new Rectangle(92, 41 * (4 - i), 36, 40), Color.White * 0.7f, 0.0f,
new Vector2(18.0f, 20.0f), Vector2.One,
SpriteEffects.None, 0.1f);
}
else if (i == 5)
{
spriteBatch.Draw(icons, new Vector2(slotRect.Center.X, slotRect.Center.Y),
new Rectangle(57, 0, 31, 32), Color.White * 0.7f, 0.0f,
new Vector2(15.0f, 16.0f), Vector2.One,
SpriteEffects.None, 0.1f);
}
}
base.Draw(spriteBatch);
if (character == Character.Controlled)
{
for (int i = 0; i < capacity; i++)
{
if (selectedSlot != i &&
Items[i] != null && Items[i].CanUseOnSelf && character.HasSelectedItem(Items[i]))
{
useOnSelfButton[i - 3].Draw(spriteBatch);
}
}
}
if (selectedSlot > -1)
{
DrawSubInventory(spriteBatch, selectedSlot);
if (selectedSlot > -1 &&
!slots[selectedSlot].IsHighlighted &&
(draggingItem == null || draggingItem.Container != Items[selectedSlot]))
{
selectedSlot = -1;
}
}
}
}
}

View File

@@ -0,0 +1,142 @@
using Barotrauma.Lights;
using Barotrauma.Networking;
using FarseerPhysics;
using FarseerPhysics.Dynamics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml.Linq;
namespace Barotrauma.Items.Components
{
partial class Door : ItemComponent, IDrawableComponent, IServerSerializable
{
private ConvexHull convexHull;
private ConvexHull convexHull2;
private Vector2[] GetConvexHullCorners(Rectangle rect)
{
Vector2[] corners = new Vector2[4];
corners[0] = new Vector2(rect.X, rect.Y - rect.Height);
corners[1] = new Vector2(rect.X, rect.Y);
corners[2] = new Vector2(rect.Right, rect.Y);
corners[3] = new Vector2(rect.Right, rect.Y - rect.Height);
return corners;
}
private void UpdateConvexHulls()
{
doorRect = new Rectangle(
item.Rect.Center.X - (int)(doorSprite.size.X / 2),
item.Rect.Y - item.Rect.Height / 2 + (int)(doorSprite.size.Y / 2.0f),
(int)doorSprite.size.X,
(int)doorSprite.size.Y);
Rectangle rect = doorRect;
if (isHorizontal)
{
rect.Width = (int)(rect.Width * (1.0f - openState));
}
else
{
rect.Height = (int)(rect.Height * (1.0f - openState));
}
if (window.Height > 0 && window.Width > 0)
{
rect.Height = -window.Y;
rect.Y += (int)(doorRect.Height * openState);
rect.Height = Math.Max(rect.Height - (rect.Y - doorRect.Y), 0);
rect.Y = Math.Min(doorRect.Y, rect.Y);
if (convexHull2 != null)
{
Rectangle rect2 = doorRect;
rect2.Y = rect2.Y + window.Y - window.Height;
rect2.Y += (int)(doorRect.Height * openState);
rect2.Y = Math.Min(doorRect.Y, rect2.Y);
rect2.Height = rect2.Y - (doorRect.Y - (int)(doorRect.Height * (1.0f - openState)));
//convexHull2.SetVertices(GetConvexHullCorners(rect2));
if (rect2.Height == 0)
{
convexHull2.Enabled = false;
}
else
{
convexHull2.Enabled = true;
convexHull2.SetVertices(GetConvexHullCorners(rect2));
}
}
}
if (convexHull == null) return;
if (rect.Height == 0 || rect.Width == 0)
{
convexHull.Enabled = false;
}
else
{
convexHull.Enabled = true;
convexHull.SetVertices(GetConvexHullCorners(rect));
}
}
public void Draw(SpriteBatch spriteBatch, bool editing)
{
Color color = (item.IsSelected) ? Color.Green : Color.White;
color = color * (item.Condition / 100.0f);
color.A = 255;
//prefab.sprite.Draw(spriteBatch, new Vector2(rect.X, -rect.Y), new Vector2(rect.Width, rect.Height), color);
if (stuck > 0.0f && weldedSprite != null)
{
Vector2 weldSpritePos = new Vector2(item.Rect.Center.X, item.Rect.Y - item.Rect.Height / 2.0f);
if (item.Submarine != null) weldSpritePos += item.Submarine.Position;
weldSpritePos.Y = -weldSpritePos.Y;
weldedSprite.Draw(spriteBatch,
weldSpritePos, Color.White * (stuck / 100.0f), 0.0f, 1.0f);
}
if (openState == 1.0f)
{
body.Enabled = false;
return;
}
if (isHorizontal)
{
Vector2 pos = new Vector2(item.Rect.X, item.Rect.Y - item.Rect.Height / 2);
if (item.Submarine != null) pos += item.Submarine.DrawPosition;
pos.Y = -pos.Y;
spriteBatch.Draw(doorSprite.Texture, pos,
new Rectangle((int)(doorSprite.SourceRect.X + doorSprite.size.X * openState), (int)doorSprite.SourceRect.Y,
(int)(doorSprite.size.X * (1.0f - openState)), (int)doorSprite.size.Y),
color, 0.0f, doorSprite.Origin, 1.0f, SpriteEffects.None, doorSprite.Depth);
}
else
{
Vector2 pos = new Vector2(item.Rect.Center.X, item.Rect.Y);
if (item.Submarine != null) pos += item.Submarine.DrawPosition;
pos.Y = -pos.Y;
spriteBatch.Draw(doorSprite.Texture, pos,
new Rectangle(doorSprite.SourceRect.X, (int)(doorSprite.SourceRect.Y + doorSprite.size.Y * openState),
(int)doorSprite.size.X, (int)(doorSprite.size.Y * (1.0f - openState))),
color, 0.0f, doorSprite.Origin, 1.0f, SpriteEffects.None, doorSprite.Depth);
}
}
}
}

View File

@@ -0,0 +1,273 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Xml.Linq;
using Lidgren.Network;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Barotrauma.Networking;
using System.IO;
namespace Barotrauma.Items.Components
{
class ItemSound
{
public readonly Sound Sound;
public readonly ActionType Type;
public string VolumeProperty;
public float VolumeMultiplier;
public readonly float Range;
public readonly bool Loop;
public ItemSound(Sound sound, ActionType type, float range, bool loop = false)
{
this.Sound = sound;
this.Type = type;
this.Range = range;
this.Loop = loop;
}
}
partial class ItemComponent : IPropertyObject
{
private Dictionary<ActionType, List<ItemSound>> sounds;
private GUIFrame guiFrame;
protected GUIFrame GuiFrame
{
get
{
if (guiFrame == null)
{
DebugConsole.ThrowError("Error: the component " + name + " in " + item.Name + " doesn't have a GuiFrame component");
guiFrame = new GUIFrame(new Rectangle(0, 0, 100, 100), Color.Black);
}
return guiFrame;
}
}
private ItemSound loopingSound;
private int loopingSoundIndex;
public void PlaySound(ActionType type, Vector2 position)
{
if (loopingSound != null)
{
loopingSoundIndex = loopingSound.Sound.Loop(loopingSoundIndex, GetSoundVolume(loopingSound), position, loopingSound.Range);
return;
}
List<ItemSound> matchingSounds;
if (!sounds.TryGetValue(type, out matchingSounds)) return;
ItemSound itemSound = null;
if (!Sounds.SoundManager.IsPlaying(loopingSoundIndex))
{
int index = Rand.Int(matchingSounds.Count);
itemSound = matchingSounds[index];
}
if (itemSound == null) return;
if (itemSound.Loop)
{
loopingSound = itemSound;
loopingSoundIndex = loopingSound.Sound.Loop(loopingSoundIndex, GetSoundVolume(loopingSound), position, loopingSound.Range);
}
else
{
float volume = GetSoundVolume(itemSound);
if (volume == 0.0f) return;
itemSound.Sound.Play(volume, itemSound.Range, position);
}
}
public void StopSounds(ActionType type)
{
if (loopingSoundIndex <= 0) return;
if (loopingSound == null) return;
if (loopingSound.Type != type) return;
if (Sounds.SoundManager.IsPlaying(loopingSoundIndex))
{
Sounds.SoundManager.Stop(loopingSoundIndex);
loopingSound = null;
loopingSoundIndex = -1;
}
}
private float GetSoundVolume(ItemSound sound)
{
if (sound == null) return 0.0f;
if (sound.VolumeProperty == "") return 1.0f;
ObjectProperty op = null;
if (properties.TryGetValue(sound.VolumeProperty.ToLowerInvariant(), out op))
{
float newVolume = 0.0f;
try
{
newVolume = (float)op.GetValue();
}
catch
{
return 0.0f;
}
newVolume *= sound.VolumeMultiplier;
return MathHelper.Clamp(newVolume, 0.0f, 1.0f);
}
return 0.0f;
}
//public virtual void Draw(SpriteBatch spriteBatch, bool editing = false)
//{
// item.drawableComponents = Array.FindAll(item.drawableComponents, i => i != this);
//}
public virtual void DrawHUD(SpriteBatch spriteBatch, Character character) { }
public virtual void AddToGUIUpdateList() { }
public virtual void UpdateHUD(Character character) { }
private bool LoadElemProjSpecific(XElement subElement)
{
switch (subElement.Name.ToString().ToLowerInvariant())
{
case "guiframe":
string rectStr = ToolBox.GetAttributeString(subElement, "rect", "0.0,0.0,0.5,0.5");
string[] components = rectStr.Split(',');
if (components.Length < 4) break;
Vector4 rect = ToolBox.GetAttributeVector4(subElement, "rect", Vector4.One);
if (components[0].Contains(".")) rect.X *= GameMain.GraphicsWidth;
if (components[1].Contains(".")) rect.Y *= GameMain.GraphicsHeight;
if (components[2].Contains(".")) rect.Z *= GameMain.GraphicsWidth;
if (components[3].Contains(".")) rect.W *= GameMain.GraphicsHeight;
string style = ToolBox.GetAttributeString(subElement, "style", "");
Vector4 color = ToolBox.GetAttributeVector4(subElement, "color", Vector4.One);
Alignment alignment = Alignment.Center;
try
{
alignment = (Alignment)Enum.Parse(typeof(Alignment),
ToolBox.GetAttributeString(subElement, "alignment", "Center"), true);
}
catch
{
DebugConsole.ThrowError("Error in " + subElement.Parent + "! \"" + subElement.Parent.Attribute("type").Value + "\" is not a valid alignment");
}
guiFrame = new GUIFrame(
new Rectangle((int)rect.X, (int)rect.Y, (int)rect.Z, (int)rect.W),
new Color(color.X, color.Y, color.Z) * color.W,
alignment, style);
break;
case "sound":
string filePath = ToolBox.GetAttributeString(subElement, "file", "");
if (filePath == "") filePath = ToolBox.GetAttributeString(subElement, "sound", "");
if (filePath == "")
{
DebugConsole.ThrowError("Error when instantiating item \"" + item.Name + "\" - sound with no file path set");
break;
}
if (!filePath.Contains("/") && !filePath.Contains("\\") && !filePath.Contains(Path.DirectorySeparatorChar))
{
filePath = Path.Combine(Path.GetDirectoryName(item.Prefab.ConfigFile), filePath);
}
ActionType type;
try
{
type = (ActionType)Enum.Parse(typeof(ActionType), ToolBox.GetAttributeString(subElement, "type", ""), true);
}
catch (Exception e)
{
DebugConsole.ThrowError("Invalid sound type in " + subElement + "!", e);
break;
}
Sound sound = Sound.Load(filePath);
float range = ToolBox.GetAttributeFloat(subElement, "range", 800.0f);
bool loop = ToolBox.GetAttributeBool(subElement, "loop", false);
ItemSound itemSound = new ItemSound(sound, type, range, loop);
itemSound.VolumeProperty = ToolBox.GetAttributeString(subElement, "volume", "");
itemSound.VolumeMultiplier = ToolBox.GetAttributeFloat(subElement, "volumemultiplier", 1.0f);
List<ItemSound> soundList = null;
if (!sounds.TryGetValue(itemSound.Type, out soundList))
{
soundList = new List<ItemSound>();
sounds.Add(itemSound.Type, soundList);
}
soundList.Add(itemSound);
break;
default:
return false; //unknown element
}
return true; //element processed
}
//Starts a coroutine that will read the correct state of the component from the NetBuffer when correctionTimer reaches zero.
protected void StartDelayedCorrection(ServerNetObject type, NetBuffer buffer, float sendingTime)
{
if (delayedCorrectionCoroutine != null) CoroutineManager.StopCoroutines(delayedCorrectionCoroutine);
delayedCorrectionCoroutine = CoroutineManager.StartCoroutine(DoDelayedCorrection(type, buffer, sendingTime));
}
private IEnumerable<object> DoDelayedCorrection(ServerNetObject type, NetBuffer buffer, float sendingTime)
{
while (correctionTimer > 0.0f)
{
correctionTimer -= CoroutineManager.DeltaTime;
yield return CoroutineStatus.Running;
}
((IServerSerializable)this).ClientRead(type, buffer, sendingTime);
correctionTimer = 0.0f;
delayedCorrectionCoroutine = null;
yield return CoroutineStatus.Success;
}
public virtual XElement Save(XElement parentElement)
{
XElement componentElement = new XElement(name);
foreach (RelatedItem ri in requiredItems)
{
XElement newElement = new XElement("requireditem");
ri.Save(newElement);
componentElement.Add(newElement);
}
ObjectProperty.SaveProperties(this, componentElement);
parentElement.Add(componentElement);
return componentElement;
}
}
}

View File

@@ -0,0 +1,87 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using FarseerPhysics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace Barotrauma.Items.Components
{
partial class ItemContainer : ItemComponent, IDrawableComponent
{
//TODO: shouldn't this be overriding the base method?
public void Draw(SpriteBatch spriteBatch, bool editing = false)
{
if (hideItems || (item.body != null && !item.body.Enabled)) return;
Vector2 transformedItemPos = itemPos;
Vector2 transformedItemInterval = itemInterval;
float currentRotation = itemRotation;
if (item.body == null)
{
transformedItemPos = new Vector2(item.Rect.X, item.Rect.Y);
if (item.Submarine != null) transformedItemPos += item.Submarine.DrawPosition;
transformedItemPos = transformedItemPos + itemPos;
}
else
{
//item.body.Enabled = true;
Matrix transform = Matrix.CreateRotationZ(item.body.Rotation);
if (item.body.Dir == -1.0f)
{
transformedItemPos.X = -transformedItemPos.X;
transformedItemInterval.X = -transformedItemInterval.X;
}
transformedItemPos = Vector2.Transform(transformedItemPos, transform);
transformedItemInterval = Vector2.Transform(transformedItemInterval, transform);
transformedItemPos += item.DrawPosition;
currentRotation += item.body.Rotation;
}
foreach (Item containedItem in Inventory.Items)
{
if (containedItem == null) continue;
containedItem.Sprite.Draw(
spriteBatch,
new Vector2(transformedItemPos.X, -transformedItemPos.Y),
-currentRotation,
1.0f,
(item.body != null && item.body.Dir == -1) ? SpriteEffects.FlipHorizontally : SpriteEffects.None);
transformedItemPos += transformedItemInterval;
}
}
public override void UpdateHUD(Character character)
{
Inventory.Update((float)Timing.Step);
}
public override void DrawHUD(SpriteBatch spriteBatch, Character character)
{
Inventory.Draw(spriteBatch);
}
public override XElement Save(XElement parentElement)
{
XElement componentElement = base.Save(parentElement);
string[] itemIdStrings = new string[Inventory.Items.Length];
for (int i = 0; i < Inventory.Items.Length; i++)
{
itemIdStrings[i] = (Inventory.Items[i] == null) ? "0" : Inventory.Items[i].ID.ToString();
}
componentElement.Add(new XAttribute("contained", string.Join(",", itemIdStrings)));
return componentElement;
}
}
}

View File

@@ -1,21 +1,24 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System.Xml.Linq;
namespace Barotrauma.Items.Components
{
class ItemLabel : ItemComponent, IDrawableComponent
partial class ItemLabel : ItemComponent, IDrawableComponent
{
private GUITextBlock textBlock;
private Color textColor;
[HasDefaultValue("", true), Editable(100)]
public string Text
{
get { return textBlock.Text.Replace("\n", ""); }
set
set
{
if (value == TextBlock.Text || item.Rect.Width < 5) return;
if (textBlock.Rect.Width != item.Rect.Width || textBlock.Rect.Height != item.Rect.Height)
if (textBlock.Rect.Width != item.Rect.Width || textBlock.Rect.Height != item.Rect.Height)
{
textBlock = null;
}
@@ -24,7 +27,6 @@ namespace Barotrauma.Items.Components
}
}
private Color textColor;
[Editable, HasDefaultValue("0.0,0.0,0.0,1.0", true)]
public string TextColor
{
@@ -35,7 +37,7 @@ namespace Barotrauma.Items.Components
if (textBlock != null) textBlock.TextColor = textColor;
}
}
[Editable, HasDefaultValue(1.0f, true)]
public float TextScale
{
@@ -48,23 +50,23 @@ namespace Barotrauma.Items.Components
private GUITextBlock TextBlock
{
get
{
get
{
if (textBlock == null)
{
textBlock = new GUITextBlock(new Rectangle(item.Rect.X,-item.Rect.Y,item.Rect.Width, item.Rect.Height), "",
Color.Transparent, textColor,
Alignment.TopLeft, Alignment.Center,
textBlock = new GUITextBlock(new Rectangle(item.Rect.X, -item.Rect.Y, item.Rect.Width, item.Rect.Height), "",
Color.Transparent, textColor,
Alignment.TopLeft, Alignment.Center,
null, null, true);
textBlock.Font = GUI.SmallFont;
textBlock.Padding = new Vector4(5.0f, 5.0f, 5.0f, 5.0f);
textBlock.TextDepth = item.Sprite.Depth - 0.0001f;
textBlock.TextScale = TextScale;
}
return textBlock;
return textBlock;
}
}
public override void Move(Vector2 amount)
{
textBlock.Rect = new Rectangle(item.Rect.X, -item.Rect.Y, item.Rect.Width, item.Rect.Height);
@@ -74,14 +76,14 @@ namespace Barotrauma.Items.Components
: base(item, element)
{
}
public void Draw(SpriteBatch spriteBatch, bool editing = false)
{
var drawPos = new Vector2(
item.DrawPosition.X - item.Rect.Width/2.0f,
-(item.DrawPosition.Y + item.Rect.Height/2.0f));
item.DrawPosition.X - item.Rect.Width / 2.0f,
-(item.DrawPosition.Y + item.Rect.Height / 2.0f));
textBlock.Draw(spriteBatch, drawPos - textBlock.Rect.Location.ToVector2());
}
}
}
}

View File

@@ -0,0 +1,27 @@
using Microsoft.Xna.Framework;
using Barotrauma.Lights;
using System;
using System.Xml.Linq;
using Barotrauma.Networking;
using Lidgren.Network;
namespace Barotrauma.Items.Components
{
partial class LightComponent : Powered, IServerSerializable, IDrawableComponent
{
private LightSource light;
public void Draw(Microsoft.Xna.Framework.Graphics.SpriteBatch spriteBatch, bool editing = false)
{
if (light.LightSprite != null && (item.body == null || item.body.Enabled))
{
light.LightSprite.Draw(spriteBatch, new Vector2(item.DrawPosition.X, -item.DrawPosition.Y), lightColor * lightBrightness, 0.0f, 1.0f, Microsoft.Xna.Framework.Graphics.SpriteEffects.None, item.Sprite.Depth - 0.0001f);
}
}
public void ClientRead(ServerNetObject type, NetBuffer msg, float sendingTime)
{
IsOn = msg.ReadBoolean();
}
}
}

View File

@@ -0,0 +1,61 @@
using Barotrauma.Networking;
using Lidgren.Network;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
namespace Barotrauma.Items.Components
{
partial class Deconstructor : Powered, IServerSerializable, IClientSerializable
{
GUIProgressBar progressBar;
GUIButton activateButton;
public override void DrawHUD(SpriteBatch spriteBatch, Character character)
{
GuiFrame.Draw(spriteBatch);
}
public override void AddToGUIUpdateList()
{
GuiFrame.AddToGUIUpdateList();
}
public override void UpdateHUD(Character character)
{
GuiFrame.Update((float)Timing.Step);
}
private bool ToggleActive(GUIButton button, object obj)
{
SetActive(!IsActive, Character.Controlled);
currPowerConsumption = IsActive ? powerConsumption : 0.0f;
if (GameMain.Server != null)
{
item.CreateServerEvent(this);
}
else if (GameMain.Client != null)
{
item.CreateClientEvent(this);
}
return true;
}
public void ClientWrite(NetBuffer msg, object[] extraData = null)
{
msg.Write(IsActive);
}
public void ClientRead(ServerNetObject type, NetBuffer msg, float sendingTime)
{
SetActive(msg.ReadBoolean());
}
}
}

View File

@@ -0,0 +1,38 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Xml.Linq;
namespace Barotrauma.Items.Components
{
partial class Engine : Powered
{
public override void DrawHUD(SpriteBatch spriteBatch, Character character)
{
//isActive = true;
GuiFrame.Draw(spriteBatch);
//int width = 300, height = 300;
//int x = Game1.GraphicsWidth / 2 - width / 2;
//int y = Game1.GraphicsHeight / 2 - height / 2 - 50;
//GUI.DrawRectangle(spriteBatch, new Rectangle(x, y, width, height), Color.Black, true);
GUI.Font.DrawString(spriteBatch, "Force: " + (int)(targetForce) + " %", new Vector2(GuiFrame.Rect.X + 30, GuiFrame.Rect.Y + 30), Color.White);
}
public override void AddToGUIUpdateList()
{
GuiFrame.AddToGUIUpdateList();
}
public override void UpdateHUD(Character character)
{
GuiFrame.Update(1.0f / 60.0f);
}
}
}

View File

@@ -0,0 +1,243 @@
using Barotrauma.Networking;
using Lidgren.Network;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
namespace Barotrauma.Items.Components
{
partial class Fabricator : Powered, IServerSerializable, IClientSerializable
{
private GUIListBox itemList;
private GUIFrame selectedItemFrame;
private GUIProgressBar progressBar;
private GUIButton activateButton;
partial void InitProjSpecific()
{
GuiFrame.Padding = new Vector4(20.0f, 20.0f, 20.0f, 20.0f);
itemList = new GUIListBox(new Rectangle(0, 0, GuiFrame.Rect.Width / 2 - 20, 0), "", GuiFrame);
itemList.OnSelected = SelectItem;
foreach (FabricableItem fi in fabricableItems)
{
GUIFrame frame = new GUIFrame(new Rectangle(0, 0, 0, 50), Color.Transparent, null, itemList)
{
UserData = fi,
Padding = new Vector4(5.0f, 5.0f, 5.0f, 5.0f),
HoverColor = Color.Gold * 0.2f,
SelectedColor = Color.Gold * 0.5f,
ToolTip = fi.TargetItem.Description
};
GUITextBlock textBlock = new GUITextBlock(
new Rectangle(40, 0, 0, 25),
fi.TargetItem.Name,
Color.Transparent, Color.White,
Alignment.Left, Alignment.Left,
null, frame);
textBlock.ToolTip = fi.TargetItem.Description;
textBlock.Padding = new Vector4(5.0f, 0.0f, 5.0f, 0.0f);
if (fi.TargetItem.sprite != null)
{
GUIImage img = new GUIImage(new Rectangle(0, 0, 40, 40), fi.TargetItem.sprite, Alignment.Left, frame);
img.Scale = Math.Min(Math.Min(40.0f / img.SourceRect.Width, 40.0f / img.SourceRect.Height), 1.0f);
img.Color = fi.TargetItem.SpriteColor;
img.ToolTip = fi.TargetItem.Description;
}
}
}
private bool SelectItem(GUIComponent component, object obj)
{
FabricableItem targetItem = obj as FabricableItem;
if (targetItem == null) return false;
if (selectedItemFrame != null) GuiFrame.RemoveChild(selectedItemFrame);
//int width = 200, height = 150;
selectedItemFrame = new GUIFrame(new Rectangle(0, 0, (int)(GuiFrame.Rect.Width * 0.4f), 300), Color.Black * 0.8f, Alignment.CenterY | Alignment.Right, null, GuiFrame);
selectedItemFrame.Padding = new Vector4(10.0f, 10.0f, 10.0f, 10.0f);
progressBar = new GUIProgressBar(new Rectangle(0, 0, 0, 20), Color.Green, "", 0.0f, Alignment.BottomCenter, selectedItemFrame);
progressBar.IsHorizontal = true;
if (targetItem.TargetItem.sprite != null)
{
int y = 0;
GUIImage img = new GUIImage(new Rectangle(10, 0, 40, 40), targetItem.TargetItem.sprite, Alignment.TopLeft, selectedItemFrame);
img.Scale = Math.Min(Math.Min(40.0f / img.SourceRect.Width, 40.0f / img.SourceRect.Height), 1.0f);
img.Color = targetItem.TargetItem.SpriteColor;
new GUITextBlock(
new Rectangle(60, 0, 0, 25),
targetItem.TargetItem.Name,
Color.Transparent, Color.White,
Alignment.TopLeft,
Alignment.TopLeft, null,
selectedItemFrame, true);
y += 40;
if (!string.IsNullOrWhiteSpace(targetItem.TargetItem.Description))
{
var description = new GUITextBlock(
new Rectangle(0, y, 0, 0),
targetItem.TargetItem.Description,
"", Alignment.TopLeft, Alignment.TopLeft,
selectedItemFrame, true, GUI.SmallFont);
y += description.Rect.Height + 10;
}
List<Skill> inadequateSkills = new List<Skill>();
if (Character.Controlled != null)
{
inadequateSkills = targetItem.RequiredSkills.FindAll(skill => Character.Controlled.GetSkillLevel(skill.Name) < skill.Level);
}
Color textColor = Color.White;
string text;
if (!inadequateSkills.Any())
{
text = "Required items:\n";
foreach (Tuple<ItemPrefab, int> ip in targetItem.RequiredItems)
{
text += " - " + ip.Item1.Name + " x" + ip.Item2 + "\n";
}
text += "Required time: " + targetItem.RequiredTime + " s";
}
else
{
text = "Skills required to calibrate:\n";
foreach (Skill skill in inadequateSkills)
{
text += " - " + skill.Name + " lvl " + skill.Level + "\n";
}
textColor = Color.Red;
}
new GUITextBlock(
new Rectangle(0, y, 0, 25),
text,
Color.Transparent, textColor,
Alignment.TopLeft,
Alignment.TopLeft, null,
selectedItemFrame);
activateButton = new GUIButton(new Rectangle(0, -30, 100, 20), "Create", Color.White, Alignment.CenterX | Alignment.Bottom, "", selectedItemFrame);
activateButton.OnClicked = StartButtonClicked;
activateButton.UserData = targetItem;
activateButton.Enabled = false;
}
return true;
}
private bool StartButtonClicked(GUIButton button, object obj)
{
if (fabricatedItem == null)
{
StartFabricating(obj as FabricableItem, Character.Controlled);
}
else
{
CancelFabricating(Character.Controlled);
}
if (GameMain.Server != null)
{
item.CreateServerEvent(this);
}
else if (GameMain.Client != null)
{
item.CreateClientEvent(this);
}
return true;
}
public override void DrawHUD(SpriteBatch spriteBatch, Character character)
{
GuiFrame.Draw(spriteBatch);
}
public override void AddToGUIUpdateList()
{
GuiFrame.AddToGUIUpdateList();
}
public override void UpdateHUD(Character character)
{
FabricableItem targetItem = itemList.SelectedData as FabricableItem;
if (targetItem != null)
{
activateButton.Enabled = CanBeFabricated(targetItem, character);
}
if (character != null)
{
bool itemsChanged = false;
if (prevContainedItems == null)
{
itemsChanged = true;
}
else
{
var itemContainer = item.GetComponent<ItemContainer>();
for (int i = 0; i < itemContainer.Inventory.Items.Length; i++)
{
if (prevContainedItems[i] != itemContainer.Inventory.Items[i])
{
itemsChanged = true;
break;
}
}
}
if (itemsChanged) CheckFabricableItems(character);
}
GuiFrame.Update((float)Timing.Step);
}
public void ClientWrite(NetBuffer msg, object[] extraData = null)
{
int itemIndex = fabricatedItem == null ? -1 : fabricableItems.IndexOf(fabricatedItem);
msg.WriteRangedInteger(-1, fabricableItems.Count - 1, itemIndex);
}
public void ClientRead(ServerNetObject type, NetBuffer msg, float sendingTime)
{
int itemIndex = msg.ReadRangedInteger(-1, fabricableItems.Count - 1);
if (itemIndex == -1)
{
CancelFabricating();
}
else
{
//if already fabricating the selected item, return
if (fabricatedItem != null && fabricableItems.IndexOf(fabricatedItem) == itemIndex) return;
if (itemIndex < 0 || itemIndex >= fabricableItems.Count) return;
SelectItem(null, fabricableItems[itemIndex]);
StartFabricating(fabricableItems[itemIndex]);
}
}
}
}

View File

@@ -7,76 +7,8 @@ using System.Linq;
namespace Barotrauma.Items.Components
{
class MiniMap : Powered
partial class MiniMap : Powered
{
class HullData
{
public float? Oxygen;
public float? Water;
}
private DateTime resetDataTime;
bool hasPower;
[Editable, HasDefaultValue(false, true)]
public bool RequireWaterDetectors
{
get;
set;
}
[Editable, HasDefaultValue(true, true)]
public bool RequireOxygenDetectors
{
get;
set;
}
[Editable, HasDefaultValue(false, true)]
public bool ShowHullIntegrity
{
get;
set;
}
private Dictionary<Hull, HullData> hullDatas;
public MiniMap(Item item, XElement element)
: base(item, element)
{
IsActive = true;
hullDatas = new Dictionary<Hull, HullData>();
}
public override void Update(float deltaTime, Camera cam)
{
//periodically reset all hull data
//(so that outdated hull info won't be shown if detectors stop sending signals)
if (DateTime.Now > resetDataTime)
{
hullDatas.Clear();
resetDataTime = DateTime.Now + new TimeSpan(0, 0, 1);
}
currPowerConsumption = powerConsumption;
hasPower = voltage > minVoltage;
voltage = 0.0f;
}
public override bool Pick(Character picker)
{
if (picker == null) return false;
//picker.SelectedConstruction = item;
return true;
}
public override void DrawHUD(SpriteBatch spriteBatch, Character character)
{
if (item.Submarine == null) return;
@@ -97,7 +29,7 @@ namespace Barotrauma.Items.Components
Point topLeft = new Point(
miniMap.X + (int)((hull.Rect.X - item.Submarine.HiddenSubPosition.X - item.Submarine.Borders.X) * size),
miniMap.Y - (int)((hull.Rect.Y - item.Submarine.HiddenSubPosition.Y - item.Submarine.Borders.Y) * size));
Point bottomRight = new Point(
topLeft.X + (int)(hull.Rect.Width * size),
topLeft.Y + (int)(hull.Rect.Height * size));
@@ -112,7 +44,7 @@ namespace Barotrauma.Items.Components
HullData hullData;
hullDatas.TryGetValue(hull, out hullData);
Color borderColor = Color.Green;
@@ -154,9 +86,9 @@ namespace Barotrauma.Items.Components
if (hullRect.Height * waterAmount > 3.0f)
{
Rectangle waterRect = new Rectangle(
hullRect.X,
hullRect.X,
(int)(hullRect.Y + hullRect.Height * (1.0f - waterAmount)),
hullRect.Width,
hullRect.Width,
(int)(hullRect.Height * waterAmount));
waterRect.Inflate(-3, -3);
@@ -174,7 +106,7 @@ namespace Barotrauma.Items.Components
{
GUI.DrawString(spriteBatch,
new Vector2(x + 10, y + height - 60),
"Hull breach", Color.Red, Color.Black * 0.5f, 2, GUI.SmallFont);
"Hull breach", Color.Red, Color.Black * 0.5f, 2, GUI.SmallFont);
}
GUI.DrawString(spriteBatch,
@@ -189,51 +121,9 @@ namespace Barotrauma.Items.Components
waterAmount == null ? Color.Red : Color.Lerp(Color.LightGreen, Color.Red, (float)waterAmount),
Color.Black * 0.5f, 2, GUI.SmallFont);
}
GUI.DrawRectangle(spriteBatch, hullRect, borderColor, false, 0.0f, 2);
}
}
public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power = 0)
{
base.ReceiveSignal(stepsTaken, signal, connection, source, sender, power);
if (sender == null || sender.CurrentHull == null) return;
Hull senderHull = sender.CurrentHull;
HullData hullData;
if (!hullDatas.TryGetValue(senderHull, out hullData))
{
hullData = new HullData();
hullDatas.Add(senderHull, hullData);
}
switch (connection.Name)
{
case "water_data_in":
//cheating a bit because water detectors don't actually send the water level
if (source.GetComponent<WaterDetector>() == null)
{
hullData.Water = Rand.Range(0.0f, 1.0f);
}
else
{
hullData.Water = Math.Min(senderHull.Volume / senderHull.FullVolume, 1.0f);
}
break;
case "oxygen_data_in":
float oxy;
if (!float.TryParse(signal, System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture, out oxy))
{
oxy = Rand.Range(0.0f, 100.0f);
}
hullData.Oxygen = oxy;
break;
}
}
}
}

View File

@@ -0,0 +1,117 @@
using Barotrauma.Networking;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.Collections.Specialized;
using System.Globalization;
using System.Xml.Linq;
namespace Barotrauma.Items.Components
{
partial class Pump : Powered, IServerSerializable, IClientSerializable
{
private GUITickBox isActiveTickBox;
partial void InitProjSpecific()
{
isActiveTickBox = new GUITickBox(new Rectangle(0, 0, 20, 20), "Running", Alignment.TopLeft, GuiFrame);
isActiveTickBox.OnSelected = (GUITickBox box) =>
{
targetLevel = null;
IsActive = !IsActive;
if (!IsActive) currPowerConsumption = 0.0f;
if (GameMain.Server != null)
{
item.CreateServerEvent(this);
GameServer.Log(Character.Controlled + (IsActive ? " turned on " : " turned off ") + item.Name, ServerLog.MessageType.ItemInteraction);
}
else if (GameMain.Client != null)
{
correctionTimer = CorrectionDelay;
item.CreateClientEvent(this);
}
return true;
};
var button = new GUIButton(new Rectangle(160, 40, 35, 30), "OUT", "", GuiFrame);
button.OnClicked = (GUIButton btn, object obj) =>
{
FlowPercentage -= 10.0f;
if (GameMain.Server != null)
{
item.CreateServerEvent(this);
GameServer.Log(Character.Controlled + " set the pumping speed of " + item.Name + " to " + (int)(flowPercentage) + " %", ServerLog.MessageType.ItemInteraction);
}
else if (GameMain.Client != null)
{
correctionTimer = CorrectionDelay;
item.CreateClientEvent(this);
}
return true;
};
button = new GUIButton(new Rectangle(210, 40, 35, 30), "IN", "", GuiFrame);
button.OnClicked = (GUIButton btn, object obj) =>
{
FlowPercentage += 10.0f;
if (GameMain.Server != null)
{
item.CreateServerEvent(this);
GameServer.Log(Character.Controlled + " set the pumping speed of " + item.Name + " to " + (int)(flowPercentage) + " %", ServerLog.MessageType.ItemInteraction);
}
else if (GameMain.Client != null)
{
correctionTimer = CorrectionDelay;
item.CreateClientEvent(this);
}
return true;
};
}
public override void DrawHUD(SpriteBatch spriteBatch, Character character)
{
int x = GuiFrame.Rect.X;
int y = GuiFrame.Rect.Y;
GuiFrame.Draw(spriteBatch);
GUI.Font.DrawString(spriteBatch, "Pumping speed: " + (int)flowPercentage + " %", new Vector2(x + 40, y + 85), Color.White);
}
public override void AddToGUIUpdateList()
{
GuiFrame.AddToGUIUpdateList();
}
public override void UpdateHUD(Character character)
{
GuiFrame.Update(1.0f / 60.0f);
}
public void ClientWrite(Lidgren.Network.NetBuffer msg, object[] extraData = null)
{
//flowpercentage can only be adjusted at 10% intervals -> no need for more accuracy than this
msg.WriteRangedInteger(-10, 10, (int)(flowPercentage / 10.0f));
msg.Write(IsActive);
}
public void ClientRead(ServerNetObject type, Lidgren.Network.NetBuffer msg, float sendingTime)
{
if (correctionTimer > 0.0f)
{
StartDelayedCorrection(type, msg.ExtractBits(5 + 1), sendingTime);
return;
}
FlowPercentage = msg.ReadRangedInteger(-10, 10) * 10.0f;
IsActive = msg.ReadBoolean();
}
}
}

View File

@@ -9,130 +9,11 @@ using Voronoi2;
namespace Barotrauma.Items.Components
{
class Radar : Powered, IServerSerializable, IClientSerializable
partial class Radar : Powered, IServerSerializable, IClientSerializable
{
private float range;
private float pingState;
private readonly Sprite pingCircle, screenOverlay;
private readonly Sprite radarBlip;
private GUITickBox isActiveTickBox;
private List<RadarBlip> radarBlips;
private float prevPingRadius;
float prevPassivePingRadius;
private Vector2 center;
private float displayRadius;
private float displayScale;
private float displayBorderSize;
[HasDefaultValue(10000.0f, false)]
public float Range
{
get { return range; }
set { range = MathHelper.Clamp(value, 0.0f, 100000.0f); }
}
[HasDefaultValue(false, false)]
public bool DetectSubmarineWalls
{
get;
set;
}
public override bool IsActive
{
get
{
return base.IsActive;
}
set
{
base.IsActive = value;
if (isActiveTickBox != null) isActiveTickBox.Selected = value;
}
}
public Radar(Item item, XElement element)
: base(item, element)
{
radarBlips = new List<RadarBlip>();
displayBorderSize = ToolBox.GetAttributeFloat(element, "displaybordersize", 0.0f);
foreach (XElement subElement in element.Elements())
{
switch (subElement.Name.ToString().ToLowerInvariant())
{
case "pingcircle":
pingCircle = new Sprite(subElement);
break;
case "screenoverlay":
screenOverlay = new Sprite(subElement);
break;
case "blip":
radarBlip = new Sprite(subElement);
break;
}
}
isActiveTickBox = new GUITickBox(new Rectangle(0, 0, 20, 20), "Active Sonar", Alignment.TopLeft, GuiFrame);
isActiveTickBox.OnSelected = (GUITickBox box) =>
{
if (GameMain.Server != null)
{
item.CreateServerEvent(this);
}
else if (GameMain.Client != null)
{
item.CreateClientEvent(this);
correctionTimer = CorrectionDelay;
}
IsActive = box.Selected;
return true;
};
GuiFrame.CanBeFocused = false;
IsActive = false;
}
public override void Update(float deltaTime, Camera cam)
{
currPowerConsumption = powerConsumption;
base.Update(deltaTime, cam);
if (voltage >= minVoltage || powerConsumption <= 0.0f)
{
pingState = pingState + deltaTime * 0.5f;
if (pingState > 1.0f)
{
if (item.CurrentHull != null) item.CurrentHull.AiTarget.SoundRange = Math.Max(Range * pingState, item.CurrentHull.AiTarget.SoundRange);
item.Use(deltaTime);
pingState = 0.0f;
}
}
else
{
pingState = 0.0f;
}
Voltage -= deltaTime;
}
public override bool Use(float deltaTime, Character character = null)
{
return pingState > 1.0f;
}
public override void AddToGUIUpdateList()
{
@@ -142,13 +23,13 @@ namespace Barotrauma.Items.Components
public override void UpdateHUD(Character character)
{
GuiFrame.Update((float)Timing.Step);
for (int i = radarBlips.Count - 1; i >= 0; i--)
{
radarBlips[i].FadeTimer -= (float)Timing.Step * 0.5f;
if (radarBlips[i].FadeTimer <= 0.0f) radarBlips.RemoveAt(i);
}
if (IsActive)
{
float pingRadius = displayRadius * pingState;
@@ -162,11 +43,11 @@ namespace Barotrauma.Items.Components
foreach (AITarget t in AITarget.List)
{
if (t.SoundRange <= 0.0f) continue;
if (Vector2.Distance(t.WorldPosition, item.WorldPosition) < t.SoundRange)
{
Ping(t.WorldPosition, t.SoundRange * passivePingRadius * 0.2f, t.SoundRange * prevPassivePingRadius * 0.2f, displayScale, t.SoundRange, 0.5f);
radarBlips.Add(new RadarBlip(t.WorldPosition, 1.0f));
}
}
@@ -178,11 +59,11 @@ namespace Barotrauma.Items.Components
public override void DrawHUD(SpriteBatch spriteBatch, Character character)
{
GuiFrame.Draw(spriteBatch);
int radius = GuiFrame.Rect.Height / 2 - 10;
DrawRadar(spriteBatch, new Rectangle((int)GuiFrame.Center.X - radius, (int)GuiFrame.Center.Y - radius, radius * 2, radius * 2));
}
private void DrawRadar(SpriteBatch spriteBatch, Rectangle rect)
{
center = new Vector2(rect.X + rect.Width * 0.5f, rect.Center.Y);
@@ -191,9 +72,9 @@ namespace Barotrauma.Items.Components
if (IsActive)
{
pingCircle.Draw(spriteBatch, center, Color.White * (1.0f - pingState), 0.0f, (displayRadius*2 / pingCircle.size.X) * pingState);
pingCircle.Draw(spriteBatch, center, Color.White * (1.0f - pingState), 0.0f, (displayRadius * 2 / pingCircle.size.X) * pingState);
}
if (item.Submarine != null && !DetectSubmarineWalls)
{
float simScale = displayScale * Physics.DisplayToSimRation;
@@ -239,7 +120,7 @@ namespace Barotrauma.Items.Components
{
screenOverlay.Draw(spriteBatch, center, 0.0f, rect.Width / screenOverlay.size.X);
}
if (GameMain.GameSession == null) return;
DrawMarker(spriteBatch,
@@ -267,7 +148,7 @@ namespace Barotrauma.Items.Components
if (!sub.OnRadar) continue;
if (item.Submarine == sub || sub.DockedTo.Contains(item.Submarine)) continue;
if (sub.WorldPosition.Y > Level.Loaded.Size.Y) continue;
DrawMarker(spriteBatch, sub.Name, sub.WorldPosition - item.WorldPosition, displayScale, center, (rect.Width * 0.45f));
}
@@ -297,6 +178,7 @@ namespace Barotrauma.Items.Components
}
}
private void Ping(Vector2 pingSource, float pingRadius, float prevPingRadius, float displayScale, float range, float pingStrength = 1.0f)
{
foreach (Submarine submarine in Submarine.Loaded)
@@ -409,8 +291,8 @@ namespace Barotrauma.Items.Components
Vector2 lineDir = (point2 - point1) / length;
range *= displayScale;
for (float x = 0; x < length; x += lineStep*Rand.Range(0.8f,1.2f))
for (float x = 0; x < length; x += lineStep * Rand.Range(0.8f, 1.2f))
{
Vector2 point = point1 + lineDir * x;
//point += cell.Translation;
@@ -419,7 +301,7 @@ namespace Barotrauma.Items.Components
if (pointDist > displayRadius) continue;
if (pointDist < prevPingRadius || pointDist > pingRadius) continue;
float alpha = pingStrength * Rand.Range(1.5f, 2.0f);
for (float z = 0; z < displayRadius - pointDist * displayScale; z += zStep)
{
@@ -442,7 +324,7 @@ namespace Barotrauma.Items.Components
{
alpha -= 0.1f;
}
if (alpha < 0) break;
}
@@ -461,8 +343,8 @@ namespace Barotrauma.Items.Components
new Color(255, 255, 255) };
float scaledT = strength * (colors.Length - 1);
Color color = Color.Lerp(colors[(int)scaledT], colors[(int)Math.Min(scaledT+1, colors.Length-1)], (scaledT - (int)scaledT));
Color color = Color.Lerp(colors[(int)scaledT], colors[(int)Math.Min(scaledT + 1, colors.Length - 1)], (scaledT - (int)scaledT));
Vector2 pos = (blip.Position - item.WorldPosition) * displayScale;
pos.Y = -pos.Y;
@@ -471,7 +353,7 @@ namespace Barotrauma.Items.Components
blip.FadeTimer = 0.0f;
return;
}
float posDist = pos.Length();
Vector2 dir = pos / posDist;
float distFactor = (posDist / displayRadius);
@@ -486,9 +368,9 @@ namespace Barotrauma.Items.Components
return;
}
radarBlip.Draw(spriteBatch, center + pos, color, radarBlip.Origin, MathUtils.VectorToAngle(pos),
radarBlip.Draw(spriteBatch, center + pos, color, radarBlip.Origin, MathUtils.VectorToAngle(pos),
new Vector2(scale * 0.3f, scale) * 0.04f, SpriteEffects.None, 0);
pos += Rand.Range(0.0f, 1.0f) * dir + Rand.Range(-scale, scale) * normal;
radarBlip.Draw(spriteBatch, center + pos, color * 0.5f, radarBlip.Origin, MathUtils.VectorToAngle(pos),
@@ -508,7 +390,7 @@ namespace Barotrauma.Items.Components
Vector2 dir = Vector2.Normalize(position);
Vector2 markerPos = (dist*scale>radius) ? dir * radius : position;
Vector2 markerPos = (dist * scale > radius) ? dir * radius : position;
markerPos += center;
markerPos.X = (int)markerPos.X;
@@ -516,47 +398,24 @@ namespace Barotrauma.Items.Components
GUI.DrawRectangle(spriteBatch, new Rectangle((int)markerPos.X, (int)markerPos.Y, 5, 5), Color.LightBlue);
if (dir.X < 0.0f) markerPos.X -= GUI.SmallFont.MeasureString(label).X+10;
if (dir.X < 0.0f) markerPos.X -= GUI.SmallFont.MeasureString(label).X + 10;
string wrappedLabel = ToolBox.WrapText(label, 150, GUI.SmallFont);
wrappedLabel += "\n"+((int)(dist * Physics.DisplayToRealWorldRatio) + " m");
wrappedLabel += "\n" + ((int)(dist * Physics.DisplayToRealWorldRatio) + " m");
GUI.DrawString(spriteBatch,
new Vector2(markerPos.X + 10, markerPos.Y),
wrappedLabel,
Color.LightBlue * textAlpha, Color.Black * textAlpha * 0.5f,
2, GUI.SmallFont);
GUI.DrawString(spriteBatch,
new Vector2(markerPos.X + 10, markerPos.Y),
wrappedLabel,
Color.LightBlue * textAlpha, Color.Black * textAlpha * 0.5f,
2, GUI.SmallFont);
}
protected override void RemoveComponentSpecific()
{
if (pingCircle!=null) pingCircle.Remove();
if (screenOverlay != null) screenOverlay.Remove();
}
public void ClientWrite(Lidgren.Network.NetBuffer msg, object[] extraData = null)
{
msg.Write(IsActive);
}
public void ServerRead(ClientNetObject type, Lidgren.Network.NetBuffer msg, Barotrauma.Networking.Client c)
{
bool isActive = msg.ReadBoolean();
if (!item.CanClientAccess(c)) return;
IsActive = isActive;
isActiveTickBox.Selected = IsActive;
item.CreateServerEvent(this);
}
public void ServerWrite(Lidgren.Network.NetBuffer msg, Barotrauma.Networking.Client c, object[] extraData = null)
{
msg.Write(IsActive);
}
public void ClientRead(ServerNetObject type, Lidgren.Network.NetBuffer msg, float sendingTime)
{
if (correctionTimer > 0.0f)
@@ -567,7 +426,7 @@ namespace Barotrauma.Items.Components
IsActive = msg.ReadBoolean();
isActiveTickBox.Selected = IsActive;
}
}
}
class RadarBlip

View File

@@ -0,0 +1,265 @@
using System;
using System.Collections.Generic;
using System.Xml.Linq;
using Lidgren.Network;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Barotrauma.Networking;
namespace Barotrauma.Items.Components
{
partial class Reactor : Powered, IDrawableComponent, IServerSerializable, IClientSerializable
{
private GUITickBox autoTempTickBox;
partial void InitProjSpecific()
{
var button = new GUIButton(new Rectangle(410, 70, 40, 40), "-", "", GuiFrame);
button.OnPressed = () =>
{
lastUser = Character.Controlled;
if (nextServerLogWriteTime == null)
{
nextServerLogWriteTime = Math.Max(lastServerLogWriteTime + 1.0f, (float)Timing.TotalTime);
}
unsentChanges = true;
ShutDownTemp -= 100.0f;
return false;
};
button = new GUIButton(new Rectangle(460, 70, 40, 40), "+", "", GuiFrame);
button.OnPressed = () =>
{
lastUser = Character.Controlled;
if (nextServerLogWriteTime == null)
{
nextServerLogWriteTime = Math.Max(lastServerLogWriteTime + 1.0f, (float)Timing.TotalTime);
}
unsentChanges = true;
ShutDownTemp += 100.0f;
return false;
};
autoTempTickBox = new GUITickBox(new Rectangle(410, 170, 20, 20), "Automatic temperature control", Alignment.TopLeft, GuiFrame);
autoTempTickBox.OnSelected = ToggleAutoTemp;
button = new GUIButton(new Rectangle(210, 290, 40, 40), "+", "", GuiFrame);
button.OnPressed = () =>
{
lastUser = Character.Controlled;
if (nextServerLogWriteTime == null)
{
nextServerLogWriteTime = Math.Max(lastServerLogWriteTime + 1.0f, (float)Timing.TotalTime);
}
unsentChanges = true;
FissionRate += 1.0f;
return false;
};
button = new GUIButton(new Rectangle(210, 340, 40, 40), "-", "", GuiFrame);
button.OnPressed = () =>
{
lastUser = Character.Controlled;
if (nextServerLogWriteTime == null)
{
nextServerLogWriteTime = Math.Max(lastServerLogWriteTime + 1.0f, (float)Timing.TotalTime);
}
unsentChanges = true;
FissionRate -= 1.0f;
return false;
};
button = new GUIButton(new Rectangle(500, 290, 40, 40), "+", "", GuiFrame);
button.OnPressed = () =>
{
lastUser = Character.Controlled;
if (nextServerLogWriteTime == null)
{
nextServerLogWriteTime = Math.Max(lastServerLogWriteTime + 1.0f, (float)Timing.TotalTime);
}
unsentChanges = true;
CoolingRate += 1.0f;
return false;
};
button = new GUIButton(new Rectangle(500, 340, 40, 40), "-", "", GuiFrame);
button.OnPressed = () =>
{
lastUser = Character.Controlled;
if (nextServerLogWriteTime == null)
{
nextServerLogWriteTime = Math.Max(lastServerLogWriteTime + 1.0f, (float)Timing.TotalTime);
}
unsentChanges = true;
CoolingRate -= 1.0f;
return false;
};
}
private void UpdateGraph(float deltaTime)
{
graphTimer += deltaTime * 1000.0f;
if (graphTimer > updateGraphInterval)
{
UpdateGraph(fissionRateGraph, fissionRate);
UpdateGraph(coolingRateGraph, coolingRate);
UpdateGraph(tempGraph, temperature);
UpdateGraph(loadGraph, load);
graphTimer = 0.0f;
}
}
public void Draw(SpriteBatch spriteBatch, bool editing = false)
{
GUI.DrawRectangle(spriteBatch,
new Vector2(item.Rect.X + item.Rect.Width / 2 - 6, -item.Rect.Y + 29),
new Vector2(12, 42), Color.Black);
if (temperature > 0)
GUI.DrawRectangle(spriteBatch,
new Vector2(item.Rect.X + item.Rect.Width / 2 - 5, -item.Rect.Y + 30 + (40.0f * (1.0f - temperature / 10000.0f))),
new Vector2(10, 40 * (temperature / 10000.0f)), new Color(temperature / 10000.0f, 1.0f - (temperature / 10000.0f), 0.0f, 1.0f), true);
}
public override void DrawHUD(SpriteBatch spriteBatch, Character character)
{
IsActive = true;
int x = GuiFrame.Rect.X;
int y = GuiFrame.Rect.Y;
GuiFrame.Draw(spriteBatch);
float xOffset = graphTimer / updateGraphInterval;
//GUI.DrawRectangle(spriteBatch, new Rectangle(x, y, width, height), Color.Black, true);
GUI.Font.DrawString(spriteBatch, "Output: " + (int)temperature + " kW",
new Vector2(x + 450, y + 30), Color.Red);
GUI.Font.DrawString(spriteBatch, "Grid load: " + (int)load + " kW",
new Vector2(x + 600, y + 30), Color.Yellow);
float maxLoad = 0.0f;
foreach (float loadVal in loadGraph)
{
maxLoad = Math.Max(maxLoad, loadVal);
}
DrawGraph(tempGraph, spriteBatch,
new Rectangle(x + 30, y + 30, 400, 250), Math.Max(10000.0f, maxLoad), xOffset, Color.Red);
DrawGraph(loadGraph, spriteBatch,
new Rectangle(x + 30, y + 30, 400, 250), Math.Max(10000.0f, maxLoad), xOffset, Color.Yellow);
GUI.Font.DrawString(spriteBatch, "Shutdown Temperature: " + (int)shutDownTemp, new Vector2(x + 450, y + 80), Color.White);
//GUI.Font.DrawString(spriteBatch, "Automatic Temperature Control: " + ((autoTemp) ? "ON" : "OFF"), new Vector2(x + 450, y + 180), Color.White);
y += 300;
GUI.Font.DrawString(spriteBatch, "Fission rate: " + (int)fissionRate + " %", new Vector2(x + 30, y), Color.White);
DrawGraph(fissionRateGraph, spriteBatch,
new Rectangle(x + 30, y + 30, 200, 100), 100.0f, xOffset, Color.Orange);
GUI.Font.DrawString(spriteBatch, "Cooling rate: " + (int)coolingRate + " %", new Vector2(x + 320, y), Color.White);
DrawGraph(coolingRateGraph, spriteBatch,
new Rectangle(x + 320, y + 30, 200, 100), 100.0f, xOffset, Color.LightBlue);
//y = y - 260;
}
public override void AddToGUIUpdateList()
{
GuiFrame.AddToGUIUpdateList();
}
public override void UpdateHUD(Character character)
{
GuiFrame.Update(1.0f / 60.0f);
}
private bool ToggleAutoTemp(GUITickBox tickBox)
{
unsentChanges = true;
autoTemp = tickBox.Selected;
return true;
}
static void UpdateGraph<T>(IList<T> graph, T newValue)
{
for (int i = graph.Count - 1; i > 0; i--)
{
graph[i] = graph[i - 1];
}
graph[0] = newValue;
}
static void DrawGraph(IList<float> graph, SpriteBatch spriteBatch, Rectangle rect, float maxVal, float xOffset, Color color)
{
float lineWidth = (float)rect.Width / (float)(graph.Count - 2);
float yScale = (float)rect.Height / maxVal;
GUI.DrawRectangle(spriteBatch, rect, Color.White);
Vector2 prevPoint = new Vector2(rect.Right, rect.Bottom - (graph[1] + (graph[0] - graph[1]) * xOffset) * yScale);
float currX = rect.Right - ((xOffset - 1.0f) * lineWidth);
for (int i = 1; i < graph.Count - 1; i++)
{
currX -= lineWidth;
Vector2 newPoint = new Vector2(currX, rect.Bottom - graph[i] * yScale);
GUI.DrawLine(spriteBatch, prevPoint, newPoint - new Vector2(1.0f, 0), color);
prevPoint = newPoint;
}
Vector2 lastPoint = new Vector2(rect.X,
rect.Bottom - (graph[graph.Count - 1] + (graph[graph.Count - 2] - graph[graph.Count - 1]) * xOffset) * yScale);
GUI.DrawLine(spriteBatch, prevPoint, lastPoint, color);
}
public void ClientWrite(NetBuffer msg, object[] extraData = null)
{
msg.Write(autoTemp);
msg.WriteRangedSingle(shutDownTemp, 0.0f, 10000.0f, 15);
msg.WriteRangedSingle(coolingRate, 0.0f, 100.0f, 8);
msg.WriteRangedSingle(fissionRate, 0.0f, 100.0f, 8);
correctionTimer = CorrectionDelay;
}
public void ClientRead(ServerNetObject type, NetBuffer msg, float sendingTime)
{
if (correctionTimer > 0.0f)
{
StartDelayedCorrection(type, msg.ExtractBits(16 + 1 + 15 + 8 + 8), sendingTime);
return;
}
Temperature = msg.ReadRangedSingle(0.0f, 10000.0f, 16);
AutoTemp = msg.ReadBoolean();
ShutDownTemp = msg.ReadRangedSingle(0.0f, 10000.0f, 15);
CoolingRate = msg.ReadRangedSingle(0.0f, 100.0f, 8);
FissionRate = msg.ReadRangedSingle(0.0f, 100.0f, 8);
}
}
}

View File

@@ -0,0 +1,268 @@
using Barotrauma.Networking;
using FarseerPhysics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using Voronoi2;
namespace Barotrauma.Items.Components
{
partial class Steering : Powered, IServerSerializable, IClientSerializable
{
private GUITickBox autopilotTickBox, maintainPosTickBox;
private GUITickBox levelEndTickBox, levelStartTickBox;
public bool LevelStartSelected
{
get { return levelStartTickBox.Selected; }
set { levelStartTickBox.Selected = value; }
}
public bool LevelEndSelected
{
get { return levelEndTickBox.Selected; }
set { levelEndTickBox.Selected = value; }
}
public bool MaintainPos
{
get { return maintainPosTickBox.Selected; }
set { maintainPosTickBox.Selected = value; }
}
partial void InitProjSpecific()
{
autopilotTickBox = new GUITickBox(new Rectangle(0, 25, 20, 20), "Autopilot", Alignment.TopLeft, GuiFrame);
autopilotTickBox.OnSelected = (GUITickBox box) =>
{
AutoPilot = box.Selected;
unsentChanges = true;
return true;
};
maintainPosTickBox = new GUITickBox(new Rectangle(5, 50, 15, 15), "Maintain position", Alignment.TopLeft, GUI.SmallFont, GuiFrame);
maintainPosTickBox.Enabled = false;
maintainPosTickBox.OnSelected = ToggleMaintainPosition;
levelStartTickBox = new GUITickBox(
new Rectangle(5, 70, 15, 15),
GameMain.GameSession == null ? "" : ToolBox.LimitString(GameMain.GameSession.StartLocation.Name, 20),
Alignment.TopLeft, GUI.SmallFont, GuiFrame);
levelStartTickBox.Enabled = false;
levelStartTickBox.OnSelected = SelectDestination;
levelEndTickBox = new GUITickBox(
new Rectangle(5, 90, 15, 15),
GameMain.GameSession == null ? "" : ToolBox.LimitString(GameMain.GameSession.EndLocation.Name, 20),
Alignment.TopLeft, GUI.SmallFont, GuiFrame);
levelEndTickBox.Enabled = false;
levelEndTickBox.OnSelected = SelectDestination;
}
private bool ToggleMaintainPosition(GUITickBox tickBox)
{
unsentChanges = true;
levelStartTickBox.Selected = false;
levelEndTickBox.Selected = false;
if (item.Submarine == null)
{
posToMaintain = null;
}
else
{
posToMaintain = item.Submarine.WorldPosition;
}
tickBox.Selected = true;
return true;
}
public override void DrawHUD(SpriteBatch spriteBatch, Character character)
{
//if (voltage < minVoltage) return;
int width = GuiFrame.Rect.Width, height = GuiFrame.Rect.Height;
int x = GuiFrame.Rect.X;
int y = GuiFrame.Rect.Y;
GuiFrame.Draw(spriteBatch);
if (voltage < minVoltage && powerConsumption > 0.0f) return;
Rectangle velRect = new Rectangle(x + 20, y + 20, width - 40, height - 40);
//GUI.DrawRectangle(spriteBatch, velRect, Color.White, false);
if (item.Submarine != null && Level.Loaded != null)
{
Vector2 realWorldVelocity = ConvertUnits.ToDisplayUnits(item.Submarine.Velocity * Physics.DisplayToRealWorldRatio) * 3.6f;
float realWorldDepth = Math.Abs(item.Submarine.Position.Y - Level.Loaded.Size.Y) * Physics.DisplayToRealWorldRatio;
GUI.DrawString(spriteBatch, new Vector2(x + 20, y + height - 65),
"Velocity: " + (int)realWorldVelocity.X + " km/h", Color.LightGreen, null, 0, GUI.SmallFont);
GUI.DrawString(spriteBatch, new Vector2(x + 20, y + height - 50),
"Descent velocity: " + -(int)realWorldVelocity.Y + " km/h", Color.LightGreen, null, 0, GUI.SmallFont);
GUI.DrawString(spriteBatch, new Vector2(x + 20, y + height - 30),
"Depth: " + (int)realWorldDepth + " m", Color.LightGreen, null, 0, GUI.SmallFont);
}
GUI.DrawLine(spriteBatch,
new Vector2(velRect.Center.X, velRect.Center.Y),
new Vector2(velRect.Center.X + currVelocity.X, velRect.Center.Y - currVelocity.Y),
Color.Gray);
Vector2 targetVelPos = new Vector2(velRect.Center.X + targetVelocity.X, velRect.Center.Y - targetVelocity.Y);
GUI.DrawLine(spriteBatch,
new Vector2(velRect.Center.X, velRect.Center.Y),
targetVelPos,
Color.LightGray);
GUI.DrawRectangle(spriteBatch, new Rectangle((int)targetVelPos.X - 5, (int)targetVelPos.Y - 5, 10, 10), Color.White);
if (Vector2.Distance(PlayerInput.MousePosition, new Vector2(velRect.Center.X, velRect.Center.Y)) < 200.0f)
{
GUI.DrawRectangle(spriteBatch, new Rectangle((int)targetVelPos.X - 10, (int)targetVelPos.Y - 10, 20, 20), Color.Red);
}
}
public override void AddToGUIUpdateList()
{
GuiFrame.AddToGUIUpdateList();
}
public override void UpdateHUD(Character character)
{
GuiFrame.Update(1.0f / 60.0f);
if (Vector2.Distance(PlayerInput.MousePosition, new Vector2(GuiFrame.Rect.Center.X, GuiFrame.Rect.Center.Y)) < 200.0f)
{
if (PlayerInput.LeftButtonHeld())
{
TargetVelocity = PlayerInput.MousePosition - new Vector2(GuiFrame.Rect.Center.X, GuiFrame.Rect.Center.Y);
targetVelocity.Y = -targetVelocity.Y;
unsentChanges = true;
}
}
}
private bool SelectDestination(GUITickBox tickBox)
{
unsentChanges = true;
if (tickBox == levelStartTickBox)
{
levelEndTickBox.Selected = false;
}
else
{
levelStartTickBox.Selected = false;
}
maintainPosTickBox.Selected = false;
posToMaintain = null;
tickBox.Selected = true;
UpdatePath();
return true;
}
public void ClientWrite(Lidgren.Network.NetBuffer msg, object[] extraData = null)
{
msg.Write(autoPilot);
if (!autoPilot)
{
//no need to write steering info if autopilot is controlling
msg.Write(targetVelocity.X);
msg.Write(targetVelocity.Y);
}
else
{
msg.Write(posToMaintain != null);
if (posToMaintain != null)
{
msg.Write(((Vector2)posToMaintain).X);
msg.Write(((Vector2)posToMaintain).Y);
}
else
{
msg.Write(LevelStartSelected);
}
}
}
public void ClientRead(ServerNetObject type, Lidgren.Network.NetBuffer msg, float sendingTime)
{
long msgStartPos = msg.Position;
bool autoPilot = msg.ReadBoolean();
Vector2 newTargetVelocity = targetVelocity;
bool maintainPos = false;
Vector2? newPosToMaintain = null;
bool headingToStart = false;
if (autoPilot)
{
maintainPos = msg.ReadBoolean();
if (maintainPos)
{
newPosToMaintain = new Vector2(
msg.ReadFloat(),
msg.ReadFloat());
}
else
{
headingToStart = msg.ReadBoolean();
}
}
else
{
newTargetVelocity = new Vector2(msg.ReadFloat(), msg.ReadFloat());
}
if (correctionTimer > 0.0f)
{
int msgLength = (int)(msg.Position - msgStartPos);
msg.Position = msgStartPos;
StartDelayedCorrection(type, msg.ExtractBits(msgLength), sendingTime);
return;
}
AutoPilot = autoPilot;
if (!AutoPilot)
{
targetVelocity = newTargetVelocity;
}
else
{
MaintainPos = newPosToMaintain != null;
posToMaintain = newPosToMaintain;
if (posToMaintain == null)
{
LevelStartSelected = headingToStart;
LevelEndSelected = !headingToStart;
UpdatePath();
}
else
{
LevelStartSelected = false;
LevelEndSelected = false;
}
}
}
}
}

View File

@@ -0,0 +1,110 @@
using System;
using System.Xml.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Barotrauma.Networking;
using Lidgren.Network;
namespace Barotrauma.Items.Components
{
partial class PowerContainer : Powered, IDrawableComponent, IServerSerializable, IClientSerializable
{
partial void InitProjSpecific()
{
if (canBeSelected)
{
var button = new GUIButton(new Rectangle(160, 50, 30, 30), "-", "", GuiFrame);
button.OnClicked = (GUIButton btn, object obj) =>
{
RechargeSpeed = rechargeSpeed - maxRechargeSpeed * 0.1f;
if (GameMain.Server != null)
{
item.CreateServerEvent(this);
GameServer.Log(Character.Controlled + " set the recharge speed of " + item.Name + " to " + (int)((rechargeSpeed / maxRechargeSpeed) * 100.0f) + " %", ServerLog.MessageType.ItemInteraction);
}
else if (GameMain.Client != null)
{
item.CreateClientEvent(this);
correctionTimer = CorrectionDelay;
}
return true;
};
button = new GUIButton(new Rectangle(200, 50, 30, 30), "+", "", GuiFrame);
button.OnClicked = (GUIButton btn, object obj) =>
{
RechargeSpeed = rechargeSpeed + maxRechargeSpeed * 0.1f;
if (GameMain.Server != null)
{
item.CreateServerEvent(this);
GameServer.Log(Character.Controlled + " set the recharge speed of " + item.Name + " to " + (int)((rechargeSpeed / maxRechargeSpeed) * 100.0f) + " %", ServerLog.MessageType.ItemInteraction);
}
else if (GameMain.Client != null)
{
item.CreateClientEvent(this);
correctionTimer = CorrectionDelay;
}
return true;
};
}
}
public void Draw(SpriteBatch spriteBatch, bool editing = false)
{
GUI.DrawRectangle(spriteBatch,
new Vector2(item.DrawPosition.X - 4, -item.DrawPosition.Y),
new Vector2(8, 22), Color.Black);
if (charge > 0)
GUI.DrawRectangle(spriteBatch,
new Vector2(item.DrawPosition.X - 3, -item.DrawPosition.Y + 1 + (20.0f * (1.0f - charge / capacity))),
new Vector2(6, 20 * (charge / capacity)), Color.Green, true);
}
public override void DrawHUD(SpriteBatch spriteBatch, Character character)
{
GuiFrame.Draw(spriteBatch);
int x = GuiFrame.Rect.X;
int y = GuiFrame.Rect.Y;
//GUI.DrawRectangle(spriteBatch, new Rectangle(x, y, width, height), Color.Black, true);
GUI.Font.DrawString(spriteBatch,
"Charge: " + (int)charge + "/" + (int)capacity + " kWm (" + (int)((charge / capacity) * 100.0f) + " %)",
new Vector2(x + 30, y + 30), Color.White);
GUI.Font.DrawString(spriteBatch, "Recharge rate: " + (int)((rechargeSpeed / maxRechargeSpeed) * 100.0f) + " %", new Vector2(x + 30, y + 95), Color.White);
}
public override void AddToGUIUpdateList()
{
GuiFrame.AddToGUIUpdateList();
}
public override void UpdateHUD(Character character)
{
GuiFrame.Update(1.0f / 60.0f);
}
public void ClientWrite(NetBuffer msg, object[] extraData)
{
msg.WriteRangedInteger(0, 10, (int)(rechargeSpeed / MaxRechargeSpeed * 10));
}
public void ClientRead(ServerNetObject type, NetBuffer msg, float sendingTime)
{
if (correctionTimer > 0.0f)
{
StartDelayedCorrection(type, msg.ExtractBits(4 + 8), sendingTime);
return;
}
RechargeSpeed = msg.ReadRangedInteger(0, 10) / 10.0f * maxRechargeSpeed;
Charge = msg.ReadRangedSingle(0.0f, 1.0f, 8) * capacity;
}
}
}

View File

@@ -0,0 +1,36 @@
using System.Collections.Generic;
using System.Xml.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.Globalization;
using System.Linq;
namespace Barotrauma.Items.Components
{
partial class PowerTransfer : Powered
{
public override void DrawHUD(SpriteBatch spriteBatch, Character character)
{
if (!canBeSelected) return;
int x = GuiFrame.Rect.X;
int y = GuiFrame.Rect.Y;
GuiFrame.Draw(spriteBatch);
GUI.Font.DrawString(spriteBatch, "Power: " + (int)(-currPowerConsumption) + " kW", new Vector2(x + 30, y + 30), Color.White);
GUI.Font.DrawString(spriteBatch, "Load: " + (int)powerLoad + " kW", new Vector2(x + 30, y + 100), Color.White);
}
public override void AddToGUIUpdateList()
{
GuiFrame.AddToGUIUpdateList();
}
public override void UpdateHUD(Character character)
{
GuiFrame.Update(1.0f / 60.0f);
}
}
}

View File

@@ -0,0 +1,14 @@
using System;
using System.Xml.Linq;
namespace Barotrauma.Items.Components
{
partial class Powered : ItemComponent
{
protected static Sound[] sparkSounds;
private bool powerOnSoundPlayed;
private static Sound powerOnSound;
}
}

View File

@@ -7,190 +7,12 @@ using System.Xml.Linq;
namespace Barotrauma.Items.Components
{
class Connection
partial class Connection
{
private static Texture2D panelTexture;
private static Sprite connector;
private static Sprite wireVertical;
//how many wires can be linked to a single connector
public const int MaxLinked = 5;
public readonly string Name;
public Wire[] Wires;
private Item item;
public readonly bool IsOutput;
private static Wire draggingConnected;
private List<StatusEffect> effects;
public readonly ushort[] wireId;
public bool IsPower
{
get;
private set;
}
public List<Connection> Recipients
{
get
{
List<Connection> recipients = new List<Connection>();
for (int i = 0; i < MaxLinked; i++)
{
if (Wires[i] == null) continue;
Connection recipient = Wires[i].OtherConnection(this);
if (recipient != null) recipients.Add(recipient);
}
return recipients;
}
}
public Item Item
{
get { return item; }
}
public Connection(XElement element, Item item)
{
if (connector == null)
{
panelTexture = Sprite.LoadTexture("Content/Items/connectionpanel.png");
connector = new Sprite(panelTexture, new Rectangle(470, 102, 19, 43), Vector2.Zero, 0.0f);
connector.Origin = new Vector2(9.5f, 10.0f);
wireVertical = new Sprite(panelTexture, new Rectangle(408, 1, 11, 102), Vector2.Zero, 0.0f);
}
this.item = item;
//recipient = new Connection[MaxLinked];
Wires = new Wire[MaxLinked];
IsOutput = (element.Name.ToString() == "output");
Name = ToolBox.GetAttributeString(element, "name", (IsOutput) ? "output" : "input");
IsPower = Name == "power_in" || Name == "power" || Name == "power_out";
effects = new List<StatusEffect>();
wireId = new ushort[MaxLinked];
foreach (XElement subElement in element.Elements())
{
switch (subElement.Name.ToString().ToLowerInvariant())
{
case "link":
int index = -1;
for (int i = 0; i < MaxLinked; i++)
{
if (wireId[i] < 1) index = i;
}
if (index == -1) break;
int id = ToolBox.GetAttributeInt(subElement, "w", 0);
if (id < 0) id = 0;
wireId[index] = (ushort)id;
break;
case "statuseffect":
effects.Add(StatusEffect.Load(subElement));
break;
}
}
}
public int FindEmptyIndex()
{
for (int i = 0; i < MaxLinked; i++)
{
if (Wires[i] == null) return i;
}
return -1;
}
//public int FindLinkIndex(Item item)
//{
// for (int i = 0; i < MaxLinked; i++)
// {
// if (item == null && recipient[i] == null) return i;
// if (recipient[i]!=null && recipient[i].item == item) return i;
// }
// return -1;
//}
public int FindWireIndex(Item wireItem)
{
for (int i = 0; i < MaxLinked; i++)
{
if (Wires[i] == null && wireItem == null) return i;
if (Wires[i] != null && Wires[i].Item == wireItem) return i;
}
return -1;
}
public void TryAddLink(Wire wire)
{
for (int i = 0; i < MaxLinked; i++)
{
if (Wires[i] == null)
{
Wires[i] = wire;
return;
}
}
}
public void AddLink(int index, Wire wire)
{
Wires[index] = wire;
}
public void SendSignal(int stepsTaken, string signal, Item source, Character sender, float power)
{
for (int i = 0; i < MaxLinked; i++)
{
if (Wires[i] == null) continue;
Connection recipient = Wires[i].OtherConnection(this);
if (recipient == null) continue;
if (recipient.item == this.item || recipient.item == source) continue;
foreach (ItemComponent ic in recipient.item.components)
{
ic.ReceiveSignal(stepsTaken, signal, recipient, item, sender, power);
}
foreach (StatusEffect effect in recipient.effects)
{
//effect.Apply(ActionType.OnUse, 1.0f, recipient.item, recipient.item);
recipient.item.ApplyStatusEffect(effect, ActionType.OnUse, 1.0f);
}
}
}
public void ClearConnections()
{
for (int i = 0; i < MaxLinked; i++)
{
if (Wires[i] == null) continue;
Wires[i].RemoveConnection(this);
Wires[i] = null;
}
}
public static void DrawConnections(SpriteBatch spriteBatch, ConnectionPanel panel, Character character)
{
@@ -438,7 +260,7 @@ namespace Barotrauma.Items.Components
{
XElement newElement = new XElement(IsOutput ? "output" : "input", new XAttribute("name", Name));
Array.Sort(Wires, delegate(Wire wire1, Wire wire2)
Array.Sort(Wires, delegate (Wire wire1, Wire wire2)
{
if (wire1 == null) return 1;
if (wire2 == null) return -1;
@@ -458,29 +280,5 @@ namespace Barotrauma.Items.Components
parentElement.Add(newElement);
}
public void ConnectLinked()
{
if (wireId == null) return;
for (int i = 0; i < MaxLinked; i++)
{
if (wireId[i] == 0) continue;
Item wireItem = MapEntity.FindEntityByID(wireId[i]) as Item;
if (wireItem == null) continue;
Wires[i] = wireItem.GetComponent<Wire>();
if (Wires[i] != null)
{
if (Wires[i].Item.body != null) Wires[i].Item.body.Enabled = false;
Wires[i].Connect(this, false, false);
}
}
}
}
}
}

View File

@@ -0,0 +1,51 @@
using Barotrauma.Networking;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.Linq;
using System.Collections.Generic;
using System.Xml.Linq;
using Lidgren.Network;
namespace Barotrauma.Items.Components
{
partial class ConnectionPanel : ItemComponent, IServerSerializable, IClientSerializable
{
public override void UpdateHUD(Character character)
{
if (character != Character.Controlled || character != user) return;
if (Screen.Selected != GameMain.EditMapScreen &&
character.IsKeyHit(InputType.Select) &&
character.SelectedConstruction == this.item) character.SelectedConstruction = null;
if (HighlightedWire != null)
{
HighlightedWire.Item.IsHighlighted = true;
if (HighlightedWire.Connections[0] != null && HighlightedWire.Connections[0].Item != null) HighlightedWire.Connections[0].Item.IsHighlighted = true;
if (HighlightedWire.Connections[1] != null && HighlightedWire.Connections[1].Item != null) HighlightedWire.Connections[1].Item.IsHighlighted = true;
}
}
public override void DrawHUD(SpriteBatch spriteBatch, Character character)
{
if (character != Character.Controlled || character != user) return;
HighlightedWire = null;
Connection.DrawConnections(spriteBatch, this, character);
}
public override XElement Save(XElement parentElement)
{
XElement componentElement = base.Save(parentElement);
foreach (Connection c in Connections)
{
c.Save(componentElement);
}
return componentElement;
}
}
}

View File

@@ -0,0 +1,256 @@
using Barotrauma.Networking;
using Lidgren.Network;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Xml.Linq;
namespace Barotrauma.Items.Components
{
partial class Wire : ItemComponent, IDrawableComponent, IServerSerializable
{
partial class WireSection
{
public void Draw(SpriteBatch spriteBatch, Color color, Vector2 offset, float depth, float width = 0.3f)
{
spriteBatch.Draw(wireSprite.Texture,
new Vector2(start.X + offset.X, -(start.Y + offset.Y)), null, color,
-angle,
new Vector2(0.0f, wireSprite.size.Y / 2.0f),
new Vector2(length / wireSprite.Texture.Width, width),
SpriteEffects.None,
depth);
}
public static void Draw(SpriteBatch spriteBatch, Vector2 start, Vector2 end, Color color, float depth, float width = 0.3f)
{
start.Y = -start.Y;
end.Y = -end.Y;
spriteBatch.Draw(wireSprite.Texture,
start, null, color,
MathUtils.VectorToAngle(end - start),
new Vector2(0.0f, wireSprite.size.Y / 2.0f),
new Vector2((Vector2.Distance(start, end)) / wireSprite.Texture.Width, width),
SpriteEffects.None,
depth);
}
}
public void Draw(SpriteBatch spriteBatch, bool editing)
{
if (sections.Count == 0 && !IsActive)
{
Drawable = false;
return;
}
Vector2 drawOffset = Vector2.Zero;
if (item.Submarine != null)
{
drawOffset = item.Submarine.DrawPosition + item.Submarine.HiddenSubPosition;
}
float depth = item.IsSelected ? 0.0f : wireSprite.Depth + ((item.ID % 100) * 0.00001f);
if (item.IsHighlighted)
{
foreach (WireSection section in sections)
{
section.Draw(spriteBatch, Color.Gold, drawOffset, depth + 0.00001f, 0.7f);
}
}
else if (item.IsSelected)
{
foreach (WireSection section in sections)
{
section.Draw(spriteBatch, Color.Red, drawOffset, depth + 0.00001f, 0.7f);
}
}
foreach (WireSection section in sections)
{
section.Draw(spriteBatch, item.Color, drawOffset, depth, 0.3f);
}
if (IsActive && nodes.Count > 0 && Vector2.Distance(newNodePos, nodes[nodes.Count - 1]) > nodeDistance)
{
WireSection.Draw(
spriteBatch,
new Vector2(nodes[nodes.Count - 1].X, nodes[nodes.Count - 1].Y) + drawOffset,
new Vector2(newNodePos.X, newNodePos.Y) + drawOffset,
item.Color * 0.5f,
depth,
0.3f);
}
if (!editing || !GameMain.EditMapScreen.WiringMode) return;
for (int i = 0; i < nodes.Count; i++)
{
Vector2 drawPos = nodes[i];
if (item.Submarine != null) drawPos += item.Submarine.Position + item.Submarine.HiddenSubPosition;
drawPos.Y = -drawPos.Y;
if (item.IsSelected)
{
GUI.DrawRectangle(spriteBatch, drawPos + new Vector2(-5, -5), new Vector2(10, 10), item.Color, true, 0.0f);
if (highlightedNodeIndex == i)
{
GUI.DrawRectangle(spriteBatch, drawPos + new Vector2(-10, -10), new Vector2(20, 20), Color.Red, false, 0.0f);
}
}
else
{
GUI.DrawRectangle(spriteBatch, drawPos + new Vector2(-3, -3), new Vector2(6, 6), item.Color, true, 0.0f);
}
}
}
public static void UpdateEditing(List<Wire> wires)
{
//dragging a node of some wire
if (draggingWire != null)
{
//cancel dragging
if (!PlayerInput.LeftButtonHeld())
{
draggingWire = null;
selectedNodeIndex = null;
}
//update dragging
else
{
MapEntity.DisableSelect = true;
Submarine sub = null;
if (draggingWire.connections[0] != null && draggingWire.connections[0].Item.Submarine != null) sub = draggingWire.connections[0].Item.Submarine;
if (draggingWire.connections[1] != null && draggingWire.connections[1].Item.Submarine != null) sub = draggingWire.connections[1].Item.Submarine;
Vector2 nodeWorldPos = GameMain.EditMapScreen.Cam.ScreenToWorld(PlayerInput.MousePosition) - sub.HiddenSubPosition - sub.Position;// Nodes[(int)selectedNodeIndex];
nodeWorldPos.X = MathUtils.Round(nodeWorldPos.X, Submarine.GridSize.X / 2.0f);
nodeWorldPos.Y = MathUtils.Round(nodeWorldPos.Y, Submarine.GridSize.Y / 2.0f);
draggingWire.nodes[(int)selectedNodeIndex] = nodeWorldPos;
draggingWire.UpdateSections();
MapEntity.SelectEntity(draggingWire.item);
}
return;
}
//a wire has been selected -> check if we should start dragging one of the nodes
float nodeSelectDist = 10, sectionSelectDist = 5;
highlightedNodeIndex = null;
if (MapEntity.SelectedList.Count == 1 && MapEntity.SelectedList[0] is Item)
{
Wire selectedWire = ((Item)MapEntity.SelectedList[0]).GetComponent<Wire>();
if (selectedWire != null)
{
Vector2 mousePos = GameMain.EditMapScreen.Cam.ScreenToWorld(PlayerInput.MousePosition);
if (selectedWire.item.Submarine != null) mousePos -= (selectedWire.item.Submarine.Position + selectedWire.item.Submarine.HiddenSubPosition);
//left click while holding ctrl -> check if the cursor is on a wire section,
//and add a new node if it is
if (PlayerInput.KeyDown(Keys.RightControl) || PlayerInput.KeyDown(Keys.LeftControl))
{
if (PlayerInput.LeftButtonClicked())
{
float temp = 0.0f;
int closestSectionIndex = selectedWire.GetClosestSectionIndex(mousePos, sectionSelectDist, out temp);
if (closestSectionIndex > -1)
{
selectedWire.nodes.Insert(closestSectionIndex + 1, mousePos);
selectedWire.UpdateSections();
}
}
}
else
{
//check if close enough to a node
float temp = 0.0f;
int closestIndex = selectedWire.GetClosestNodeIndex(mousePos, nodeSelectDist, out temp);
if (closestIndex > -1)
{
highlightedNodeIndex = closestIndex;
//start dragging the node
if (PlayerInput.LeftButtonHeld())
{
draggingWire = selectedWire;
selectedNodeIndex = closestIndex;
}
//remove the node
else if (PlayerInput.RightButtonClicked() && closestIndex > 0 && closestIndex < selectedWire.nodes.Count - 1)
{
selectedWire.nodes.RemoveAt(closestIndex);
selectedWire.UpdateSections();
}
}
}
}
}
//check which wire is highlighted with the cursor
Wire highlighted = null;
float closestDist = 0.0f;
foreach (Wire w in wires)
{
Vector2 mousePos = GameMain.EditMapScreen.Cam.ScreenToWorld(PlayerInput.MousePosition);
if (w.item.Submarine != null) mousePos -= (w.item.Submarine.Position + w.item.Submarine.HiddenSubPosition);
float dist = 0.0f;
if (w.GetClosestNodeIndex(mousePos, highlighted == null ? nodeSelectDist : closestDist, out dist) > -1)
{
highlighted = w;
closestDist = dist;
}
if (w.GetClosestSectionIndex(mousePos, highlighted == null ? sectionSelectDist : closestDist, out dist) > -1)
{
highlighted = w;
closestDist = dist;
}
}
if (highlighted != null)
{
highlighted.item.IsHighlighted = true;
if (PlayerInput.LeftButtonClicked())
{
MapEntity.DisableSelect = true;
MapEntity.SelectEntity(highlighted.item);
}
}
}
public override XElement Save(XElement parentElement)
{
XElement componentElement = base.Save(parentElement);
if (nodes == null || nodes.Count == 0) return componentElement;
string[] nodeCoords = new string[nodes.Count * 2];
for (int i = 0; i < nodes.Count; i++)
{
nodeCoords[i * 2] = nodes[i].X.ToString(CultureInfo.InvariantCulture);
nodeCoords[i * 2 + 1] = nodes[i].Y.ToString(CultureInfo.InvariantCulture);
}
componentElement.Add(new XAttribute("nodes", string.Join(";", nodeCoords)));
return componentElement;
}
}
}

View File

@@ -8,19 +8,8 @@ using Microsoft.Xna.Framework;
namespace Barotrauma.Items.Components
{
class StatusHUD : ItemComponent
partial class StatusHUD : ItemComponent
{
private static readonly string[] BleedingTexts = {"Minor bleeding", "Bleeding", "Bleeding heavily", "Catastrophic Bleeding"};
private static readonly string[] HealthTexts = { "No visible injuries", "Minor injuries", "Injured", "Major injuries", "Critically injured" };
private static readonly string[] OxygenTexts = { "Oxygen level normal", "Gasping for air", "Signs of oxygen deprivation", "Not breathing" };
public StatusHUD(Item item, XElement element)
: base(item, element)
{
}
public override void DrawHUD(SpriteBatch spriteBatch, Character character)
{
if (character == null) return;

View File

@@ -0,0 +1,63 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Xml.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using FarseerPhysics;
using Barotrauma.Networking;
using Lidgren.Network;
namespace Barotrauma.Items.Components
{
partial class Turret : Powered, IDrawableComponent, IServerSerializable
{
public void Draw(SpriteBatch spriteBatch, bool editing = false)
{
Vector2 drawPos = new Vector2(item.Rect.X, item.Rect.Y);
if (item.Submarine != null) drawPos += item.Submarine.DrawPosition;
drawPos.Y = -drawPos.Y;
if (barrelSprite != null)
{
barrelSprite.Draw(spriteBatch,
drawPos + barrelPos, Color.White,
rotation + MathHelper.PiOver2, 1.0f,
SpriteEffects.None, item.Sprite.Depth + 0.01f);
}
if (!editing) return;
GUI.DrawLine(spriteBatch,
drawPos + barrelPos,
drawPos + barrelPos + new Vector2((float)Math.Cos(minRotation), (float)Math.Sin(minRotation)) * 60.0f,
Color.Green);
GUI.DrawLine(spriteBatch,
drawPos + barrelPos,
drawPos + barrelPos + new Vector2((float)Math.Cos(maxRotation), (float)Math.Sin(maxRotation)) * 60.0f,
Color.Green);
GUI.DrawLine(spriteBatch,
drawPos + barrelPos,
drawPos + barrelPos + new Vector2((float)Math.Cos((maxRotation + minRotation) / 2), (float)Math.Sin((maxRotation + minRotation) / 2)) * 60.0f,
Color.LightGreen);
}
public void ClientRead(ServerNetObject type, NetBuffer msg, float sendingTime)
{
UInt16 projectileID = msg.ReadUInt16();
Item projectile = Entity.FindEntityByID(projectileID) as Item;
if (projectile == null)
{
DebugConsole.ThrowError("Failed to launch a projectile - item with the ID \"" + projectileID + " not found");
return;
}
Launch(projectile);
PlaySound(ActionType.OnUse, item.WorldPosition);
}
}
}

View File

@@ -0,0 +1,75 @@
using Barotrauma.Networking;
using FarseerPhysics;
using FarseerPhysics.Dynamics;
using FarseerPhysics.Dynamics.Joints;
using FarseerPhysics.Factories;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
namespace Barotrauma.Items.Components
{
partial class DockingPort : ItemComponent, IDrawableComponent, IServerSerializable
{
public void Draw(SpriteBatch spriteBatch, bool editing)
{
if (dockingState == 0.0f) return;
Vector2 drawPos = item.DrawPosition;
drawPos.Y = -drawPos.Y;
var rect = overlaySprite.SourceRect;
if (IsHorizontal)
{
drawPos.Y -= rect.Height / 2;
if (dockingDir == 1)
{
spriteBatch.Draw(overlaySprite.Texture,
drawPos,
new Rectangle(
rect.Center.X + (int)(rect.Width / 2 * (1.0f - dockingState)), rect.Y,
(int)(rect.Width / 2 * dockingState), rect.Height), Color.White);
}
else
{
spriteBatch.Draw(overlaySprite.Texture,
drawPos - Vector2.UnitX * (rect.Width / 2 * dockingState),
new Rectangle(
rect.X, rect.Y,
(int)(rect.Width / 2 * dockingState), rect.Height), Color.White);
}
}
else
{
drawPos.X -= rect.Width / 2;
if (dockingDir == 1)
{
spriteBatch.Draw(overlaySprite.Texture,
drawPos - Vector2.UnitY * (rect.Height / 2 * dockingState),
new Rectangle(
rect.X, rect.Y,
rect.Width, (int)(rect.Height / 2 * dockingState)), Color.White);
}
else
{
spriteBatch.Draw(overlaySprite.Texture,
drawPos,
new Rectangle(
rect.X, rect.Y + rect.Height / 2 + (int)(rect.Height / 2 * (1.0f - dockingState)),
rect.Width, (int)(rect.Height / 2 * dockingState)), Color.White);
}
}
}
}
}

View File

@@ -9,58 +9,20 @@ using System.Xml.Linq;
namespace Barotrauma
{
class FixRequirement
partial class FixRequirement
{
string name;
private static GUIFrame frame;
List<Skill> requiredSkills;
List<string> requiredItems;
public bool Fixed;
public FixRequirement(XElement element)
{
name = ToolBox.GetAttributeString(element, "name", "");
requiredSkills = new List<Skill>();
requiredItems = new List<string>();
foreach (XElement subElement in element.Elements())
{
switch (subElement.Name.ToString().ToLowerInvariant())
{
case "skill":
string skillName = ToolBox.GetAttributeString(subElement, "name", "");
int level = ToolBox.GetAttributeInt(subElement, "level", 1);
requiredSkills.Add(new Skill(skillName, level));
break;
case "item":
string itemName = ToolBox.GetAttributeString(subElement, "name", "");
requiredItems.Add(itemName);
break;
}
}
}
public bool CanBeFixed(Character character, GUIComponent reqFrame = null)
{
if (character == null) return false;
bool success = true;
foreach (string itemName in requiredItems)
{
Item item = character.Inventory.FindItem(itemName);
bool itemFound = (item != null);
if (!itemFound) success = false;
if (reqFrame != null)
{
GUIComponent component = reqFrame.children.Find(c => c.UserData as string == itemName);
GUIComponent component = reqFrame.children.Find(c => c.UserData as string == itemName);
GUITextBlock text = component as GUITextBlock;
if (text != null) text.TextColor = itemFound ? Color.LightGreen : Color.Red;
}
@@ -71,8 +33,6 @@ namespace Barotrauma
float characterSkill = character.GetSkillLevel(skill.Name);
bool sufficientSkill = characterSkill >= skill.Level;
if (!sufficientSkill) success = false;
if (reqFrame != null)
{
GUIComponent component = reqFrame.children.Find(c => c.UserData as Skill == skill);
@@ -81,9 +41,9 @@ namespace Barotrauma
}
}
return success;
return CanBeFixed(character);
}
private static void CreateGUIFrame(Item item)
{
int width = 400, height = 500;
@@ -93,13 +53,13 @@ namespace Barotrauma
frame.Padding = new Vector4(20.0f, 20.0f, 20.0f, 20.0f);
frame.UserData = item;
new GUITextBlock(new Rectangle(0,0,200,20), "Attempting to fix " + item.Name, "", frame);
new GUITextBlock(new Rectangle(0, 0, 200, 20), "Attempting to fix " + item.Name, "", frame);
y = y + 40;
foreach (FixRequirement requirement in item.FixRequirements)
{
GUIFrame reqFrame = new GUIFrame(
new Rectangle(0, y, 0, 20 + Math.Max(requirement.requiredItems.Count, requirement.requiredSkills.Count) * 15),
new Rectangle(0, y, 0, 20 + Math.Max(requirement.requiredItems.Count, requirement.requiredSkills.Count) * 15),
Color.Transparent, null, frame);
reqFrame.UserData = requirement;
@@ -108,7 +68,7 @@ namespace Barotrauma
fixButton.OnClicked = FixButtonPressed;
fixButton.UserData = requirement;
var tickBox = new GUITickBox(new Rectangle(70, 0, 20,20), requirement.name, Alignment.Left, reqFrame);
var tickBox = new GUITickBox(new Rectangle(70, 0, 20, 20), requirement.name, Alignment.Left, reqFrame);
tickBox.Enabled = false;
int y2 = 20;
@@ -117,10 +77,10 @@ namespace Barotrauma
var itemBlock = new GUITextBlock(new Rectangle(30, y2, 200, 15), itemName, "", reqFrame);
itemBlock.Font = GUI.SmallFont;
itemBlock.UserData = itemName;
y2 += 15;
}
y2 = 20;
foreach (Skill skill in requirement.requiredSkills)
{
@@ -148,7 +108,7 @@ namespace Barotrauma
if (GameMain.Client != null)
{
GameMain.Client.CreateEntityEvent(item, new object[] { NetEntityEvent.Type.Repair, item.FixRequirements.IndexOf(requirement)});
GameMain.Client.CreateEntityEvent(item, new object[] { NetEntityEvent.Type.Repair, item.FixRequirements.IndexOf(requirement) });
}
else if (GameMain.Server != null)
{
@@ -159,7 +119,7 @@ namespace Barotrauma
{
requirement.Fixed = true;
}
return true;
}

View File

@@ -0,0 +1,203 @@
using System.Linq;
using Lidgren.Network;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Barotrauma.Networking;
using System;
using System.Collections.Generic;
using Barotrauma.Items.Components;
namespace Barotrauma
{
partial class InventorySlot
{
public GUIComponent.ComponentState State;
public bool IsHighlighted
{
get
{
return State == GUIComponent.ComponentState.Hover;
}
}
public Color Color;
public Color BorderHighlightColor;
private CoroutineHandle BorderHighlightCoroutine;
public void ShowBorderHighlight(Color color, float fadeInDuration, float fadeOutDuration)
{
if (BorderHighlightCoroutine != null)
{
BorderHighlightCoroutine = null;
}
BorderHighlightCoroutine = CoroutineManager.StartCoroutine(UpdateBorderHighlight(color, fadeInDuration, fadeOutDuration));
}
private IEnumerable<object> UpdateBorderHighlight(Color color, float fadeInDuration, float fadeOutDuration)
{
float t = 0.0f;
while (t < fadeInDuration + fadeOutDuration)
{
BorderHighlightColor = (t < fadeInDuration) ?
Color.Lerp(Color.Transparent, color, t / fadeInDuration) :
Color.Lerp(color, Color.Transparent, (t - fadeInDuration) / fadeOutDuration);
t += CoroutineManager.DeltaTime;
yield return CoroutineStatus.Running;
}
yield return CoroutineStatus.Success;
}
}
partial class Inventory
{
public virtual void Draw(SpriteBatch spriteBatch, bool subInventory = false)
{
if (slots == null || isSubInventory != subInventory) return;
for (int i = 0; i < capacity; i++)
{
if (slots[i].Disabled) continue;
//don't draw the item if it's being dragged out of the slot
bool drawItem = draggingItem == null || draggingItem != Items[i] || slots[i].IsHighlighted;
DrawSlot(spriteBatch, slots[i], Items[i], drawItem);
}
if (draggingItem != null &&
(draggingSlot == null || (!draggingSlot.Rect.Contains(PlayerInput.MousePosition) && draggingItem.ParentInventory == this)))
{
Rectangle dragRect = new Rectangle(
(int)PlayerInput.MousePosition.X - 10,
(int)PlayerInput.MousePosition.Y - 10,
40, 40);
DrawSlot(spriteBatch, new InventorySlot(dragRect), draggingItem);
}
for (int i = 0; i < capacity; i++)
{
if (slots[i].IsHighlighted && !slots[i].Disabled && Items[i] != null)
{
string toolTip = "";
if (GameMain.DebugDraw)
{
toolTip = Items[i].ToString();
}
else
{
toolTip = string.IsNullOrEmpty(Items[i].Description) ?
Items[i].Name :
Items[i].Name + '\n' + Items[i].Description;
}
DrawToolTip(spriteBatch, toolTip, slots[i].Rect);
break;
}
}
}
protected void DrawToolTip(SpriteBatch spriteBatch, string toolTip, Rectangle highlightedSlot)
{
int maxWidth = 300;
toolTip = ToolBox.WrapText(toolTip, maxWidth, GUI.Font);
Vector2 textSize = GUI.Font.MeasureString(toolTip);
Vector2 rectSize = textSize * 1.2f;
Vector2 pos = new Vector2(highlightedSlot.Right, highlightedSlot.Y - rectSize.Y);
pos.X = (int)(pos.X + 3);
pos.Y = (int)pos.Y;
GUI.DrawRectangle(spriteBatch, pos, rectSize, Color.Black * 0.8f, true);
GUI.Font.DrawString(spriteBatch, toolTip,
new Vector2((int)(pos.X + rectSize.X * 0.5f), (int)(pos.Y + rectSize.Y * 0.5f)),
Color.White, 0.0f,
new Vector2((int)(textSize.X * 0.5f), (int)(textSize.Y * 0.5f)),
1.0f, SpriteEffects.None, 0.0f);
}
public void DrawSubInventory(SpriteBatch spriteBatch, int slotIndex)
{
var item = Items[slotIndex];
if (item == null) return;
var container = item.GetComponent<ItemContainer>();
if (container == null) return;
if (container.Inventory.slots == null || !container.Inventory.isSubInventory) return;
int itemCapacity = container.Capacity;
#if DEBUG
System.Diagnostics.Debug.Assert(slotIndex >= 0 && slotIndex < Items.Length);
#else
if (slotIndex < 0 || slotIndex >= Items.Length) return;
#endif
var slot = slots[slotIndex];
Rectangle containerRect = new Rectangle(slot.Rect.X - 5, slot.Rect.Y - (40 + 10) * itemCapacity - 5,
slot.Rect.Width + 10, slot.Rect.Height + (40 + 10) * itemCapacity + 10);
GUI.DrawRectangle(spriteBatch, new Rectangle(containerRect.X, containerRect.Y, containerRect.Width, containerRect.Height - slot.Rect.Height - 5), Color.Black * 0.8f, true);
GUI.DrawRectangle(spriteBatch, containerRect, Color.White);
container.Inventory.Draw(spriteBatch, true);
if (!containerRect.Contains(PlayerInput.MousePosition))
{
if (draggingItem == null || draggingItem.Container != item) selectedSlot = -1;
}
}
protected void DrawSlot(SpriteBatch spriteBatch, InventorySlot slot, Item item, bool drawItem = true)
{
Rectangle rect = slot.Rect;
GUI.DrawRectangle(spriteBatch, rect, (slot.IsHighlighted ? Color.Red * 0.4f : slot.Color), true);
if (item != null && drawItem)
{
if (item.Condition < 100.0f)
{
GUI.DrawRectangle(spriteBatch, new Rectangle(rect.X, rect.Bottom - 8, rect.Width, 8), Color.Black * 0.8f, true);
GUI.DrawRectangle(spriteBatch,
new Rectangle(rect.X, rect.Bottom - 8, (int)(rect.Width * item.Condition / 100.0f), 8),
Color.Lerp(Color.Red, Color.Green, item.Condition / 100.0f) * 0.8f, true);
}
var containedItems = item.ContainedItems;
if (containedItems != null && containedItems.Length == 1 && containedItems[0].Condition < 100.0f)
{
GUI.DrawRectangle(spriteBatch, new Rectangle(rect.X, rect.Y, rect.Width, 8), Color.Black * 0.8f, true);
GUI.DrawRectangle(spriteBatch,
new Rectangle(rect.X, rect.Y, (int)(rect.Width * containedItems[0].Condition / 100.0f), 8),
Color.Lerp(Color.Red, Color.Green, containedItems[0].Condition / 100.0f) * 0.8f, true);
}
}
GUI.DrawRectangle(spriteBatch, rect, (slot.IsHighlighted ? Color.Red * 0.4f : slot.Color), false);
if (slot.BorderHighlightColor != Color.Transparent)
{
Rectangle highlightRect = slot.Rect;
highlightRect.Inflate(3, 3);
GUI.DrawRectangle(spriteBatch, highlightRect, slot.BorderHighlightColor, false, 0, 5);
}
if (item == null || !drawItem) return;
item.Sprite.Draw(spriteBatch, new Vector2(rect.X + rect.Width / 2, rect.Y + rect.Height / 2), item.Color);
}
}
}

View File

@@ -0,0 +1,575 @@
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 System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Xml.Linq;
namespace Barotrauma
{
partial class Item : MapEntity, IDamageable, IPropertyObject, IServerSerializable, IClientSerializable
{
public override Sprite Sprite
{
get { return prefab.sprite; }
}
public override void Draw(SpriteBatch spriteBatch, bool editing, bool back = true)
{
if (!Visible) return;
Color color = (IsSelected && editing) ? color = Color.Red : spriteColor;
if (isHighlighted) color = Color.Orange;
SpriteEffects oldEffects = prefab.sprite.effects;
prefab.sprite.effects ^= SpriteEffects;
if (prefab.sprite != null)
{
float depth = Sprite.Depth;
depth += (ID % 255) * 0.000001f;
if (body == null)
{
if (prefab.ResizeHorizontal || prefab.ResizeVertical || SpriteEffects.HasFlag(SpriteEffects.FlipHorizontally) || SpriteEffects.HasFlag(SpriteEffects.FlipVertically))
{
prefab.sprite.DrawTiled(spriteBatch, new Vector2(DrawPosition.X - rect.Width / 2, -(DrawPosition.Y + rect.Height / 2)), new Vector2(rect.Width, rect.Height), color);
}
else
{
prefab.sprite.Draw(spriteBatch, new Vector2(DrawPosition.X, -DrawPosition.Y), color, 0.0f, 1.0f, SpriteEffects.None, depth);
}
}
else if (body.Enabled)
{
var holdable = GetComponent<Holdable>();
if (holdable != null && holdable.Picker?.AnimController != null)
{
if (holdable.Picker.SelectedItems[0] == this)
{
depth = holdable.Picker.AnimController.GetLimb(LimbType.RightHand).sprite.Depth + 0.000001f;
}
else if (holdable.Picker.SelectedItems[1] == this)
{
depth = holdable.Picker.AnimController.GetLimb(LimbType.LeftArm).sprite.Depth - 0.000001f;
}
body.Draw(spriteBatch, prefab.sprite, color, depth);
}
else
{
body.Draw(spriteBatch, prefab.sprite, color, depth);
}
}
}
prefab.sprite.effects = oldEffects;
List<IDrawableComponent> staticDrawableComponents = new List<IDrawableComponent>(drawableComponents); //static list to compensate for drawable toggling
for (int i = 0; i < staticDrawableComponents.Count; i++)
{
staticDrawableComponents[i].Draw(spriteBatch, editing);
}
if (GameMain.DebugDraw && aiTarget != null) aiTarget.Draw(spriteBatch);
if (!editing || (body != null && !body.Enabled))
{
return;
}
if (IsSelected || isHighlighted)
{
GUI.DrawRectangle(spriteBatch, new Vector2(DrawPosition.X - rect.Width / 2, -(DrawPosition.Y + rect.Height / 2)), new Vector2(rect.Width, rect.Height), Color.Green, false, 0, (int)Math.Max((1.5f / GameScreen.Selected.Cam.Zoom), 1.0f));
foreach (Rectangle t in prefab.Triggers)
{
Rectangle transformedTrigger = TransformTrigger(t);
Vector2 rectWorldPos = new Vector2(transformedTrigger.X, transformedTrigger.Y);
if (Submarine != null) rectWorldPos += Submarine.Position;
rectWorldPos.Y = -rectWorldPos.Y;
GUI.DrawRectangle(spriteBatch,
rectWorldPos,
new Vector2(transformedTrigger.Width, transformedTrigger.Height),
Color.Green,
false,
0,
(int)Math.Max((1.5f / GameScreen.Selected.Cam.Zoom), 1.0f));
}
}
if (!ShowLinks) return;
foreach (MapEntity e in linkedTo)
{
GUI.DrawLine(spriteBatch,
new Vector2(WorldPosition.X, -WorldPosition.Y),
new Vector2(e.WorldPosition.X, -e.WorldPosition.Y),
Color.Red * 0.3f);
}
}
public override void UpdateEditing(Camera cam)
{
if (editingHUD == null || editingHUD.UserData as Item != this)
{
editingHUD = CreateEditingHUD(Screen.Selected != GameMain.EditMapScreen);
}
editingHUD.Update((float)Timing.Step);
if (Screen.Selected != GameMain.EditMapScreen) return;
if (!prefab.IsLinkable) return;
if (!PlayerInput.LeftButtonClicked() || !PlayerInput.KeyDown(Keys.Space)) return;
Vector2 position = cam.ScreenToWorld(PlayerInput.MousePosition);
foreach (MapEntity entity in mapEntityList)
{
if (entity == this || !entity.IsHighlighted) continue;
if (linkedTo.Contains(entity)) continue;
if (!entity.IsMouseOn(position)) continue;
linkedTo.Add(entity);
if (entity.IsLinkable && entity.linkedTo != null) entity.linkedTo.Add(this);
}
}
public override void DrawEditing(SpriteBatch spriteBatch, Camera cam)
{
if (editingHUD != null) editingHUD.Draw(spriteBatch);
}
private GUIComponent CreateEditingHUD(bool inGame = false)
{
List<ObjectProperty> editableProperties = inGame ? GetProperties<InGameEditable>() : GetProperties<Editable>();
int requiredItemCount = 0;
if (!inGame)
{
foreach (ItemComponent ic in components)
{
requiredItemCount += ic.requiredItems.Count;
}
}
int width = 450;
int height = 80 + requiredItemCount * 20;
int x = GameMain.GraphicsWidth / 2 - width / 2, y = 10;
foreach (var objectProperty in editableProperties)
{
var editable = objectProperty.Attributes.OfType<Editable>().FirstOrDefault();
if (editable != null) height += (int)(Math.Ceiling(editable.MaxLength / 40.0f) * 18.0f) + 5;
}
editingHUD = new GUIFrame(new Rectangle(x, y, width, height), "");
editingHUD.Padding = new Vector4(10, 10, 0, 0);
editingHUD.UserData = this;
new GUITextBlock(new Rectangle(0, 0, 100, 20), prefab.Name, "",
Alignment.TopLeft, Alignment.TopLeft, editingHUD, false, GUI.LargeFont);
y += 25;
if (!inGame)
{
if (prefab.IsLinkable)
{
new GUITextBlock(new Rectangle(0, 5, 0, 20), "Hold space to link to another item",
"", Alignment.TopRight, Alignment.TopRight, editingHUD).Font = GUI.SmallFont;
}
foreach (ItemComponent ic in components)
{
foreach (RelatedItem relatedItem in ic.requiredItems)
{
new GUITextBlock(new Rectangle(0, y, 100, 15), ic.Name + ": " + relatedItem.Type.ToString() + " required", "", Alignment.TopLeft, Alignment.CenterLeft, editingHUD, false, GUI.SmallFont);
GUITextBox namesBox = new GUITextBox(new Rectangle(-10, y, 160, 15), Alignment.Right, "", editingHUD);
namesBox.Font = GUI.SmallFont;
PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(relatedItem);
PropertyDescriptor property = properties.Find("JoinedNames", false);
namesBox.Text = relatedItem.JoinedNames;
namesBox.UserData = new ObjectProperty(property, relatedItem);
namesBox.OnEnterPressed = EnterProperty;
namesBox.OnTextChanged = PropertyChanged;
y += 20;
}
}
if (requiredItemCount > 0) y += 10;
}
foreach (var objectProperty in editableProperties)
{
int boxHeight = 18;
var editable = objectProperty.Attributes.OfType<Editable>().FirstOrDefault();
if (editable != null) boxHeight = (int)(Math.Ceiling(editable.MaxLength / 40.0f) * 18.0f);
object value = objectProperty.GetValue();
if (value is bool)
{
GUITickBox propertyTickBox = new GUITickBox(new Rectangle(10, y, 18, 18), objectProperty.Name,
Alignment.Left, editingHUD);
propertyTickBox.Font = GUI.SmallFont;
propertyTickBox.Selected = (bool)value;
propertyTickBox.UserData = objectProperty;
propertyTickBox.OnSelected = EnterProperty;
}
else
{
new GUITextBlock(new Rectangle(0, y, 100, 18), objectProperty.Name, "", Alignment.TopLeft, Alignment.Left, editingHUD, false, GUI.SmallFont);
GUITextBox propertyBox = new GUITextBox(new Rectangle(180, y, 250, boxHeight), "", editingHUD);
propertyBox.Font = GUI.SmallFont;
if (boxHeight > 18) propertyBox.Wrap = true;
if (value != null)
{
if (value is float)
{
propertyBox.Text = ((float)value).ToString("G", System.Globalization.CultureInfo.InvariantCulture);
}
else
{
propertyBox.Text = value.ToString();
}
}
propertyBox.UserData = objectProperty;
propertyBox.OnEnterPressed = EnterProperty;
propertyBox.OnTextChanged = PropertyChanged;
}
y = y + boxHeight + 5;
}
return editingHUD;
}
public virtual void UpdateHUD(Camera cam, Character character)
{
if (condition <= 0.0f)
{
FixRequirement.UpdateHud(this, character);
return;
}
if (HasInGameEditableProperties)
{
UpdateEditing(cam);
}
foreach (ItemComponent ic in components)
{
if (ic.CanBeSelected) ic.UpdateHUD(character);
}
}
public virtual void DrawHUD(SpriteBatch spriteBatch, Camera cam, Character character)
{
if (condition <= 0.0f)
{
FixRequirement.DrawHud(spriteBatch, this, character);
return;
}
if (HasInGameEditableProperties)
{
DrawEditing(spriteBatch, cam);
}
foreach (ItemComponent ic in components)
{
if (ic.CanBeSelected) ic.DrawHUD(spriteBatch, character);
}
}
public override void AddToGUIUpdateList()
{
if (Screen.Selected is EditMapScreen)
{
if (editingHUD != null) editingHUD.AddToGUIUpdateList();
}
else
{
if (HasInGameEditableProperties)
{
if (editingHUD != null) editingHUD.AddToGUIUpdateList();
}
}
if (Character.Controlled != null && Character.Controlled.SelectedConstruction == this)
{
if (condition <= 0.0f)
{
FixRequirement.AddToGUIUpdateList();
return;
}
foreach (ItemComponent ic in components)
{
if (ic.CanBeSelected) ic.AddToGUIUpdateList();
}
}
}
private bool EnterProperty(GUITickBox tickBox)
{
var objectProperty = tickBox.UserData as ObjectProperty;
if (objectProperty == null) return false;
objectProperty.TrySetValue(tickBox.Selected);
return true;
}
private bool EnterProperty(GUITextBox textBox, string text)
{
textBox.Color = Color.DarkGreen;
var objectProperty = textBox.UserData as ObjectProperty;
if (objectProperty == null) return false;
object prevValue = objectProperty.GetValue();
textBox.Deselect();
if (objectProperty.TrySetValue(text))
{
textBox.Text = text;
if (GameMain.Server != null)
{
GameMain.Server.CreateEntityEvent(this, new object[] { NetEntityEvent.Type.ChangeProperty, objectProperty });
}
else if (GameMain.Client != null)
{
GameMain.Client.CreateEntityEvent(this, new object[] { NetEntityEvent.Type.ChangeProperty, objectProperty });
}
return true;
}
else
{
if (prevValue != null)
{
textBox.Text = prevValue.ToString();
}
return false;
}
}
private bool PropertyChanged(GUITextBox textBox, string text)
{
textBox.Color = Color.Red;
return true;
}
public override XElement Save(XElement parentElement)
{
XElement element = new XElement("Item");
element.Add(new XAttribute("name", prefab.Name),
new XAttribute("ID", ID));
System.Diagnostics.Debug.Assert(Submarine != null);
if (ResizeHorizontal || ResizeVertical)
{
element.Add(new XAttribute("rect",
(int)(rect.X - Submarine.HiddenSubPosition.X) + "," +
(int)(rect.Y - Submarine.HiddenSubPosition.Y) + "," +
rect.Width + "," + rect.Height));
}
else
{
element.Add(new XAttribute("rect",
(int)(rect.X - Submarine.HiddenSubPosition.X) + "," +
(int)(rect.Y - Submarine.HiddenSubPosition.Y)));
}
if (linkedTo != null && linkedTo.Count > 0)
{
string[] linkedToIDs = new string[linkedTo.Count];
for (int i = 0; i < linkedTo.Count; i++)
{
linkedToIDs[i] = linkedTo[i].ID.ToString();
}
element.Add(new XAttribute("linked", string.Join(",", linkedToIDs)));
}
ObjectProperty.SaveProperties(this, element);
foreach (ItemComponent ic in components)
{
ic.Save(element);
}
parentElement.Add(element);
return element;
}
public void ClientRead(ServerNetObject type, NetBuffer msg, float sendingTime)
{
if (type == ServerNetObject.ENTITY_POSITION)
{
ClientReadPosition(type, msg, sendingTime);
return;
}
NetEntityEvent.Type eventType =
(NetEntityEvent.Type)msg.ReadRangedInteger(0, Enum.GetValues(typeof(NetEntityEvent.Type)).Length - 1);
switch (eventType)
{
case NetEntityEvent.Type.ComponentState:
int componentIndex = msg.ReadRangedInteger(0, components.Count - 1);
(components[componentIndex] as IServerSerializable).ClientRead(type, msg, sendingTime);
break;
case NetEntityEvent.Type.InventoryState:
ownInventory.ClientRead(type, msg, sendingTime);
break;
case NetEntityEvent.Type.Status:
condition = msg.ReadRangedSingle(0.0f, 100.0f, 8);
if (FixRequirements.Count > 0)
{
if (Condition <= 0.0f)
{
for (int i = 0; i < FixRequirements.Count; i++)
FixRequirements[i].Fixed = msg.ReadBoolean();
}
else
{
for (int i = 0; i < FixRequirements.Count; i++)
FixRequirements[i].Fixed = true;
}
}
break;
case NetEntityEvent.Type.ApplyStatusEffect:
ActionType actionType = (ActionType)msg.ReadRangedInteger(0, Enum.GetValues(typeof(ActionType)).Length - 1);
ushort targetID = msg.ReadUInt16();
Character target = FindEntityByID(targetID) as Character;
ApplyStatusEffects(actionType, (float)Timing.Step, target, true);
break;
case NetEntityEvent.Type.ChangeProperty:
ReadPropertyChange(msg);
break;
}
}
public void ClientWrite(NetBuffer msg, object[] extraData = null)
{
if (extraData == null || extraData.Length == 0 || !(extraData[0] is NetEntityEvent.Type))
{
return;
}
NetEntityEvent.Type eventType = (NetEntityEvent.Type)extraData[0];
msg.WriteRangedInteger(0, Enum.GetValues(typeof(NetEntityEvent.Type)).Length - 1, (int)eventType);
switch (eventType)
{
case NetEntityEvent.Type.ComponentState:
int componentIndex = (int)extraData[1];
msg.WriteRangedInteger(0, components.Count - 1, componentIndex);
(components[componentIndex] as IClientSerializable).ClientWrite(msg, extraData);
break;
case NetEntityEvent.Type.InventoryState:
ownInventory.ClientWrite(msg, extraData);
break;
case NetEntityEvent.Type.Repair:
if (FixRequirements.Count > 0)
{
int requirementIndex = (int)extraData[1];
msg.WriteRangedInteger(0, FixRequirements.Count - 1, requirementIndex);
}
break;
case NetEntityEvent.Type.ApplyStatusEffect:
//no further data needed, the server applies the effect
//on the character of the client who sent the message
break;
case NetEntityEvent.Type.ChangeProperty:
WritePropertyChange(msg, extraData);
break;
}
msg.WritePadBits();
}
public void ClientReadPosition(ServerNetObject type, NetBuffer msg, float sendingTime)
{
Vector2 newPosition = new Vector2(msg.ReadFloat(), msg.ReadFloat());
float newRotation = msg.ReadRangedSingle(0.0f, MathHelper.TwoPi, 7);
bool awake = msg.ReadBoolean();
Vector2 newVelocity = Vector2.Zero;
if (awake)
{
newVelocity = new Vector2(
msg.ReadRangedSingle(-MaxVel, MaxVel, 12),
msg.ReadRangedSingle(-MaxVel, MaxVel, 12));
}
if (body == null)
{
DebugConsole.ThrowError("Received a position update for an item with no physics body (" + Name + ")");
return;
}
body.FarseerBody.Awake = awake;
if (body.FarseerBody.Awake)
{
if ((newVelocity - body.LinearVelocity).Length() > 8.0f) body.LinearVelocity = newVelocity;
}
else
{
body.FarseerBody.Enabled = false;
}
if ((newPosition - SimPosition).Length() > body.LinearVelocity.Length() * 2.0f)
{
body.SetTransform(newPosition, newRotation);
Vector2 displayPos = ConvertUnits.ToDisplayUnits(body.SimPosition);
rect.X = (int)(displayPos.X - rect.Width / 2.0f);
rect.Y = (int)(displayPos.Y + rect.Height / 2.0f);
}
}
public void CreateClientEvent<T>(T ic) where T : ItemComponent, IClientSerializable
{
if (GameMain.Client == null) return;
int index = components.IndexOf(ic);
if (index == -1) return;
GameMain.Client.CreateEntityEvent(this, new object[] { NetEntityEvent.Type.ComponentState, index });
}
}
}

View File

@@ -0,0 +1,53 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Xml.Linq;
using FarseerPhysics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
namespace Barotrauma
{
partial class ItemPrefab : MapEntityPrefab
{
public override void DrawPlacing(SpriteBatch spriteBatch, Camera cam)
{
Vector2 position = Submarine.MouseToWorldGrid(cam, Submarine.MainSub);
if (PlayerInput.RightButtonClicked())
{
selected = null;
return;
}
if (!resizeHorizontal && !resizeVertical)
{
sprite.Draw(spriteBatch, new Vector2(position.X + sprite.size.X / 2.0f, -position.Y + sprite.size.Y / 2.0f), SpriteColor);
}
else
{
Vector2 placeSize = size;
if (placePosition == Vector2.Zero)
{
if (PlayerInput.LeftButtonHeld()) placePosition = position;
}
else
{
if (resizeHorizontal)
placeSize.X = Math.Max(position.X - placePosition.X, size.X);
if (resizeVertical)
placeSize.Y = Math.Max(placePosition.Y - position.Y, size.Y);
position = placePosition;
}
if (sprite != null) sprite.DrawTiled(spriteBatch, new Vector2(position.X, -position.Y), placeSize, SpriteColor);
}
//if (PlayerInput.GetMouseState.RightButton == ButtonState.Pressed) selected = null;
}
}
}

View File

@@ -0,0 +1,53 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using FarseerPhysics;
using FarseerPhysics.Collision.Shapes;
using FarseerPhysics.Common;
using FarseerPhysics.Dynamics;
using FarseerPhysics.Dynamics.Joints;
using FarseerPhysics.Factories;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace Barotrauma.Items.Components
{
partial class Rope : ItemComponent, IDrawableComponent
{
public void Draw(SpriteBatch spriteBatch, bool editing = false)
{
if (!IsActive) return;
RevoluteJoint firstJoint = null;
for (int i = 0; i < ropeBodies.Length - 1; i++)
{
if (!ropeBodies[i].Enabled) continue;
if (firstJoint == null) firstJoint = ropeJoints[i];
DrawSection(spriteBatch, ropeJoints[i].WorldAnchorA, ropeJoints[i + 1].WorldAnchorA, i);
}
if (gunJoint == null || firstJoint == null) return;
DrawSection(spriteBatch, gunJoint.WorldAnchorA, firstJoint.WorldAnchorA, 0);
}
private void DrawSection(SpriteBatch spriteBatch, Vector2 start, Vector2 end, int i)
{
start.Y = -start.Y;
end.Y = -end.Y;
spriteBatch.Draw(sprite.Texture,
ConvertUnits.ToDisplayUnits(start), null, Color.White,
MathUtils.VectorToAngle(end - start),
new Vector2(0.0f, sprite.size.Y / 2.0f),
new Vector2((ConvertUnits.ToDisplayUnits(Vector2.Distance(start, end))) / sprite.Texture.Width, 1.0f),
SpriteEffects.None,
sprite.Depth + i * 0.00001f);
}
}
}

View File

@@ -0,0 +1,73 @@
using Microsoft.Xna.Framework;
using Barotrauma.Lights;
using System;
using System.Collections.Generic;
using System.Xml.Linq;
using Barotrauma.Networking;
using FarseerPhysics;
namespace Barotrauma
{
partial class Explosion
{
partial void ExplodeProjSpecific(Vector2 worldPosition,Hull hull)
{
if (shockwave)
{
GameMain.ParticleManager.CreateParticle("shockwave", worldPosition,
Vector2.Zero, 0.0f, hull);
}
for (int i = 0; i < attack.Range * 0.1f; i++)
{
Vector2 bubblePos = Rand.Vector(attack.Range * 0.5f);
GameMain.ParticleManager.CreateParticle("bubbles", worldPosition + bubblePos,
bubblePos, 0.0f, hull);
if (sparks)
{
GameMain.ParticleManager.CreateParticle("spark", worldPosition,
Rand.Vector(Rand.Range(500.0f, 800.0f)), 0.0f, hull);
}
if (flames)
{
GameMain.ParticleManager.CreateParticle("explosionfire", ClampParticlePos(worldPosition + Rand.Vector(50f), hull),
Rand.Vector(Rand.Range(50.0f, 100.0f)), 0.0f, hull);
}
if (smoke)
{
GameMain.ParticleManager.CreateParticle("smoke", ClampParticlePos(worldPosition + Rand.Vector(50f), hull),
Rand.Vector(Rand.Range(1.0f, 10.0f)), 0.0f, hull);
}
}
float displayRange = attack.Range;
if (displayRange < 0.1f) return;
var light = new LightSource(worldPosition, displayRange, Color.LightYellow, null);
CoroutineManager.StartCoroutine(DimLight(light));
}
private IEnumerable<object> DimLight(LightSource light)
{
float currBrightness = 1.0f;
float startRange = light.Range;
while (light.Color.A > 0.0f)
{
light.Color = new Color(light.Color.R, light.Color.G, light.Color.B, currBrightness);
light.Range = startRange * currBrightness;
currBrightness -= CoroutineManager.DeltaTime * 20.0f;
yield return CoroutineStatus.Running;
}
light.Remove();
yield return CoroutineStatus.Success;
}
}
}

View File

@@ -0,0 +1,86 @@
using Barotrauma.Lights;
using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Barotrauma.Networking;
namespace Barotrauma
{
partial class FireSource
{
static Sound fireSoundBasic, fireSoundLarge;
private LightSource lightSource;
partial void UpdateProjSpecific(float growModifier)
{
if (hull.FireSources.Any(fs => fs != this && fs.size.X > size.X))
{
if (basicSoundIndex > 0)
{
Sounds.SoundManager.Stop(basicSoundIndex);
basicSoundIndex = -1;
}
if (largeSoundIndex > 0)
{
Sounds.SoundManager.Stop(largeSoundIndex);
largeSoundIndex = -1;
}
}
else
{
if (fireSoundBasic != null)
{
basicSoundIndex = fireSoundBasic.Loop(basicSoundIndex,
Math.Min(size.X / 100.0f, 1.0f), WorldPosition + size / 2.0f, 1000.0f);
}
if (fireSoundLarge != null)
{
largeSoundIndex = fireSoundLarge.Loop(largeSoundIndex,
MathHelper.Clamp((size.X - 200.0f) / 100.0f, 0.0f, 1.0f), WorldPosition + size / 2.0f, 1000.0f);
}
}
float count = Rand.Range(0.0f, size.X / 50.0f);
for (int i = 0; i < count; i++)
{
Vector2 particlePos = new Vector2(
WorldPosition.X + Rand.Range(0.0f, size.X),
Rand.Range(WorldPosition.Y - size.Y, WorldPosition.Y + 20.0f));
Vector2 particleVel = new Vector2(
(particlePos.X - (WorldPosition.X + size.X / 2.0f)),
(float)Math.Sqrt(size.X) * Rand.Range(0.0f, 15.0f) * growModifier);
var particle = GameMain.ParticleManager.CreateParticle("flame",
particlePos, particleVel, 0.0f, hull);
if (particle == null) continue;
//make some of the particles create another firesource when they enter another hull
if (Rand.Int(20) == 1) particle.OnChangeHull = OnChangeHull;
particle.Size *= MathHelper.Clamp(size.X / 60.0f * Math.Max(hull.Oxygen / hull.FullVolume, 0.4f), 0.5f, 1.0f);
if (Rand.Int(5) == 1)
{
var smokeParticle = GameMain.ParticleManager.CreateParticle("smoke",
particlePos, new Vector2(particleVel.X, particleVel.Y * 0.1f), 0.0f, hull);
if (smokeParticle != null)
{
smokeParticle.Size *= MathHelper.Clamp(size.X / 100.0f * Math.Max(hull.Oxygen / hull.FullVolume, 0.4f), 0.5f, 1.0f);
}
}
}
lightSource.Range = Math.Max(size.X, size.Y) * 10.0f / 2.0f;
lightSource.Color = new Color(1.0f, 0.45f, 0.3f) * Rand.Range(0.8f, 1.0f);
lightSource.Position = position + Vector2.UnitY * 30.0f;
}
}
}

View File

@@ -0,0 +1,95 @@
using System;
using System.Collections.Generic;
using System.Xml.Linq;
using FarseerPhysics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System.Collections.ObjectModel;
using Barotrauma.Items.Components;
namespace Barotrauma
{
partial class Gap : MapEntity
{
public override void Draw(SpriteBatch sb, bool editing, bool back = true)
{
if (GameMain.DebugDraw)
{
Vector2 center = new Vector2(WorldRect.X + rect.Width / 2.0f, -(WorldRect.Y - rect.Height / 2.0f));
GUI.DrawLine(sb, center, center + new Vector2(flowForce.X, -flowForce.Y) / 10.0f, Color.Red);
GUI.DrawLine(sb, center + Vector2.One * 5.0f, center + new Vector2(lerpedFlowForce.X, -lerpedFlowForce.Y) / 10.0f + Vector2.One * 5.0f, Color.Orange);
}
if (!editing || !ShowGaps) return;
Color clr = (open == 0.0f) ? Color.Red : Color.Cyan;
if (isHighlighted) clr = Color.Gold;
float depth = (ID % 255) * 0.000001f;
GUI.DrawRectangle(
sb, new Rectangle(WorldRect.X, -WorldRect.Y, rect.Width, rect.Height),
clr * 0.5f, true,
depth,
(int)Math.Max((1.5f / GameScreen.Selected.Cam.Zoom), 1.0f));
for (int i = 0; i < linkedTo.Count; i++)
{
Vector2 dir = isHorizontal ?
new Vector2(Math.Sign(linkedTo[i].Rect.Center.X - rect.Center.X), 0.0f)
: new Vector2(0.0f, Math.Sign((linkedTo[i].Rect.Y - linkedTo[i].Rect.Height / 2.0f) - (rect.Y - rect.Height / 2.0f)));
Vector2 arrowPos = new Vector2(WorldRect.Center.X, -(WorldRect.Y - WorldRect.Height / 2));
arrowPos += new Vector2(dir.X * (WorldRect.Width / 2 + 10), dir.Y * (WorldRect.Height / 2 + 10));
GUI.Arrow.Draw(sb,
arrowPos, clr * 0.8f,
GUI.Arrow.Origin, MathUtils.VectorToAngle(dir) + MathHelper.PiOver2,
isHorizontal ? new Vector2(rect.Height / 16.0f, 1.0f) : new Vector2(rect.Width / 16.0f, 1.0f),
SpriteEffects.None, depth);
}
if (IsSelected)
{
GUI.DrawRectangle(sb,
new Vector2(WorldRect.X - 5, -WorldRect.Y - 5),
new Vector2(rect.Width + 10, rect.Height + 10),
Color.Red,
false,
depth,
(int)Math.Max((1.5f / GameScreen.Selected.Cam.Zoom), 1.0f));
}
}
public override XElement Save(XElement parentElement)
{
XElement element = new XElement("Gap");
element.Add(
new XAttribute("ID", ID),
new XAttribute("horizontal", isHorizontal ? "true" : "false"));
element.Add(new XAttribute("rect",
(int)(rect.X - Submarine.HiddenSubPosition.X) + "," +
(int)(rect.Y - Submarine.HiddenSubPosition.Y) + "," +
rect.Width + "," + rect.Height));
//if (linkedTo != null)
//{
// int i = 0;
// foreach (Entity e in linkedTo)
// {
// if (e == null) continue;
// element.Add(new XAttribute("linkedto" + i, e.ID));
// i += 1;
// }
//}
parentElement.Add(element);
return element;
}
}
}

View File

@@ -0,0 +1,205 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Xml.Linq;
using FarseerPhysics;
using FarseerPhysics.Dynamics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Lidgren.Network;
using Barotrauma.Networking;
namespace Barotrauma
{
partial class Hull : MapEntity, IPropertyObject, IServerSerializable
{
public static WaterRenderer renderer;
private Sound currentFlowSound;
private int soundIndex;
private float soundVolume;
public override bool IsMouseOn(Vector2 position)
{
if (!GameMain.DebugDraw && !ShowHulls) return false;
return (Submarine.RectContains(WorldRect, position) &&
!Submarine.RectContains(MathUtils.ExpandRect(WorldRect, -8), position));
}
public override void Draw(SpriteBatch spriteBatch, bool editing, bool back = true)
{
//if (back) return;
Rectangle drawRect;
if (!Visible)
{
drawRect =
Submarine == null ? rect : new Rectangle((int)(Submarine.DrawPosition.X + rect.X), (int)(Submarine.DrawPosition.Y + rect.Y), rect.Width, rect.Height);
GUI.DrawRectangle(spriteBatch,
new Vector2(drawRect.X, -drawRect.Y),
new Vector2(rect.Width, rect.Height),
Color.Black, true,
0, (int)Math.Max((1.5f / GameScreen.Selected.Cam.Zoom), 1.0f));
}
if (!ShowHulls && !GameMain.DebugDraw) return;
if (!editing && !GameMain.DebugDraw) return;
if (aiTarget != null) aiTarget.Draw(spriteBatch);
drawRect =
Submarine == null ? rect : new Rectangle((int)(Submarine.DrawPosition.X + rect.X), (int)(Submarine.DrawPosition.Y + rect.Y), rect.Width, rect.Height);
GUI.DrawRectangle(spriteBatch,
new Vector2(drawRect.X, -drawRect.Y),
new Vector2(rect.Width, rect.Height),
Color.Blue, false, (ID % 255) * 0.000001f, (int)Math.Max((1.5f / Screen.Selected.Cam.Zoom), 1.0f));
GUI.DrawRectangle(spriteBatch,
new Rectangle(drawRect.X, -drawRect.Y, rect.Width, rect.Height),
Color.Red * ((100.0f - OxygenPercentage) / 400.0f), true, 0, (int)Math.Max((1.5f / GameScreen.Selected.Cam.Zoom), 1.0f));
if (GameMain.DebugDraw)
{
GUI.SmallFont.DrawString(spriteBatch, "Pressure: " + ((int)pressure - rect.Y).ToString() +
" - Oxygen: " + ((int)OxygenPercentage), new Vector2(drawRect.X + 5, -drawRect.Y + 5), Color.White);
GUI.SmallFont.DrawString(spriteBatch, volume + " / " + FullVolume, new Vector2(drawRect.X + 5, -drawRect.Y + 20), Color.White);
foreach (FireSource fs in fireSources)
{
GUI.DrawRectangle(spriteBatch, new Rectangle((int)fs.WorldPosition.X, (int)-fs.WorldPosition.Y, (int)fs.Size.X, (int)fs.Size.Y), Color.Orange, false);
}
}
if ((IsSelected || isHighlighted) && editing)
{
GUI.DrawRectangle(spriteBatch,
new Vector2(drawRect.X + 5, -drawRect.Y + 5),
new Vector2(rect.Width - 10, rect.Height - 10),
isHighlighted ? Color.LightBlue * 0.5f : Color.Red * 0.5f, true, 0, (int)Math.Max((1.5f / GameScreen.Selected.Cam.Zoom), 1.0f));
}
}
public void Render(GraphicsDevice graphicsDevice, Camera cam)
{
if (renderer.PositionInBuffer > renderer.vertices.Length - 6) return;
Vector2 submarinePos = Submarine == null ? Vector2.Zero : Submarine.DrawPosition;
//calculate where the surface should be based on the water volume
float top = rect.Y + submarinePos.Y;
float bottom = top - rect.Height;
float drawSurface = surface + submarinePos.Y;
Matrix transform = cam.Transform * Matrix.CreateOrthographic(GameMain.GraphicsWidth, GameMain.GraphicsHeight, -1, 1) * 0.5f;
if (bottom > cam.WorldView.Y || top < cam.WorldView.Y - cam.WorldView.Height) return;
if (!update)
{
// create the four corners of our triangle.
Vector3[] corners = new Vector3[4];
corners[0] = new Vector3(rect.X, rect.Y, 0.0f);
corners[1] = new Vector3(rect.X + rect.Width, rect.Y, 0.0f);
corners[2] = new Vector3(corners[1].X, rect.Y - rect.Height, 0.0f);
corners[3] = new Vector3(corners[0].X, corners[2].Y, 0.0f);
Vector2[] uvCoords = new Vector2[4];
for (int i = 0; i < 4; i++)
{
corners[i] += new Vector3(submarinePos, 0.0f);
uvCoords[i] = Vector2.Transform(new Vector2(corners[i].X, -corners[i].Y), transform);
}
renderer.vertices[renderer.PositionInBuffer] = new VertexPositionTexture(corners[0], uvCoords[0]);
renderer.vertices[renderer.PositionInBuffer + 1] = new VertexPositionTexture(corners[1], uvCoords[1]);
renderer.vertices[renderer.PositionInBuffer + 2] = new VertexPositionTexture(corners[2], uvCoords[2]);
renderer.vertices[renderer.PositionInBuffer + 3] = new VertexPositionTexture(corners[0], uvCoords[0]);
renderer.vertices[renderer.PositionInBuffer + 4] = new VertexPositionTexture(corners[2], uvCoords[2]);
renderer.vertices[renderer.PositionInBuffer + 5] = new VertexPositionTexture(corners[3], uvCoords[3]);
renderer.PositionInBuffer += 6;
return;
}
float x = rect.X + Submarine.DrawPosition.X;
int start = (int)Math.Floor((cam.WorldView.X - x) / WaveWidth);
start = Math.Max(start, 0);
int end = (waveY.Length - 1)
- (int)Math.Floor((float)((x + rect.Width) - (cam.WorldView.X + cam.WorldView.Width)) / WaveWidth);
end = Math.Min(end, waveY.Length - 1);
x += start * WaveWidth;
for (int i = start; i < end; i++)
{
if (renderer.PositionInBuffer > renderer.vertices.Length - 6) return;
Vector3[] corners = new Vector3[4];
corners[0] = new Vector3(x, top, 0.0f);
corners[3] = new Vector3(corners[0].X, drawSurface + waveY[i], 0.0f);
//skip adjacent "water rects" if the surface of the water is roughly at the same position
int width = WaveWidth;
while (i < end - 1 && Math.Abs(waveY[i + 1] - waveY[i]) < 1.0f)
{
width += WaveWidth;
i++;
}
corners[1] = new Vector3(x + width, top, 0.0f);
corners[2] = new Vector3(corners[1].X, drawSurface + waveY[i + 1], 0.0f);
Vector2[] uvCoords = new Vector2[4];
for (int n = 0; n < 4; n++)
{
uvCoords[n] = Vector2.Transform(new Vector2(corners[n].X, -corners[n].Y), transform);
}
renderer.vertices[renderer.PositionInBuffer] = new VertexPositionTexture(corners[0], uvCoords[0]);
renderer.vertices[renderer.PositionInBuffer + 1] = new VertexPositionTexture(corners[1], uvCoords[1]);
renderer.vertices[renderer.PositionInBuffer + 2] = new VertexPositionTexture(corners[2], uvCoords[2]);
renderer.vertices[renderer.PositionInBuffer + 3] = new VertexPositionTexture(corners[0], uvCoords[0]);
renderer.vertices[renderer.PositionInBuffer + 4] = new VertexPositionTexture(corners[2], uvCoords[2]);
renderer.vertices[renderer.PositionInBuffer + 5] = new VertexPositionTexture(corners[3], uvCoords[3]);
renderer.PositionInBuffer += 6;
x += width;
}
}
public override XElement Save(XElement parentElement)
{
XElement element = new XElement("Hull");
element.Add
(
new XAttribute("ID", ID),
new XAttribute("rect",
(int)(rect.X - Submarine.HiddenSubPosition.X) + "," +
(int)(rect.Y - Submarine.HiddenSubPosition.Y) + "," +
rect.Width + "," + rect.Height),
new XAttribute("water", volume)
);
parentElement.Add(element);
return element;
}
}
}

View File

@@ -0,0 +1,166 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Voronoi2;
using Microsoft.Xna.Framework.Graphics;
using FarseerPhysics;
using FarseerPhysics.Common;
using FarseerPhysics.Dynamics;
using FarseerPhysics.Factories;
namespace Barotrauma
{
static partial class CaveGenerator
{
public static List<VertexPositionTexture> GenerateRenderVerticeList(List<Vector2[]> triangles)
{
var verticeList = new List<VertexPositionTexture>();
for (int i = 0; i < triangles.Count; i++)
{
foreach (Vector2 vertex in triangles[i])
{
//shift the coordinates around a bit to make the texture repetition less obvious
Vector2 uvCoords = new Vector2(
vertex.X / 2000.0f + (float)Math.Sin(vertex.X / 500.0f) * 0.15f,
vertex.Y / 2000.0f + (float)Math.Sin(vertex.Y / 700.0f) * 0.15f);
verticeList.Add(new VertexPositionTexture(new Vector3(vertex, 1.0f), uvCoords));
}
}
return verticeList;
}
public static VertexPositionTexture[] GenerateWallShapes(List<VoronoiCell> cells)
{
float inwardThickness = 500.0f, outWardThickness = 30.0f;
List<VertexPositionTexture> verticeList = new List<VertexPositionTexture>();
foreach (VoronoiCell cell in cells)
{
//if (cell.body == null) continue;
foreach (GraphEdge edge in cell.edges)
{
if (edge.cell1 != null && edge.cell1.body == null && edge.cell1.CellType != CellType.Empty) edge.cell1 = null;
if (edge.cell2 != null && edge.cell2.body == null && edge.cell2.CellType != CellType.Empty) edge.cell2 = null;
CompareCCW compare = new CompareCCW(cell.Center);
if (compare.Compare(edge.point1, edge.point2) == -1)
{
var temp = edge.point1;
edge.point1 = edge.point2;
edge.point2 = temp;
}
}
}
foreach (VoronoiCell cell in cells)
{
//if (cell.body == null) continue;
foreach (GraphEdge edge in cell.edges)
{
if (!edge.isSolid) continue;
GraphEdge leftEdge = cell.edges.Find(e => e != edge && (edge.point1 == e.point1 || edge.point1 == e.point2));
GraphEdge rightEdge = cell.edges.Find(e => e != edge && (edge.point2 == e.point1 || edge.point2 == e.point2));
Vector2 leftNormal = Vector2.Zero, rightNormal = Vector2.Zero;
if (leftEdge == null)
{
leftNormal = GetEdgeNormal(edge, cell);
}
else
{
leftNormal = (leftEdge.isSolid) ?
Vector2.Normalize(GetEdgeNormal(leftEdge) + GetEdgeNormal(edge, cell)) :
Vector2.Normalize(leftEdge.Center - edge.point1);
}
if (!MathUtils.IsValid(leftNormal))
{
#if DEBUG
DebugConsole.ThrowError("Invalid left normal");
#endif
if (cell.body != null)
{
GameMain.World.RemoveBody(cell.body);
cell.body = null;
}
leftNormal = Vector2.UnitX;
break;
}
if (rightEdge == null)
{
rightNormal = GetEdgeNormal(edge, cell);
}
else
{
rightNormal = (rightEdge.isSolid) ?
Vector2.Normalize(GetEdgeNormal(rightEdge) + GetEdgeNormal(edge, cell)) :
Vector2.Normalize(rightEdge.Center - edge.point2);
}
if (!MathUtils.IsValid(rightNormal))
{
#if DEBUG
DebugConsole.ThrowError("Invalid right normal");
#endif
if (cell.body != null)
{
GameMain.World.RemoveBody(cell.body);
cell.body = null;
}
rightNormal = Vector2.UnitX;
break;
}
for (int i = 0; i < 2; i++)
{
Vector2[] verts = new Vector2[3];
VertexPositionTexture[] vertPos = new VertexPositionTexture[3];
if (i == 0)
{
verts[0] = edge.point1 - leftNormal * outWardThickness;
verts[1] = edge.point2 - rightNormal * outWardThickness;
verts[2] = edge.point1 + leftNormal * inwardThickness;
vertPos[0] = new VertexPositionTexture(new Vector3(verts[0], 0.0f), Vector2.Zero);
vertPos[1] = new VertexPositionTexture(new Vector3(verts[1], 0.0f), Vector2.UnitX);
vertPos[2] = new VertexPositionTexture(new Vector3(verts[2], 0.0f), new Vector2(0, 0.5f));
}
else
{
verts[0] = edge.point1 + leftNormal * inwardThickness;
verts[1] = edge.point2 - rightNormal * outWardThickness;
verts[2] = edge.point2 + rightNormal * inwardThickness;
vertPos[0] = new VertexPositionTexture(new Vector3(verts[0], 0.0f), new Vector2(0.0f, 0.5f));
vertPos[1] = new VertexPositionTexture(new Vector3(verts[1], 0.0f), Vector2.UnitX);
vertPos[2] = new VertexPositionTexture(new Vector3(verts[2], 0.0f), new Vector2(1.0f, 0.5f));
}
var comparer = new CompareCCW((verts[0] + verts[1] + verts[2]) / 3.0f);
Array.Sort(verts, vertPos, comparer);
for (int j = 0; j < 3; j++)
{
verticeList.Add(vertPos[j]);
}
}
}
}
return verticeList.ToArray();
}
}
}

View File

@@ -0,0 +1,59 @@
using FarseerPhysics;
using FarseerPhysics.Common;
using FarseerPhysics.Dynamics;
using FarseerPhysics.Factories;
using Lidgren.Network;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.Linq;
using System.Collections.Generic;
using System.Diagnostics;
using Voronoi2;
using Barotrauma.RuinGeneration;
namespace Barotrauma
{
partial class Level
{
private LevelRenderer renderer;
public void DrawFront(SpriteBatch spriteBatch)
{
if (renderer == null) return;
renderer.Draw(spriteBatch);
if (GameMain.DebugDraw)
{
foreach (InterestingPosition pos in positionsOfInterest)
{
Color color = Color.Yellow;
if (pos.PositionType == PositionType.Cave)
{
color = Color.DarkOrange;
}
else if (pos.PositionType == PositionType.Ruin)
{
color = Color.LightGray;
}
GUI.DrawRectangle(spriteBatch, new Vector2(pos.Position.X - 15.0f, -pos.Position.Y - 15.0f), new Vector2(30.0f, 30.0f), color, true);
}
}
}
public void DrawBack(GraphicsDevice graphics, SpriteBatch spriteBatch, Camera cam, BackgroundCreatureManager backgroundSpriteManager = null)
{
float brightness = MathHelper.Clamp(50.0f + (cam.Position.Y - Size.Y) / 2000.0f, 10.0f, 40.0f);
float avgValue = (backgroundColor.R + backgroundColor.G + backgroundColor.G) / 3;
GameMain.LightManager.AmbientLight = new Color(backgroundColor * (brightness / avgValue), 1.0f);
graphics.Clear(backgroundColor);
if (renderer == null) return;
renderer.DrawBackground(spriteBatch, cam, backgroundSpriteManager);
}
}
}

Some files were not shown because too many files have changed in this diff Show More