2f107db...5202af9

This commit is contained in:
Joonas Rikkonen
2019-03-18 21:42:26 +02:00
parent 58c92888b7
commit 044fd3344b
395 changed files with 27417 additions and 19754 deletions
@@ -1,412 +1,507 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup> <PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">ReleaseLinux</Configuration> <Configuration Condition=" '$(Configuration)' == '' ">ReleaseLinux</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform> <Platform Condition=" '$(Platform)' == '' ">x64</Platform>
<ProductVersion>8.0.30703</ProductVersion> <ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion> <SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{008C0F83-E914-4966-9135-EA885059EDD8}</ProjectGuid> <ProjectGuid>{008C0F83-E914-4966-9135-EA885059EDD8}</ProjectGuid>
<OutputType>WinExe</OutputType> <OutputType>WinExe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder> <AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Barotrauma</RootNamespace> <RootNamespace>Barotrauma</RootNamespace>
<AssemblyName>Barotrauma</AssemblyName> <AssemblyName>Barotrauma</AssemblyName>
<FileAlignment>512</FileAlignment> <FileAlignment>512</FileAlignment>
<IsWebBootstrapper>false</IsWebBootstrapper> <IsWebBootstrapper>false</IsWebBootstrapper>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion> <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<TargetFrameworkProfile /> <TargetFrameworkProfile />
<ReleaseVersion>0.7.0.1</ReleaseVersion> <ReleaseVersion>0.9.0.0</ReleaseVersion>
<PublishUrl>publish\</PublishUrl> <PublishUrl>publish\</PublishUrl>
<Install>true</Install> <Install>true</Install>
<InstallFrom>Disk</InstallFrom> <InstallFrom>Disk</InstallFrom>
<UpdateEnabled>false</UpdateEnabled> <UpdateEnabled>false</UpdateEnabled>
<UpdateMode>Foreground</UpdateMode> <UpdateMode>Foreground</UpdateMode>
<UpdateInterval>7</UpdateInterval> <UpdateInterval>7</UpdateInterval>
<UpdateIntervalUnits>Days</UpdateIntervalUnits> <UpdateIntervalUnits>Days</UpdateIntervalUnits>
<UpdatePeriodically>false</UpdatePeriodically> <UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired> <UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions> <MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>0</ApplicationRevision> <ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>0.1.0.%2a</ApplicationVersion> <ApplicationVersion>0.1.0.%2a</ApplicationVersion>
<UseApplicationTrust>false</UseApplicationTrust> <UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled> <BootstrapperEnabled>true</BootstrapperEnabled>
</PropertyGroup> <NuGetPackageImportStamp>
<PropertyGroup> </NuGetPackageImportStamp>
<ApplicationIcon>..\BarotraumaShared\Icon.ico</ApplicationIcon> </PropertyGroup>
</PropertyGroup> <PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'ReleaseLinux|x64'"> <ApplicationIcon>..\BarotraumaShared\Icon.ico</ApplicationIcon>
<DebugSymbols>true</DebugSymbols> </PropertyGroup>
<OutputPath>..\bin\ReleaseLinux\</OutputPath> <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'ReleaseLinux|x64'">
<DefineConstants>TRACE;LINUX;CLIENT</DefineConstants> <DebugSymbols>true</DebugSymbols>
<Optimize>true</Optimize> <OutputPath>..\bin\ReleaseLinux\</OutputPath>
<DebugType>pdbonly</DebugType> <DefineConstants>TRACE;LINUX;CLIENT</DefineConstants>
<PlatformTarget>x64</PlatformTarget> <Optimize>true</Optimize>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet> <DebugType>pdbonly</DebugType>
<Prefer32Bit>true</Prefer32Bit> <PlatformTarget>x64</PlatformTarget>
</PropertyGroup> <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'DebugLinux|x64'"> <Prefer32Bit>true</Prefer32Bit>
<DebugSymbols>true</DebugSymbols> </PropertyGroup>
<OutputPath>..\bin\DebugLinux\</OutputPath> <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'DebugLinux|x64'">
<DefineConstants>TRACE;LINUX;CLIENT;DEBUG</DefineConstants> <DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType> <OutputPath>..\bin\DebugLinux\</OutputPath>
<PlatformTarget>x64</PlatformTarget> <DefineConstants>TRACE;LINUX;CLIENT;DEBUG</DefineConstants>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet> <DebugType>full</DebugType>
<Prefer32Bit>true</Prefer32Bit> <PlatformTarget>x64</PlatformTarget>
</PropertyGroup> <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'ReleaseMac|x64'"> <Prefer32Bit>true</Prefer32Bit>
<DebugSymbols>true</DebugSymbols> </PropertyGroup>
<OutputPath>..\bin\ReleaseMac\</OutputPath> <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'ReleaseMac|x64'">
<DefineConstants>TRACE;OSX;CLIENT</DefineConstants> <DebugSymbols>true</DebugSymbols>
<Optimize>true</Optimize> <OutputPath>..\bin\ReleaseMac\</OutputPath>
<DebugType>pdbonly</DebugType> <DefineConstants>TRACE;OSX;CLIENT</DefineConstants>
<PlatformTarget>x64</PlatformTarget> <Optimize>true</Optimize>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet> <DebugType>pdbonly</DebugType>
<Prefer32Bit>true</Prefer32Bit> <PlatformTarget>x64</PlatformTarget>
</PropertyGroup> <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'DebugMac|x64'"> <Prefer32Bit>true</Prefer32Bit>
<DebugSymbols>true</DebugSymbols> </PropertyGroup>
<OutputPath>..\bin\DebugMac\</OutputPath> <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'DebugMac|x64'">
<DefineConstants>TRACE;OSX;CLIENT;DEBUG</DefineConstants> <DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType> <OutputPath>..\bin\DebugMac\</OutputPath>
<PlatformTarget>x64</PlatformTarget> <DefineConstants>TRACE;OSX;CLIENT;DEBUG</DefineConstants>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet> <DebugType>full</DebugType>
<Prefer32Bit>true</Prefer32Bit> <PlatformTarget>x64</PlatformTarget>
</PropertyGroup> <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'ReleaseWindows|x64'"> <Prefer32Bit>true</Prefer32Bit>
<DebugSymbols>true</DebugSymbols> </PropertyGroup>
<OutputPath>..\bin\ReleaseWindows\</OutputPath> <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'ReleaseWindows|x64'">
<DefineConstants>TRACE;WINDOWS;CLIENT</DefineConstants> <DebugSymbols>true</DebugSymbols>
<Optimize>true</Optimize> <OutputPath>..\bin\ReleaseWindows\</OutputPath>
<DebugType>pdbonly</DebugType> <DefineConstants>TRACE;WINDOWS;CLIENT</DefineConstants>
<PlatformTarget>x64</PlatformTarget> <Optimize>true</Optimize>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet> <DebugType>pdbonly</DebugType>
<Prefer32Bit>true</Prefer32Bit> <PlatformTarget>x64</PlatformTarget>
</PropertyGroup> <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'DebugWindows|x64'"> <Prefer32Bit>true</Prefer32Bit>
<DebugSymbols>true</DebugSymbols> </PropertyGroup>
<OutputPath>..\bin\DebugWindows\</OutputPath> <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'DebugWindows|x64'">
<DefineConstants>TRACE;WINDOWS;CLIENT;DEBUG</DefineConstants> <DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType> <OutputPath>..\bin\DebugWindows\</OutputPath>
<PlatformTarget>x64</PlatformTarget> <DefineConstants>TRACE;WINDOWS;CLIENT;DEBUG</DefineConstants>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet> <DebugType>full</DebugType>
<Prefer32Bit>true</Prefer32Bit> <PlatformTarget>x64</PlatformTarget>
</PropertyGroup> <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<ItemGroup> <Prefer32Bit>true</Prefer32Bit>
<Compile Include="Properties\AssemblyInfo.cs" /> </PropertyGroup>
<Compile Include="Source\Camera.cs" /> <ItemGroup>
<Compile Include="Source\Characters\AICharacter.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Source\Characters\AI\AIController.cs" /> <Compile Include="Source\Camera.cs" />
<Compile Include="Source\Characters\AI\AITarget.cs" /> <Compile Include="Source\Characters\AICharacter.cs" />
<Compile Include="Source\Characters\AI\EnemyAIController.cs" /> <Compile Include="Source\Characters\AI\AIController.cs" />
<Compile Include="Source\Characters\AI\HumanAIController.cs" /> <Compile Include="Source\Characters\AI\AITarget.cs" />
<Compile Include="Source\Characters\Animation\Ragdoll.cs" /> <Compile Include="Source\Characters\AI\EnemyAIController.cs" />
<Compile Include="Source\Characters\Attack.cs" /> <Compile Include="Source\Characters\AI\HumanAIController.cs" />
<Compile Include="Source\Characters\Health\AfflictionPsychosis.cs" /> <Compile Include="Source\Characters\Animation\Ragdoll.cs" />
<Compile Include="Source\Events\EventManager.cs" /> <Compile Include="Source\Characters\Attack.cs" />
<Compile Include="Source\GameSession\GameModes\Tutorials\ContextualTutorial.cs" /> <Compile Include="Source\Characters\Health\AfflictionHusk.cs" />
<Compile Include="Source\GameSession\GameModes\Tutorials\ScenarioTutorial.cs" /> <Compile Include="Source\Characters\Health\AfflictionPsychosis.cs" />
<Compile Include="Source\GUI\ChatBox.cs" /> <Compile Include="Source\Characters\Health\CharacterHealth.cs" />
<Compile Include="Source\GUI\ParamsEditor.cs" /> <Compile Include="Source\Characters\Health\DamageModifier.cs" />
<Compile Include="Source\GUI\ShapeExtensions.cs" /> <Compile Include="Source\Events\EventManager.cs" />
<Compile Include="Source\GUI\Graph.cs" /> <Compile Include="Source\Events\Missions\CombatMission.cs" />
<Compile Include="Source\Characters\CharacterHealth.cs" /> <Compile Include="Source\GameSession\GameModes\Tutorials\ContextualTutorial.cs" />
<Compile Include="Source\GameSession\GameModes\MultiPlayerCampaign.cs" /> <Compile Include="Source\GameSession\GameModes\Tutorials\ScenarioTutorial.cs" />
<Compile Include="Source\GUI\GUICanvas.cs" /> <Compile Include="Source\GUI\ChatBox.cs" />
<Compile Include="Source\GUI\GUICustomComponent.cs" /> <Compile Include="Source\GUI\GUIRadioButtonGroup.cs" />
<Compile Include="Source\GUI\GUILayoutGroup.cs" /> <Compile Include="Source\GUI\ParamsEditor.cs" />
<Compile Include="Source\GUI\HUDLayoutSettings.cs" /> <Compile Include="Source\GUI\ShapeExtensions.cs" />
<Compile Include="Source\GUI\RectTransform.cs" /> <Compile Include="Source\GUI\Graph.cs" />
<Compile Include="Source\GUI\SpriteSheetPlayer.cs" /> <Compile Include="Source\Characters\CharacterHealth.cs" />
<Compile Include="Source\GUI\UISprite.cs" /> <Compile Include="Source\GameSession\GameModes\MultiPlayerCampaign.cs" />
<Compile Include="Source\GUI\Widget.cs" /> <Compile Include="Source\GUI\GUICanvas.cs" />
<Compile Include="Source\Items\Components\ElectricalDischarger.cs" /> <Compile Include="Source\GUI\GUICustomComponent.cs" />
<Compile Include="Source\Items\Components\LevelResource.cs" /> <Compile Include="Source\GUI\GUILayoutGroup.cs" />
<Compile Include="Source\Items\Components\Machines\Controller.cs" /> <Compile Include="Source\GUI\HUDLayoutSettings.cs" />
<Compile Include="Source\Items\Components\Repairable.cs" /> <Compile Include="Source\GUI\RectTransform.cs" />
<Compile Include="Source\Items\Components\RepairTool.cs" /> <Compile Include="Source\GUI\SpriteSheetPlayer.cs" />
<Compile Include="Source\Items\Components\Signal\CustomInterface.cs" /> <Compile Include="Source\GUI\UISprite.cs" />
<Compile Include="Source\Items\Components\Signal\MotionSensor.cs" /> <Compile Include="Source\GUI\Widget.cs" />
<Compile Include="Source\Items\Components\Signal\WifiComponent.cs" /> <Compile Include="Source\Items\Components\ElectricalDischarger.cs" />
<Compile Include="Source\Items\ItemInventory.cs" /> <Compile Include="Source\Items\Components\LevelResource.cs" />
<Compile Include="Source\Map\ItemAssemblyPrefab.cs" /> <Compile Include="Source\Items\Components\Machines\Controller.cs" />
<Compile Include="Source\Map\Levels\BackgroundCreatures\BackgroundCreature.cs" /> <Compile Include="Source\Items\Components\Repairable.cs" />
<Compile Include="Source\Map\Levels\BackgroundCreatures\BackgroundCreatureManager.cs" /> <Compile Include="Source\Items\Components\RepairTool.cs" />
<Compile Include="Source\Map\Levels\BackgroundCreatures\BackgroundCreaturePrefab.cs" /> <Compile Include="Source\Items\Components\Signal\CustomInterface.cs" />
<Compile Include="Source\Characters\Character.cs" /> <Compile Include="Source\Items\Components\Signal\MotionSensor.cs" />
<Compile Include="Source\Characters\CharacterHUD.cs" /> <Compile Include="Source\Items\Components\Signal\WifiComponent.cs" />
<Compile Include="Source\Characters\CharacterInfo.cs" /> <Compile Include="Source\Items\ItemInventory.cs" />
<Compile Include="Source\Characters\CharacterNetworking.cs" /> <Compile Include="Source\Map\ItemAssemblyPrefab.cs" />
<Compile Include="Source\Characters\CharacterSound.cs" /> <Compile Include="Source\Map\Levels\BackgroundCreatures\BackgroundCreature.cs" />
<Compile Include="Source\Characters\HUDProgressBar.cs" /> <Compile Include="Source\Map\Levels\BackgroundCreatures\BackgroundCreatureManager.cs" />
<Compile Include="Source\Characters\Jobs\JobPrefab.cs" /> <Compile Include="Source\Map\Levels\BackgroundCreatures\BackgroundCreaturePrefab.cs" />
<Compile Include="Source\Characters\Limb.cs" /> <Compile Include="Source\Characters\Character.cs" />
<Compile Include="Source\DebugConsole.cs" /> <Compile Include="Source\Characters\CharacterHUD.cs" />
<Compile Include="Source\EventInput\EventInput.cs" /> <Compile Include="Source\Characters\CharacterInfo.cs" />
<Compile Include="Source\EventInput\KeyboardDispatcher.cs" /> <Compile Include="Source\Characters\CharacterNetworking.cs" />
<Compile Include="Source\Events\Missions\Mission.cs" /> <Compile Include="Source\Characters\CharacterSound.cs" />
<Compile Include="Source\Events\Missions\MissionMode.cs" /> <Compile Include="Source\Characters\HUDProgressBar.cs" />
<Compile Include="Source\Fonts\ScalableFont.cs" /> <Compile Include="Source\Characters\Jobs\JobPrefab.cs" />
<Compile Include="Source\GameMain.cs" /> <Compile Include="Source\Characters\Limb.cs" />
<Compile Include="Source\GameSession\CrewManager.cs" /> <Compile Include="Source\DebugConsole.cs" />
<Compile Include="Source\GameSession\GameMode.cs" /> <Compile Include="Source\EventInput\EventInput.cs" />
<Compile Include="Source\GameSession\GameModes\SinglePlayerCampaign.cs" /> <Compile Include="Source\EventInput\KeyboardDispatcher.cs" />
<Compile Include="Source\GameSession\GameModes\Tutorials\BasicTutorial.cs" /> <Compile Include="Source\Events\Missions\Mission.cs" />
<Compile Include="Source\GameSession\GameModes\Tutorials\EditorTutorial.cs" /> <Compile Include="Source\Events\Missions\MissionMode.cs" />
<Compile Include="Source\GameSession\GameModes\Tutorials\TutorialMode.cs" /> <Compile Include="Source\Fonts\ScalableFont.cs" />
<Compile Include="Source\GameSession\GameModes\Tutorials\Tutorial.cs" /> <Compile Include="Source\GameMain.cs" />
<Compile Include="Source\GameSession\GameSession.cs" /> <Compile Include="Source\GameSession\CrewManager.cs" />
<Compile Include="Source\GameSession\HireManager.cs" /> <Compile Include="Source\GameSession\GameMode.cs" />
<Compile Include="Source\GameSession\RoundSummary.cs" /> <Compile Include="Source\GameSession\GameModes\SinglePlayerCampaign.cs" />
<Compile Include="Source\GameSettings.cs" /> <Compile Include="Source\GameSession\GameModes\Tutorials\BasicTutorial.cs" />
<Compile Include="Source\GUI\ComponentStyle.cs" /> <Compile Include="Source\GameSession\GameModes\Tutorials\EditorTutorial.cs" />
<Compile Include="Source\GUI\GUI.cs" /> <Compile Include="Source\GameSession\GameModes\Tutorials\TutorialMode.cs" />
<Compile Include="Source\GUI\GUIButton.cs" /> <Compile Include="Source\GameSession\GameModes\Tutorials\Tutorial.cs" />
<Compile Include="Source\GUI\GUIComponent.cs" /> <Compile Include="Source\GameSession\GameSession.cs" />
<Compile Include="Source\GUI\GUIDropDown.cs" /> <Compile Include="Source\GameSession\RoundSummary.cs" />
<Compile Include="Source\GUI\GUIFrame.cs" /> <Compile Include="Source\GameSettings.cs" />
<Compile Include="Source\GUI\GUIImage.cs" /> <Compile Include="Source\GUI\ComponentStyle.cs" />
<Compile Include="Source\GUI\GUIListBox.cs" /> <Compile Include="Source\GUI\GUI.cs" />
<Compile Include="Source\GUI\GUIMessage.cs" /> <Compile Include="Source\GUI\GUIButton.cs" />
<Compile Include="Source\GUI\GUIMessageBox.cs" /> <Compile Include="Source\GUI\GUIComponent.cs" />
<Compile Include="Source\GUI\GUINumberInput.cs" /> <Compile Include="Source\GUI\GUIDropDown.cs" />
<Compile Include="Source\GUI\GUIProgressBar.cs" /> <Compile Include="Source\GUI\GUIFrame.cs" />
<Compile Include="Source\GUI\GUIScrollBar.cs" /> <Compile Include="Source\GUI\GUIImage.cs" />
<Compile Include="Source\GUI\GUIStyle.cs" /> <Compile Include="Source\GUI\GUIListBox.cs" />
<Compile Include="Source\GUI\GUITextBlock.cs" /> <Compile Include="Source\GUI\GUIMessage.cs" />
<Compile Include="Source\GUI\GUITextBox.cs" /> <Compile Include="Source\GUI\GUIMessageBox.cs" />
<Compile Include="Source\GUI\GUITickBox.cs" /> <Compile Include="Source\GUI\GUINumberInput.cs" />
<Compile Include="Source\GUI\LoadingScreen.cs" /> <Compile Include="Source\GUI\GUIProgressBar.cs" />
<Compile Include="Source\Items\CharacterInventory.cs" /> <Compile Include="Source\GUI\GUIScrollBar.cs" />
<Compile Include="Source\Items\Components\Door.cs" /> <Compile Include="Source\GUI\GUIStyle.cs" />
<Compile Include="Source\Items\Components\ItemComponent.cs" /> <Compile Include="Source\GUI\GUITextBlock.cs" />
<Compile Include="Source\Items\Components\ItemContainer.cs" /> <Compile Include="Source\GUI\GUITextBox.cs" />
<Compile Include="Source\Items\Components\ItemLabel.cs" /> <Compile Include="Source\GUI\GUITickBox.cs" />
<Compile Include="Source\Items\Components\LightComponent.cs" /> <Compile Include="Source\GUI\LoadingScreen.cs" />
<Compile Include="Source\Items\Components\Machines\Deconstructor.cs" /> <Compile Include="Source\Items\CharacterInventory.cs" />
<Compile Include="Source\Items\Components\Machines\Engine.cs" /> <Compile Include="Source\Items\Components\Door.cs" />
<Compile Include="Source\Items\Components\Machines\Fabricator.cs" /> <Compile Include="Source\Items\Components\ItemComponent.cs" />
<Compile Include="Source\Items\Components\Machines\MiniMap.cs" /> <Compile Include="Source\Items\Components\ItemContainer.cs" />
<Compile Include="Source\Items\Components\Machines\Pump.cs" /> <Compile Include="Source\Items\Components\ItemLabel.cs" />
<Compile Include="Source\Items\Components\Machines\Sonar.cs" /> <Compile Include="Source\Items\Components\LightComponent.cs" />
<Compile Include="Source\Items\Components\Machines\Reactor.cs" /> <Compile Include="Source\Items\Components\Machines\Deconstructor.cs" />
<Compile Include="Source\Items\Components\Machines\Steering.cs" /> <Compile Include="Source\Items\Components\Machines\Engine.cs" />
<Compile Include="Source\Items\Components\Power\PowerContainer.cs" /> <Compile Include="Source\Items\Components\Machines\Fabricator.cs" />
<Compile Include="Source\Items\Components\Power\Powered.cs" /> <Compile Include="Source\Items\Components\Machines\MiniMap.cs" />
<Compile Include="Source\Items\Components\Power\PowerTransfer.cs" /> <Compile Include="Source\Items\Components\Machines\Pump.cs" />
<Compile Include="Source\Items\Components\Signal\Connection.cs" /> <Compile Include="Source\Items\Components\Machines\Sonar.cs" />
<Compile Include="Source\Items\Components\Signal\ConnectionPanel.cs" /> <Compile Include="Source\Items\Components\Machines\Reactor.cs" />
<Compile Include="Source\Items\Components\Signal\Wire.cs" /> <Compile Include="Source\Items\Components\Machines\Steering.cs" />
<Compile Include="Source\Items\Components\StatusHUD.cs" /> <Compile Include="Source\Items\Components\Power\PowerContainer.cs" />
<Compile Include="Source\Items\Components\Turret.cs" /> <Compile Include="Source\Items\Components\Power\Powered.cs" />
<Compile Include="Source\Items\DockingPort.cs" /> <Compile Include="Source\Items\Components\Power\PowerTransfer.cs" />
<Compile Include="Source\Items\Inventory.cs" /> <Compile Include="Source\Items\Components\Signal\Connection.cs" />
<Compile Include="Source\Items\Item.cs" /> <Compile Include="Source\Items\Components\Signal\ConnectionPanel.cs" />
<Compile Include="Source\Items\ItemPrefab.cs" /> <Compile Include="Source\Items\Components\Signal\Wire.cs" />
<Compile Include="Source\Items\Rope.cs" /> <Compile Include="Source\Items\Components\StatusHUD.cs" />
<Compile Include="Source\Map\Explosion.cs" /> <Compile Include="Source\Items\Components\Turret.cs" />
<Compile Include="Source\Map\FireSource.cs" /> <Compile Include="Source\Items\DockingPort.cs" />
<Compile Include="Source\Map\Gap.cs" /> <Compile Include="Source\Items\Inventory.cs" />
<Compile Include="Source\Map\Hull.cs" /> <Compile Include="Source\Items\Item.cs" />
<Compile Include="Source\Map\Levels\LevelObjects\LevelObject.cs" /> <Compile Include="Source\Items\ItemPrefab.cs" />
<Compile Include="Source\Map\Levels\LevelObjects\LevelObjectManager.cs" /> <Compile Include="Source\Items\Rope.cs" />
<Compile Include="Source\Map\Levels\LevelObjects\LevelObjectPrefab.cs" /> <Compile Include="Source\Map\Explosion.cs" />
<Compile Include="Source\Map\Levels\CaveGenerator.cs" /> <Compile Include="Source\Map\FireSource.cs" />
<Compile Include="Source\Map\Levels\Level.cs" /> <Compile Include="Source\Map\Gap.cs" />
<Compile Include="Source\Map\Levels\LevelObjects\LevelTrigger.cs" /> <Compile Include="Source\Map\Hull.cs" />
<Compile Include="Source\Map\Levels\LevelRenderer.cs" /> <Compile Include="Source\Map\Levels\LevelObjects\LevelObject.cs" />
<Compile Include="Source\Map\Levels\Ruins\RuinGenerator.cs" /> <Compile Include="Source\Map\Levels\LevelObjects\LevelObjectManager.cs" />
<Compile Include="Source\Map\Levels\WaterRenderer.cs" /> <Compile Include="Source\Map\Levels\LevelObjects\LevelObjectPrefab.cs" />
<Compile Include="Source\Map\Levels\LevelWall.cs" /> <Compile Include="Source\Map\Levels\CaveGenerator.cs" />
<Compile Include="Source\Map\Lights\ConvexHull.cs" /> <Compile Include="Source\Map\Levels\Level.cs" />
<Compile Include="Source\Map\Lights\LightManager.cs" /> <Compile Include="Source\Map\Levels\LevelObjects\LevelTrigger.cs" />
<Compile Include="Source\Map\Lights\LightSource.cs" /> <Compile Include="Source\Map\Levels\LevelRenderer.cs" />
<Compile Include="Source\Map\LinkedSubmarine.cs" /> <Compile Include="Source\Map\Levels\Ruins\RuinGenerator.cs" />
<Compile Include="Source\Map\Map\Location.cs" /> <Compile Include="Source\Map\Levels\WaterRenderer.cs" />
<Compile Include="Source\Map\Map\Map.cs" /> <Compile Include="Source\Map\Levels\LevelWall.cs" />
<Compile Include="Source\Map\MapEntity.cs" /> <Compile Include="Source\Map\Lights\ConvexHull.cs" />
<Compile Include="Source\Map\MapEntityPrefab.cs" /> <Compile Include="Source\Map\Lights\LightManager.cs" />
<Compile Include="Source\Map\Structure.cs" /> <Compile Include="Source\Map\Lights\LightSource.cs" />
<Compile Include="Source\Map\StructurePrefab.cs" /> <Compile Include="Source\Map\LinkedSubmarine.cs" />
<Compile Include="Source\Map\Submarine.cs" /> <Compile Include="Source\Map\Map\Location.cs" />
<Compile Include="Source\Map\WayPoint.cs" /> <Compile Include="Source\Map\Map\Map.cs" />
<Compile Include="Source\Networking\BanList.cs" /> <Compile Include="Source\Map\MapEntity.cs" />
<Compile Include="Source\Networking\ChatMessage.cs" /> <Compile Include="Source\Map\MapEntityPrefab.cs" />
<Compile Include="Source\Networking\EntitySpawner.cs" /> <Compile Include="Source\Map\Structure.cs" />
<Compile Include="Source\Networking\FileTransfer\FileReceiver.cs" /> <Compile Include="Source\Map\StructurePrefab.cs" />
<Compile Include="Source\Networking\GameClient.cs" /> <Compile Include="Source\Map\Submarine.cs" />
<Compile Include="Source\Networking\GameServer.cs" /> <Compile Include="Source\Map\SubmarineBody.cs" />
<Compile Include="Source\Networking\GameServerSettings.cs" /> <Compile Include="Source\Map\WayPoint.cs" />
<Compile Include="Source\Networking\NetEntityEvent\ClientEntityEventManager.cs" /> <Compile Include="Source\Media\Video.cs" />
<Compile Include="Source\Networking\NetEntityEvent\NetEntityEvent.cs" /> <Compile Include="Source\Networking\BanList.cs" />
<Compile Include="Source\Networking\NetStats.cs" /> <Compile Include="Source\Networking\ChatMessage.cs" />
<Compile Include="Source\Networking\NetworkMember.cs" /> <Compile Include="Source\Networking\Client.cs" />
<Compile Include="Source\Networking\OrderChatMessage.cs" /> <Compile Include="Source\Networking\EntitySpawner.cs" />
<Compile Include="Source\Networking\ServerInfo.cs" /> <Compile Include="Source\Networking\FileTransfer\FileReceiver.cs" />
<Compile Include="Source\Networking\ServerLog.cs" /> <Compile Include="Source\Networking\GameClient.cs" />
<Compile Include="Source\Networking\Voting.cs" /> <Compile Include="Source\Networking\NetEntityEvent\ClientEntityEventManager.cs" />
<Compile Include="Source\Networking\WhiteList.cs" /> <Compile Include="Source\Networking\NetEntityEvent\NetEntityEvent.cs" />
<Compile Include="Source\Particles\Decal.cs" /> <Compile Include="Source\Networking\NetStats.cs" />
<Compile Include="Source\Particles\DecalManager.cs" /> <Compile Include="Source\Networking\OrderChatMessage.cs" />
<Compile Include="Source\Particles\DecalPrefab.cs" /> <Compile Include="Source\Networking\RespawnManager.cs" />
<Compile Include="Source\Particles\Particle.cs" /> <Compile Include="Source\Networking\ServerInfo.cs" />
<Compile Include="Source\Particles\ParticleEmitter.cs" /> <Compile Include="Source\Networking\ServerLog.cs" />
<Compile Include="Source\Particles\ParticleManager.cs" /> <Compile Include="Source\Networking\ServerSettings.cs" />
<Compile Include="Source\Particles\ParticlePrefab.cs" /> <Compile Include="Source\Networking\SteamManager.cs" />
<Compile Include="Source\Physics\PhysicsBody.cs" /> <Compile Include="Source\Networking\Voip\VoipCapture.cs" />
<Compile Include="Source\PlayerInput.cs" /> <Compile Include="Source\Networking\Voip\VoipClient.cs" />
<Compile Include="Source\Program.cs" /> <Compile Include="Source\Networking\Voip\VoipConfig.cs" />
<Compile Include="Source\Screens\CharacterEditorScreen.cs" /> <Compile Include="Source\Networking\Voting.cs" />
<Compile Include="Source\Screens\BlurEffect.cs" /> <Compile Include="Source\Networking\WhiteList.cs" />
<Compile Include="Source\Screens\CampaignSetupUI.cs" /> <Compile Include="Source\Particles\Decal.cs" />
<Compile Include="Source\Screens\CampaignUI.cs" /> <Compile Include="Source\Particles\DecalManager.cs" />
<Compile Include="Source\Screens\LevelEditorScreen.cs" /> <Compile Include="Source\Particles\DecalPrefab.cs" />
<Compile Include="Source\Screens\OldCharacterEditorScreen.cs" /> <Compile Include="Source\Particles\Particle.cs" />
<Compile Include="Source\Screens\SpriteEditorScreen.cs" /> <Compile Include="Source\Particles\ParticleEmitter.cs" />
<Compile Include="Source\Screens\SteamWorkshopScreen.cs" /> <Compile Include="Source\Particles\ParticleManager.cs" />
<Compile Include="Source\Screens\SubEditorScreen.cs" /> <Compile Include="Source\Particles\ParticlePrefab.cs" />
<Compile Include="Source\Screens\GameScreen.cs" /> <Compile Include="Source\Physics\PhysicsBody.cs" />
<Compile Include="Source\Screens\LobbyScreen.cs" /> <Compile Include="Source\PlayerInput.cs" />
<Compile Include="Source\Screens\MainMenuScreen.cs" /> <Compile Include="Source\Program.cs" />
<Compile Include="Source\Screens\NetLobbyScreen.cs" /> <Compile Include="Source\Screens\CharacterEditorScreen.cs" />
<Compile Include="Source\Screens\ParticleEditorScreen.cs" /> <Compile Include="Source\Screens\BlurEffect.cs" />
<Compile Include="Source\Screens\Screen.cs" /> <Compile Include="Source\Screens\CampaignSetupUI.cs" />
<Compile Include="Source\Screens\ServerListScreen.cs" /> <Compile Include="Source\Screens\CampaignUI.cs" />
<Compile Include="Source\Serialization\SerializableEntityEditor.cs" /> <Compile Include="Source\Screens\LevelEditorScreen.cs" />
<Compile Include="Source\Sounds\OggSound.cs" /> <Compile Include="Source\Screens\SpriteEditorScreen.cs" />
<Compile Include="Source\Sounds\Sound.cs" /> <Compile Include="Source\Screens\SteamWorkshopScreen.cs" />
<Compile Include="Source\Sounds\SoundChannel.cs" /> <Compile Include="Source\Screens\SubEditorScreen.cs" />
<Compile Include="Source\Sounds\SoundManager.cs" /> <Compile Include="Source\Screens\GameScreen.cs" />
<Compile Include="Source\Sounds\SoundPlayer.cs" /> <Compile Include="Source\Screens\LobbyScreen.cs" />
<Compile Include="Source\Sprite\DeformableSprite.cs" /> <Compile Include="Source\Screens\MainMenuScreen.cs" />
<Compile Include="Source\Sprite\DeformAnimations\CustomDeformation.cs" /> <Compile Include="Source\Screens\NetLobbyScreen.cs" />
<Compile Include="Source\Sprite\DeformAnimations\Inflate.cs" /> <Compile Include="Source\Screens\ParticleEditorScreen.cs" />
<Compile Include="Source\Sprite\DeformAnimations\NoiseDeformation.cs" /> <Compile Include="Source\Screens\Screen.cs" />
<Compile Include="Source\Sprite\DeformAnimations\PositionalDeformation.cs" /> <Compile Include="Source\Screens\ServerListScreen.cs" />
<Compile Include="Source\Sprite\DeformAnimations\JointBendDeformation.cs" /> <Compile Include="Source\Serialization\SerializableEntityEditor.cs" />
<Compile Include="Source\Sprite\DeformAnimations\SpriteDeformation.cs" /> <Compile Include="Source\Sounds\OggSound.cs" />
<Compile Include="Source\Sprite\Sprite.cs" /> <Compile Include="Source\Sounds\Sound.cs" />
<Compile Include="Source\Sprite\SpriteSheet.cs" /> <Compile Include="Source\Sounds\SoundChannel.cs" />
<Compile Include="Source\Utils\MathUtils.cs" /> <Compile Include="Source\Sounds\SoundFilters.cs" />
<Compile Include="Source\Utils\TextureLoader.cs" /> <Compile Include="Source\Sounds\SoundManager.cs" />
<Compile Include="Source\Utils\ToolBox.cs" /> <Compile Include="Source\Sounds\SoundPlayer.cs" />
</ItemGroup> <Compile Include="Source\Sounds\VoipSound.cs" />
<ItemGroup> <Compile Include="Source\Sounds\VideoSound.cs" />
<Reference Include="GameAnalytics.Mono, Version=1.0.6710.29255, Culture=neutral, processorArchitecture=MSIL"> <Compile Include="Source\Sprite\DeformableSprite.cs" />
<HintPath>..\..\Libraries\NuGet\GameAnalytics.Mono.SDK.1.1.12\lib\net45\GameAnalytics.Mono.dll</HintPath> <Compile Include="Source\Sprite\DeformAnimations\CustomDeformation.cs" />
</Reference> <Compile Include="Source\Sprite\DeformAnimations\Inflate.cs" />
<Reference Condition="$(DefineConstants.Contains('WINDOWS'))" Include="MonoGame.Framework.WindowsDX"> <Compile Include="Source\Sprite\DeformAnimations\NoiseDeformation.cs" />
<HintPath>..\..\Libraries\NuGet\MonoGame.Framework.WindowsDX.3.6.0.1625\lib\net40\MonoGame.Framework.dll</HintPath> <Compile Include="Source\Sprite\DeformAnimations\PositionalDeformation.cs" />
</Reference> <Compile Include="Source\Sprite\DeformAnimations\JointBendDeformation.cs" />
<Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL"> <Compile Include="Source\Sprite\DeformAnimations\SpriteDeformation.cs" />
<HintPath>..\..\Libraries\NuGet\NLog.4.3.8\lib\net45\NLog.dll</HintPath> <Compile Include="Source\Sprite\Sprite.cs" />
</Reference> <Compile Include="Source\Sprite\SpriteSheet.cs" />
<Reference Condition="$(DefineConstants.Contains('WINDOWS'))" Include="PresentationCore" /> <Compile Include="Source\Utils\MathUtils.cs" />
<Reference Condition="$(DefineConstants.Contains('WINDOWS'))" Include="SharpDX"> <Compile Include="Source\Utils\TextureLoader.cs" />
<HintPath>..\..\Libraries\NuGet\MonoGame.Framework.WindowsDX.3.6.0.1625\lib\net40\SharpDX.dll</HintPath> <Compile Include="Source\Utils\ToolBox.cs" />
</Reference> </ItemGroup>
<Reference Condition="$(DefineConstants.Contains('WINDOWS'))" Include="NVorbis"> <ItemGroup>
<HintPath>..\..\Libraries\NuGet\NVorbis.0.8.5.0\lib\NVorbis.dll</HintPath> <Reference Include="Concentus, Version=1.1.6.0, Culture=neutral, processorArchitecture=MSIL">
</Reference> <HintPath>..\..\Libraries\NuGet\Concentus.1.1.7\lib\portable-net45+win+wpa81+wp80\Concentus.dll</HintPath>
<Reference Include="OpenTK, Version=1.1.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4, processorArchitecture=MSIL"> </Reference>
<SpecificVersion>False</SpecificVersion> <Reference Include="GameAnalytics.Mono, Version=1.0.6710.29255, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\Libraries\NuGet\OpenTK.2.0.0\lib\net20\OpenTK.dll</HintPath> <HintPath>..\..\Libraries\NuGet\GameAnalytics.Mono.SDK.1.1.12\lib\net45\GameAnalytics.Mono.dll</HintPath>
</Reference> </Reference>
<Reference Include="System" /> <Reference Condition="$(DefineConstants.Contains('WINDOWS'))" Include="MonoGame.Framework, Version=3.7.1.189, Culture=neutral, processorArchitecture=MSIL">
<Reference Include="System.Data.SQLite, Version=1.0.102.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139, processorArchitecture=MSIL"> <HintPath>..\..\Libraries\NuGet\MonoGame.Framework.WindowsDX.3.7.1.189\lib\net45\MonoGame.Framework.dll</HintPath>
<HintPath>..\..\Libraries\NuGet\GameAnalytics.Mono.SDK.1.1.12\lib\net45\System.Data.SQLite.dll</HintPath> </Reference>
</Reference> <Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
<Reference Include="System.Drawing" /> <HintPath>..\..\Libraries\NuGet\NLog.4.3.8\lib\net45\NLog.dll</HintPath>
<Reference Include="System.Windows.Forms" /> </Reference>
<Reference Include="System.Xml" /> <Reference Include="nVLC, Version=3.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<Reference Include="System.Xml.Linq" /> <HintPath>..\..\Libraries\NuGet\nVLC.3.0.0\lib\net40\nVLC.dll</HintPath>
<Reference Condition="$(DefineConstants.Contains('LINUX')) OR $(DefineConstants.Contains('OSX'))" Include="MonoGame.Framework.DesktopGL"> </Reference>
<HintPath>..\..\Libraries\NuGet\MonoGame.Framework.DesktopGL.3.6.0.1625\lib\net40\MonoGame.Framework.dll</HintPath> <Reference Condition="$(DefineConstants.Contains('WINDOWS'))" Include="NVorbis, Version=0.8.6.0, Culture=neutral, processorArchitecture=MSIL">
</Reference> <HintPath>..\..\Libraries\NuGet\NVorbis.0.8.6\lib\net35\NVorbis.dll</HintPath>
<Reference Include="RestSharp"> </Reference>
<HintPath>..\..\Libraries\NuGet\RestSharp.105.2.3\lib\net45\RestSharp.dll</HintPath> <Reference Include="OpenTK, Version=3.0.1.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4, processorArchitecture=MSIL">
</Reference> <HintPath>..\..\Libraries\NuGet\OpenTK.3.0.1\lib\net20\OpenTK.dll</HintPath>
</ItemGroup> </Reference>
<ItemGroup> <Reference Condition="$(DefineConstants.Contains('WINDOWS'))" Include="PresentationCore" />
<Content Include="freetype6.dll"> <Reference Include="RestSharp, Version=105.2.3.0, Culture=neutral, processorArchitecture=MSIL">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <HintPath>..\..\Libraries\NuGet\RestSharp.105.2.3\lib\net45\RestSharp.dll</HintPath>
</Content> </Reference>
<Content Include="oalinst.exe"> <Reference Condition="$(DefineConstants.Contains('WINDOWS'))" Include="SharpDX, Version=4.2.0.0, Culture=neutral, PublicKeyToken=b4dcf0f35e5521f1, processorArchitecture=MSIL">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <HintPath>..\..\Libraries\NuGet\SharpDX.4.2.0\lib\net45\SharpDX.dll</HintPath>
</Content> </Reference>
<Content Include="wrap_oal.dll"> <Reference Condition="$(DefineConstants.Contains('WINDOWS'))" Include="SharpDX.Direct2D1, Version=4.2.0.0, Culture=neutral, PublicKeyToken=b4dcf0f35e5521f1, processorArchitecture=MSIL">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <HintPath>..\..\Libraries\NuGet\SharpDX.Direct2D1.4.2.0\lib\net45\SharpDX.Direct2D1.dll</HintPath>
</Content> </Reference>
<Content Include="MonoGame.Framework.dll.config"> <Reference Condition="$(DefineConstants.Contains('WINDOWS'))" Include="SharpDX.Direct3D11, Version=4.2.0.0, Culture=neutral, PublicKeyToken=b4dcf0f35e5521f1, processorArchitecture=MSIL">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <HintPath>..\..\Libraries\NuGet\SharpDX.Direct3D11.4.2.0\lib\net45\SharpDX.Direct3D11.dll</HintPath>
</Content> </Reference>
<Content Include="OpenTK.dll.config"> <Reference Condition="$(DefineConstants.Contains('WINDOWS'))" Include="SharpDX.Direct3D9, Version=4.2.0.0, Culture=neutral, PublicKeyToken=b4dcf0f35e5521f1, processorArchitecture=MSIL">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <HintPath>..\..\Libraries\NuGet\SharpDX.Direct3D9.4.2.0\lib\net45\SharpDX.Direct3D9.dll</HintPath>
</Content> </Reference>
<Content Include="SharpFont.dll.config"> <Reference Condition="$(DefineConstants.Contains('WINDOWS'))" Include="SharpDX.DXGI, Version=4.2.0.0, Culture=neutral, PublicKeyToken=b4dcf0f35e5521f1, processorArchitecture=MSIL">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <HintPath>..\..\Libraries\NuGet\SharpDX.DXGI.4.2.0\lib\net45\SharpDX.DXGI.dll</HintPath>
</Content> </Reference>
</ItemGroup> <Reference Condition="$(DefineConstants.Contains('WINDOWS'))" Include="SharpDX.Mathematics, Version=4.2.0.0, Culture=neutral, PublicKeyToken=b4dcf0f35e5521f1, processorArchitecture=MSIL">
<ItemGroup> <HintPath>..\..\Libraries\NuGet\SharpDX.Mathematics.4.2.0\lib\net45\SharpDX.Mathematics.dll</HintPath>
<BootstrapperPackage Include=".NETFramework,Version=v4.0"> </Reference>
<Visible>False</Visible> <Reference Condition="$(DefineConstants.Contains('WINDOWS'))" Include="SharpDX.MediaFoundation, Version=4.2.0.0, Culture=neutral, PublicKeyToken=b4dcf0f35e5521f1, processorArchitecture=MSIL">
<ProductName>Microsoft .NET Framework 4 %28x86 and x64%29</ProductName> <HintPath>..\..\Libraries\NuGet\SharpDX.MediaFoundation.4.2.0\lib\net45\SharpDX.MediaFoundation.dll</HintPath>
<Install>true</Install> </Reference>
</BootstrapperPackage> <Reference Condition="$(DefineConstants.Contains('WINDOWS'))" Include="SharpDX.XAudio2, Version=4.2.0.0, Culture=neutral, PublicKeyToken=b4dcf0f35e5521f1, processorArchitecture=MSIL">
<BootstrapperPackage Include="Microsoft.Net.Client.3.5"> <HintPath>..\..\Libraries\NuGet\SharpDX.XAudio2.4.2.0\lib\net45\SharpDX.XAudio2.dll</HintPath>
<Visible>False</Visible> </Reference>
<ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName> <Reference Condition="$(DefineConstants.Contains('WINDOWS'))" Include="SharpDX.XInput, Version=4.2.0.0, Culture=neutral, PublicKeyToken=b4dcf0f35e5521f1, processorArchitecture=MSIL">
<Install>false</Install> <HintPath>..\..\Libraries\NuGet\SharpDX.XInput.4.2.0\lib\net45\SharpDX.XInput.dll</HintPath>
</BootstrapperPackage> </Reference>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1"> <Reference Include="System" />
<Visible>False</Visible> <Reference Include="System.ComponentModel.Composition" />
<ProductName>.NET Framework 3.5 SP1</ProductName> <Reference Include="System.Data.SQLite, Version=1.0.102.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139, processorArchitecture=MSIL">
<Install>false</Install> <HintPath>..\..\Libraries\NuGet\GameAnalytics.Mono.SDK.1.1.12\lib\net45\System.Data.SQLite.dll</HintPath>
</BootstrapperPackage> </Reference>
<BootstrapperPackage Include="Microsoft.Windows.Installer.4.5"> <Reference Include="System.Drawing" />
<Visible>False</Visible> <Reference Include="System.IO.Compression" />
<ProductName>Windows Installer 4.5</ProductName> <Reference Include="System.Net.Http" />
<Install>true</Install> <Reference Include="System.Numerics" />
</BootstrapperPackage> <Reference Include="System.Runtime.InteropServices.RuntimeInformation, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
</ItemGroup> <HintPath>..\..\Libraries\NuGet\System.Runtime.InteropServices.RuntimeInformation.4.3.0\lib\net45\System.Runtime.InteropServices.RuntimeInformation.dll</HintPath>
<ItemGroup> </Reference>
<ProjectReference Include="..\..\Libraries\Facepunch.Steamworks\Facepunch.Steamworks.csproj"> <Reference Include="System.Windows.Forms" />
<Project>{3af0347c-5a9b-4421-868c-8ee3dbfaebc6}</Project> <Reference Include="System.Xml" />
<Name>Facepunch.Steamworks</Name> <Reference Include="System.Xml.Linq" />
</ProjectReference> <Reference Condition="$(DefineConstants.Contains('LINUX')) OR $(DefineConstants.Contains('OSX'))" Include="MonoGame.Framework.DesktopGL">
<ProjectReference Include="..\..\Libraries\Hyper.ComponentModel\Hyper.ComponentModel.csproj"> <HintPath>..\..\Libraries\NuGet\MonoGame.Framework.DesktopGL.3.7.1.189\lib\net45\MonoGame.Framework.dll</HintPath>
<Project>{3b8f9edb-6e5e-450c-abc2-ec49075d0b50}</Project> </Reference>
<Name>Hyper.ComponentModel</Name> </ItemGroup>
</ProjectReference> <ItemGroup>
<ProjectReference Include="..\..\Libraries\Lidgren.Network\Lidgren.Network.csproj"> <Content Include="freetype6.dll">
<Project>{49ba1c69-6104-41ac-a5d8-b54fa9f696e8}</Project> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<Name>Lidgren.Network</Name> </Content>
</ProjectReference> <Content Include="libvlc.dll">
<ProjectReference Include="..\..\Libraries\SharpFont\Source\SharpFont\SharpFont.csproj"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<Project>{c293db32-fa42-486d-b128-5a12522fae4e}</Project> </Content>
<Name>SharpFont</Name> <Content Include="libvlccore.dll">
</ProjectReference> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<ProjectReference Include="..\..\Libraries\Farseer Physics Engine 3.5\Farseer Physics MonoGame.csproj"> </Content>
<Project>{0AAD36E3-51A5-4A07-AB60-5C8A66BD38B7}</Project> <Content Include="plugins\access\libfilesystem_plugin.dll">
<Name>Farseer Physics MonoGame</Name> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</ProjectReference> </Content>
</ItemGroup> <Content Include="plugins\audio_filter\libaudio_format_plugin.dll">
<ItemGroup> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<None Include="packages.config" /> </Content>
</ItemGroup> <Content Include="plugins\audio_filter\libugly_resampler_plugin.dll">
<ItemGroup /> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<Import Project="..\BarotraumaShared\BarotraumaShared.projitems" Label="Shared" /> </Content>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Content Include="plugins\audio_output\libamem_plugin.dll">
<Import Project="..\..\Libraries\NuGet\GameAnalytics.Mono.SDK.1.1.12\build\net45\GameAnalytics.Mono.SDK.targets" Condition="Exists('..\..\Libraries\NuGet\GameAnalytics.Mono.SDK.1.1.12\build\net45\GameAnalytics.Mono.SDK.targets')" /> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild"> </Content>
<PropertyGroup> <Content Include="plugins\codec\libavcodec_plugin.dll">
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</PropertyGroup> </Content>
<Error Condition="!Exists('..\..\Libraries\NuGet\GameAnalytics.Mono.SDK.1.1.12\build\net45\GameAnalytics.Mono.SDK.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\Libraries\NuGet\GameAnalytics.Mono.SDK.1.1.12\build\net45\GameAnalytics.Mono.SDK.targets'))" /> <Content Include="plugins\demux\libmp4_plugin.dll">
</Target> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. </Content>
Other similar extension points exist, see Microsoft.Common.targets. <Content Include="plugins\packetizer\libpacketizer_mpeg4audio_plugin.dll">
<Target Name="BeforeBuild"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Target> </Content>
<Target Name="AfterBuild"> <Content Include="plugins\packetizer\libpacketizer_mpeg4video_plugin.dll">
</Target> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
--> </Content>
<Content Include="plugins\video_chroma\librv32_plugin.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="plugins\video_chroma\libswscale_plugin.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="plugins\video_output\libvmem_plugin.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="wrap_oal.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="MonoGame.Framework.dll.config">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="OpenTK.dll.config">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="SharpFont.dll.config">
<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\Facepunch.Steamworks\Facepunch.Steamworks.csproj">
<Project>{3af0347c-5a9b-4421-868c-8ee3dbfaebc6}</Project>
<Name>Facepunch.Steamworks</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>
<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>
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
<None Include="libvlc.dylib">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="packages.config" />
<None Include="libopenal.1.dylib">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup />
<Import Project="..\BarotraumaShared\BarotraumaShared.projitems" Label="Shared" />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="..\..\Libraries\NuGet\GameAnalytics.Mono.SDK.1.1.12\build\net45\GameAnalytics.Mono.SDK.targets" Condition="Exists('..\..\Libraries\NuGet\GameAnalytics.Mono.SDK.1.1.12\build\net45\GameAnalytics.Mono.SDK.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\..\Libraries\NuGet\GameAnalytics.Mono.SDK.1.1.12\build\net45\GameAnalytics.Mono.SDK.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\Libraries\NuGet\GameAnalytics.Mono.SDK.1.1.12\build\net45\GameAnalytics.Mono.SDK.targets'))" />
<Error Condition="!Exists('..\..\Libraries\NuGet\MonoGame.Framework.WindowsDX.3.7.1.189\build\MonoGame.Framework.WindowsDX.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\Libraries\NuGet\MonoGame.Framework.WindowsDX.3.7.1.189\build\MonoGame.Framework.WindowsDX.targets'))" />
</Target>
<Import Project="..\..\Libraries\NuGet\MonoGame.Framework.WindowsDX.3.7.1.189\build\MonoGame.Framework.WindowsDX.targets" Condition="Exists('..\..\Libraries\NuGet\MonoGame.Framework.WindowsDX.3.7.1.189\build\MonoGame.Framework.WindowsDX.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> </Project>
@@ -1,18 +1,21 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup> <PropertyGroup>
<PublishUrlHistory>publish\</PublishUrlHistory> <PublishUrlHistory>publish\</PublishUrlHistory>
<InstallUrlHistory /> <InstallUrlHistory />
<SupportUrlHistory /> <SupportUrlHistory />
<UpdateUrlHistory /> <UpdateUrlHistory />
<BootstrapperUrlHistory /> <BootstrapperUrlHistory />
<ErrorReportUrlHistory /> <ErrorReportUrlHistory />
<FallbackCulture>en-US</FallbackCulture> <FallbackCulture>en-US</FallbackCulture>
<VerifyUploadedFiles>false</VerifyUploadedFiles> <VerifyUploadedFiles>false</VerifyUploadedFiles>
<ProjectView>ShowAllFiles</ProjectView> <ProjectView>ShowAllFiles</ProjectView>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<ReferencePath> <ReferencePath>
</ReferencePath> </ReferencePath>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'DebugWindows|x64'">
<EnableUnmanagedDebugging>false</EnableUnmanagedDebugging>
</PropertyGroup>
</Project> </Project>
@@ -0,0 +1,8 @@
// This file is used by Code Analysis to maintain SuppressMessage
// attributes that are applied to this project.
// Project-level suppressions either have no target or are given
// a specific target and scoped to a namespace, type, member, etc.
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Potential Code Quality Issues", "RECS0026:Possible unassigned object created by 'new'", Justification = "<Pending>", Scope = "member", Target = "~M:Barotrauma.GameSettings.CreateSettingsFrame")]
@@ -2,8 +2,8 @@
<configuration> <configuration>
<dllmap dll="SDL2.dll" os="osx" target="libSDL2-2.0.0.dylib" /> <dllmap dll="SDL2.dll" os="osx" target="libSDL2-2.0.0.dylib" />
<dllmap dll="soft_oal.dll" os="osx" target="libopenal.1.dylib" /> <dllmap dll="soft_oal.dll" os="osx" target="libopenal.1.dylib" />
<dllmap dll="SDL2.dll" os="linux" cpu="x86" target="./x86/libSDL2-2.0.so.0" /> <!--<dllmap dll="SDL2.dll" os="linux" cpu="x86" target="./x86/libSDL2-2.0.so.0" />-->
<dllmap dll="soft_oal.dll" os="linux" cpu="x86" target="./x86/libopenal.so.1" /> <dllmap dll="soft_oal.dll" os="linux" cpu="x86" target="./x86/libopenal.so.1" />
<dllmap dll="SDL2.dll" os="linux" cpu="x86-64" target="./x64/libSDL2-2.0.so.0" /> <!--<dllmap dll="SDL2.dll" os="linux" cpu="x86-64" target="./x64/libSDL2-2.0.so.0" />-->
<dllmap dll="soft_oal.dll" os="linux" cpu="x86-64" target="./x64/libopenal.so.1" /> <dllmap dll="soft_oal.dll" os="linux" cpu="x86-64" target="./x64/libopenal.so.1" />
</configuration> </configuration>
@@ -6,7 +6,7 @@
<dllmap os="linux" dll="opencl.dll" target="libOpenCL.so"/> <dllmap os="linux" dll="opencl.dll" target="libOpenCL.so"/>
<dllmap os="linux" dll="libX11" target="libX11.so.6"/> <dllmap os="linux" dll="libX11" target="libX11.so.6"/>
<dllmap os="linux" dll="libXi" target="libXi.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="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="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="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="alut.dll" target="/System/Library/Frameworks/OpenAL.framework/OpenAL" />
@@ -31,5 +31,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers // You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below: // by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")] // [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("0.8.9.3")] [assembly: AssemblyVersion("0.8.9.4")]
[assembly: AssemblyFileVersion("0.8.9.3")] [assembly: AssemblyFileVersion("0.8.9.4")]
@@ -14,9 +14,9 @@ namespace Barotrauma
Vector2 pos = Character.WorldPosition; Vector2 pos = Character.WorldPosition;
pos.Y = -pos.Y; pos.Y = -pos.Y;
if (selectedAiTarget?.Entity != null) if (SelectedAiTarget?.Entity != null)
{ {
GUI.DrawLine(spriteBatch, pos, new Vector2(selectedAiTarget.WorldPosition.X, -selectedAiTarget.WorldPosition.Y), Color.Red * 0.3f, 0, 5); GUI.DrawLine(spriteBatch, pos, new Vector2(SelectedAiTarget.WorldPosition.X, -SelectedAiTarget.WorldPosition.Y), Color.Red * 0.3f, 0, 5);
if (wallTarget != null) if (wallTarget != null)
{ {
@@ -27,7 +27,7 @@ namespace Barotrauma
GUI.DrawLine(spriteBatch, pos, wallTargetPos, Color.Orange * 0.5f, 0, 5); GUI.DrawLine(spriteBatch, pos, wallTargetPos, Color.Orange * 0.5f, 0, 5);
} }
GUI.Font.DrawString(spriteBatch, $"{selectedAiTarget.Entity.ToString()} ({targetValue.ToString()})", pos - Vector2.UnitY * 20.0f, Color.Red); GUI.Font.DrawString(spriteBatch, $"{SelectedAiTarget.Entity.ToString()} ({targetValue.ToString()})", pos - Vector2.UnitY * 20.0f, Color.Red);
} }
/*GUI.Font.DrawString(spriteBatch, targetValue.ToString(), pos - Vector2.UnitY * 80.0f, Color.Red); /*GUI.Font.DrawString(spriteBatch, targetValue.ToString(), pos - Vector2.UnitY * 80.0f, Color.Red);
@@ -1,4 +1,6 @@
using Microsoft.Xna.Framework; using Barotrauma.Networking;
using Microsoft.Xna.Framework;
using System.Linq;
namespace Barotrauma namespace Barotrauma
{ {
@@ -21,11 +23,11 @@ namespace Barotrauma
public override void DebugDraw(Microsoft.Xna.Framework.Graphics.SpriteBatch spriteBatch) public override void DebugDraw(Microsoft.Xna.Framework.Graphics.SpriteBatch spriteBatch)
{ {
if (selectedAiTarget?.Entity != null) if (SelectedAiTarget?.Entity != null)
{ {
GUI.DrawLine(spriteBatch, GUI.DrawLine(spriteBatch,
new Vector2(Character.DrawPosition.X, -Character.DrawPosition.Y), new Vector2(Character.DrawPosition.X, -Character.DrawPosition.Y),
new Vector2(selectedAiTarget.WorldPosition.X, -selectedAiTarget.WorldPosition.Y), Color.Red); new Vector2(SelectedAiTarget.WorldPosition.X, -SelectedAiTarget.WorldPosition.Y), Color.Red);
} }
IndoorsSteeringManager pathSteering = steeringManager as IndoorsSteeringManager; IndoorsSteeringManager pathSteering = steeringManager as IndoorsSteeringManager;
@@ -50,5 +52,52 @@ namespace Barotrauma
Color.LightGreen); Color.LightGreen);
} }
} }
//TODO: move this to the shared project, otherwise bots won't be able to report things in multiplayer
partial void ReportProblems()
{
if (GameMain.Client != null) return;
Order newOrder = null;
if (Character.CurrentHull != null)
{
if (Character.CurrentHull.FireSources.Count > 0)
{
var orderPrefab = Order.PrefabList.Find(o => o.AITag == "reportfire");
newOrder = new Order(orderPrefab, Character.CurrentHull, null);
}
if (Character.CurrentHull.ConnectedGaps.Any(g => !g.IsRoomToRoom && g.ConnectedDoor == null && g.Open > 0.0f))
{
var orderPrefab = Order.PrefabList.Find(o => o.AITag == "reportbreach");
newOrder = new Order(orderPrefab, Character.CurrentHull, null);
}
foreach (Character c in Character.CharacterList)
{
if (c.CurrentHull == Character.CurrentHull && !c.IsDead &&
(c.AIController is EnemyAIController || c.TeamID != Character.TeamID))
{
var orderPrefab = Order.PrefabList.Find(o => o.AITag == "reportintruders");
newOrder = new Order(orderPrefab, Character.CurrentHull, null);
}
}
}
if (Character.CurrentHull != null && (Character.Bleeding > 1.0f || Character.Vitality < Character.MaxVitality * 0.1f))
{
var orderPrefab = Order.PrefabList.Find(o => o.AITag == "requestfirstaid");
newOrder = new Order(orderPrefab, Character.CurrentHull, null);
}
if (newOrder != null)
{
if (GameMain.GameSession?.CrewManager != null && GameMain.GameSession.CrewManager.AddOrder(newOrder, newOrder.FadeOutTime))
{
Character.Speak(
newOrder.GetChatMessage("", Character.CurrentHull?.RoomName, givingOrderToSelf: false), ChatMessageType.Order);
}
}
}
} }
} }
@@ -2,38 +2,10 @@
{ {
partial class AICharacter : Character 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) public override void DrawFront(Microsoft.Xna.Framework.Graphics.SpriteBatch spriteBatch, Camera cam)
{ {
base.DrawFront(spriteBatch, cam); base.DrawFront(spriteBatch, cam);
if (GameMain.DebugDraw && !IsDead) aiController.DebugDraw(spriteBatch); if (GameMain.DebugDraw && !IsDead) aiController.DebugDraw(spriteBatch);
} }
} }
} }
@@ -0,0 +1,48 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace Barotrauma
{
partial class HumanoidAnimParams : ISerializableEntity
{
private static GUIListBox editor;
public static GUIListBox Editor
{
get
{
if (editor == null)
{
editor = new GUIListBox(new RectTransform(new Vector2(0.3f, 1), GUI.Canvas));
//editor.AddChild(new SerializableEntityEditor(editor.RectTransform, WalkInstance, false, true, elementHeight: 20));
//editor.AddChild(new SerializableEntityEditor(editor.RectTransform, RunInstance, false, true, elementHeight: 20));
}
return editor;
}
}
public void Save()
{
XDocument doc = XMLExtensions.TryLoadXml(filePath);
if (doc == null || doc.Root == null) return;
SerializableProperty.SerializeProperties(this, doc.Root, true);
XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;
settings.OmitXmlDeclaration = true;
settings.NewLineOnAttributes = true;
using (var writer = XmlWriter.Create(filePath, settings))
{
doc.WriteTo(writer);
writer.Flush();
}
}
}
}
@@ -7,9 +7,9 @@ using FarseerPhysics.Dynamics.Joints;
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Graphics;
using System; using System;
using System.Linq;
using System.Collections.Generic; using System.Collections.Generic;
using Barotrauma.Particles; using Barotrauma.Particles;
using System.Linq;
namespace Barotrauma namespace Barotrauma
{ {
@@ -17,6 +17,233 @@ namespace Barotrauma
{ {
public HashSet<SpriteDeformation> SpriteDeformations { get; protected set; } = new HashSet<SpriteDeformation>(); public HashSet<SpriteDeformation> SpriteDeformations { get; protected set; } = new HashSet<SpriteDeformation>();
/// <summary>
/// Inversed draw order, which is used for drawing the limbs in 3d (deformable sprites).
/// </summary>
protected Limb[] inversedLimbDrawOrder;
partial void UpdateNetPlayerPositionProjSpecific(float deltaTime, float lowestSubPos)
{
if (character != GameMain.Client.Character || !character.AllowInput)
{
//remove states without a timestamp (there may still be ID-based states
//in the list when the controlled character switches to timestamp-based interpolation)
character.MemState.RemoveAll(m => m.Timestamp == 0.0f);
//use simple interpolation for other players' characters and characters that can't move
if (character.MemState.Count > 0)
{
CharacterStateInfo serverPos = character.MemState.Last();
if (!character.isSynced)
{
SetPosition(serverPos.Position, false);
Collider.LinearVelocity = Vector2.Zero;
character.MemLocalState.Clear();
character.LastNetworkUpdateID = serverPos.ID;
character.isSynced = true;
return;
}
if (character.MemState[0].Interact == null || character.MemState[0].Interact.Removed)
{
character.DeselectCharacter();
character.SelectedConstruction = null;
}
else if (character.MemState[0].Interact is Character)
{
character.SelectCharacter((Character)character.MemState[0].Interact);
}
else if (character.MemState[0].Interact is Item newSelectedConstruction)
{
if (newSelectedConstruction != null && character.SelectedConstruction != newSelectedConstruction)
{
foreach (var ic in newSelectedConstruction.Components)
{
if (ic.CanBeSelected) ic.Select(character);
}
}
character.SelectedConstruction = newSelectedConstruction;
}
if (character.MemState[0].Animation == AnimController.Animation.CPR)
{
character.AnimController.Anim = AnimController.Animation.CPR;
}
else if (character.AnimController.Anim == AnimController.Animation.CPR)
{
character.AnimController.Anim = AnimController.Animation.None;
}
Vector2 newVelocity = Collider.LinearVelocity;
Vector2 newPosition = Collider.SimPosition;
float newRotation = Collider.Rotation;
float newAngularVelocity = Collider.AngularVelocity;
Collider.CorrectPosition(character.MemState, out newPosition, out newVelocity, out newRotation, out newAngularVelocity);
newVelocity = newVelocity.ClampLength(100.0f);
if (!MathUtils.IsValid(newVelocity)) { newVelocity = Vector2.Zero; }
overrideTargetMovement = newVelocity.LengthSquared() > 0.01f ? newVelocity : Vector2.Zero;
Collider.LinearVelocity = newVelocity;
Collider.AngularVelocity = newAngularVelocity;
float distSqrd = Vector2.DistanceSquared(newPosition, Collider.SimPosition);
float errorTolerance = character.AllowInput ? 0.01f : 0.1f;
if (distSqrd > errorTolerance)
{
if (distSqrd > 10.0f || !character.AllowInput)
{
Collider.TargetRotation = newRotation;
SetPosition(newPosition, lerp: distSqrd < 1.0f);
}
else
{
Collider.TargetRotation = newRotation;
Collider.TargetPosition = newPosition;
Collider.MoveToTargetPosition(true);
}
}
//unconscious/dead characters can't correct their position using AnimController movement
// -> we need to correct it manually
if (!character.AllowInput)
{
MainLimb.PullJointWorldAnchorB = Collider.SimPosition;
MainLimb.PullJointEnabled = true;
}
}
character.MemLocalState.Clear();
}
else
{
//remove states with a timestamp (there may still timestamp-based states
//in the list if the controlled character switches from timestamp-based interpolation to ID-based)
character.MemState.RemoveAll(m => m.Timestamp > 0.0f);
for (int i = 0; i < character.MemLocalState.Count; i++)
{
if (character.Submarine == null)
{
//transform in-sub coordinates to outside coordinates
if (character.MemLocalState[i].Position.Y > lowestSubPos)
{
character.MemLocalState[i].TransformInToOutside();
}
}
else if (currentHull?.Submarine != null)
{
//transform outside coordinates to in-sub coordinates
if (character.MemLocalState[i].Position.Y < lowestSubPos)
{
character.MemLocalState[i].TransformOutToInside(currentHull.Submarine);
}
}
}
if (character.MemState.Count < 1) return;
overrideTargetMovement = Vector2.Zero;
CharacterStateInfo serverPos = character.MemState.Last();
if (!character.isSynced)
{
SetPosition(serverPos.Position, false);
Collider.LinearVelocity = Vector2.Zero;
character.MemLocalState.Clear();
character.LastNetworkUpdateID = serverPos.ID;
character.isSynced = true;
return;
}
int localPosIndex = character.MemLocalState.FindIndex(m => m.ID == serverPos.ID);
if (localPosIndex > -1)
{
CharacterStateInfo localPos = character.MemLocalState[localPosIndex];
//the entity we're interacting with doesn't match the server's
if (localPos.Interact != serverPos.Interact)
{
if (serverPos.Interact == null || serverPos.Interact.Removed)
{
character.DeselectCharacter();
character.SelectedConstruction = null;
}
else if (serverPos.Interact is Character)
{
character.SelectCharacter((Character)serverPos.Interact);
}
else
{
var newSelectedConstruction = (Item)serverPos.Interact;
if (newSelectedConstruction != null && character.SelectedConstruction != newSelectedConstruction)
{
newSelectedConstruction.TryInteract(character, true, true);
}
character.SelectedConstruction = newSelectedConstruction;
}
}
if (localPos.Animation != serverPos.Animation)
{
if (serverPos.Animation == AnimController.Animation.CPR)
{
character.AnimController.Anim = AnimController.Animation.CPR;
}
else if (character.AnimController.Anim == AnimController.Animation.CPR)
{
character.AnimController.Anim = AnimController.Animation.None;
}
}
Hull serverHull = Hull.FindHull(ConvertUnits.ToDisplayUnits(serverPos.Position), character.CurrentHull, serverPos.Position.Y < lowestSubPos);
Hull clientHull = Hull.FindHull(ConvertUnits.ToDisplayUnits(localPos.Position), serverHull, localPos.Position.Y < lowestSubPos);
if (serverHull != null && clientHull != null && serverHull.Submarine != clientHull.Submarine)
{
//hull subs don't match => teleport the camera to the other sub
character.Submarine = serverHull.Submarine;
character.CurrentHull = currentHull = serverHull;
SetPosition(serverPos.Position);
character.MemLocalState.Clear();
}
else
{
Vector2 positionError = serverPos.Position - localPos.Position;
float rotationError = serverPos.Rotation - localPos.Rotation;
for (int i = localPosIndex; i < character.MemLocalState.Count; i++)
{
Hull pointHull = Hull.FindHull(ConvertUnits.ToDisplayUnits(character.MemLocalState[i].Position), clientHull, character.MemLocalState[i].Position.Y < lowestSubPos);
if (pointHull != clientHull && ((pointHull == null) || (clientHull == null) || (pointHull.Submarine == clientHull.Submarine))) break;
character.MemLocalState[i].Translate(positionError, rotationError);
}
float errorMagnitude = positionError.Length();
if (errorMagnitude > 0.01f)
{
Collider.TargetPosition = Collider.SimPosition + positionError;
Collider.TargetRotation = Collider.Rotation + rotationError;
Collider.MoveToTargetPosition(lerp: true);
if (errorMagnitude > 0.5f)
{
character.MemLocalState.Clear();
foreach (Limb limb in Limbs)
{
limb.body.TargetPosition = limb.body.SimPosition + positionError;
limb.body.MoveToTargetPosition(lerp: true);
}
}
}
}
}
if (character.MemLocalState.Count > 120) character.MemLocalState.RemoveRange(0, character.MemLocalState.Count - 120);
character.MemState.Clear();
}
}
partial void ImpactProjSpecific(float impact, Body body) partial void ImpactProjSpecific(float impact, Body body)
{ {
float volume = Math.Min(impact - 3.0f, 1.0f); float volume = Math.Min(impact - 3.0f, 1.0f);
@@ -42,7 +269,7 @@ namespace Barotrauma
} }
else if (body.UserData is Limb || body == Collider.FarseerBody) else if (body.UserData is Limb || body == Collider.FarseerBody)
{ {
if (!character.IsRemotePlayer || GameMain.Server != null) if (!character.IsRemotePlayer)
{ {
if (impact > ImpactTolerance) if (impact > ImpactTolerance)
{ {
@@ -115,7 +342,7 @@ namespace Barotrauma
depthSortedLimbs.Reverse(); depthSortedLimbs.Reverse();
inversedLimbDrawOrder = depthSortedLimbs.ToArray(); inversedLimbDrawOrder = depthSortedLimbs.ToArray();
} }
partial void UpdateProjSpecific(float deltaTime) partial void UpdateProjSpecific(float deltaTime)
{ {
LimbJoints.ForEach(j => j.UpdateDeformations(deltaTime)); LimbJoints.ForEach(j => j.UpdateDeformations(deltaTime));
@@ -1,5 +1,6 @@
using Barotrauma.Networking; using Barotrauma.Networking;
using Barotrauma.Particles; using Barotrauma.Particles;
using Barotrauma.Sounds;
using FarseerPhysics; using FarseerPhysics;
using FarseerPhysics.Dynamics; using FarseerPhysics.Dynamics;
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework;
@@ -22,6 +23,8 @@ namespace Barotrauma
protected float hudInfoTimer; protected float hudInfoTimer;
protected bool hudInfoVisible; protected bool hudInfoVisible;
private float findFocusedTimer;
protected float lastRecvPositionUpdateTime; protected float lastRecvPositionUpdateTime;
private float hudInfoHeight; private float hudInfoHeight;
@@ -39,7 +42,6 @@ namespace Barotrauma
if (controlled == value) return; if (controlled == value) return;
controlled = value; controlled = value;
if (controlled != null) controlled.Enabled = true; if (controlled != null) controlled.Enabled = true;
GameMain.GameSession?.CrewManager?.SetCharacterSelected(controlled);
CharacterHealth.OpenHealthWindow = null; CharacterHealth.OpenHealthWindow = null;
} }
@@ -107,13 +109,7 @@ namespace Barotrauma
partial void InitProjSpecific(XDocument doc) partial void InitProjSpecific(XDocument doc)
{ {
soundInterval = doc.Root.GetAttributeFloat("soundinterval", 10.0f); soundInterval = doc.Root.GetAttributeFloat("soundinterval", 10.0f);
soundTimer = Rand.Range(0.0f, soundInterval);
keys = new Key[Enum.GetNames(typeof(InputType)).Length];
for (int i = 0; i < Enum.GetNames(typeof(InputType)).Length; i++)
{
keys[i] = new Key((InputType)i);
}
BloodDecalName = doc.Root.GetAttributeString("blooddecal", ""); BloodDecalName = doc.Root.GetAttributeString("blooddecal", "");
@@ -140,6 +136,13 @@ namespace Barotrauma
hudProgressBars = new Dictionary<object, HUDProgressBar>(); hudProgressBars = new Dictionary<object, HUDProgressBar>();
} }
partial void UpdateLimbLightSource(Limb limb)
{
if (limb.LightSource != null)
{
limb.LightSource.Enabled = enabled;
}
}
/// <summary> /// <summary>
/// Control the Character according to player input /// Control the Character according to player input
@@ -196,7 +199,7 @@ namespace Barotrauma
{ {
cam.OffsetAmount = 0.0f; cam.OffsetAmount = 0.0f;
} }
else if (SelectedConstruction != null && SelectedConstruction.components.Any(ic => (ic.GuiFrame != null && GUI.IsMouseOn(ic.GuiFrame)))) else if (SelectedConstruction != null && SelectedConstruction.Components.Any(ic => (ic.GuiFrame != null && GUI.IsMouseOn(ic.GuiFrame))))
{ {
cam.OffsetAmount = 0.0f; cam.OffsetAmount = 0.0f;
} }
@@ -229,7 +232,7 @@ namespace Barotrauma
partial void UpdateControlled(float deltaTime, Camera cam) partial void UpdateControlled(float deltaTime, Camera cam)
{ {
if (controlled != this) return; if (controlled != this) return;
ControlLocalPlayer(deltaTime, cam); ControlLocalPlayer(deltaTime, cam);
Lights.LightManager.ViewTarget = this; Lights.LightManager.ViewTarget = this;
@@ -257,7 +260,17 @@ namespace Barotrauma
} }
} }
partial void KillProjSpecific() partial void OnAttackedProjSpecific(Character attacker, AttackResult attackResult)
{
if (attackResult.Damage <= 0) { return; }
if (soundTimer < soundInterval * 0.5f)
{
PlaySound(CharacterSound.SoundType.Damage);
soundTimer = soundInterval;
}
}
partial void KillProjSpecific(CauseOfDeathType causeOfDeath, Affliction causeOfDeathAffliction)
{ {
if (GameMain.NetworkMember != null && controlled == this) if (GameMain.NetworkMember != null && controlled == this)
{ {
@@ -285,13 +298,159 @@ namespace Barotrauma
GameMain.GameSession.CrewManager.RemoveCharacter(this); GameMain.GameSession.CrewManager.RemoveCharacter(this);
} }
if (GameMain.NetworkMember?.Character == this) GameMain.NetworkMember.Character = null; if (GameMain.Client?.Character == this) GameMain.Client.Character = null;
if (Lights.LightManager.ViewTarget == this) Lights.LightManager.ViewTarget = null; if (Lights.LightManager.ViewTarget == this) Lights.LightManager.ViewTarget = null;
} }
private List<Item> debugInteractablesInRange = new List<Item>();
private List<Item> debugInteractablesAtCursor = new List<Item>();
private List<Pair<Item, float>> debugInteractablesNearCursor = new List<Pair<Item, float>>();
/// <summary>
/// Finds the front (lowest depth) interactable item at a position. "Interactable" in this case means that the character can "reach" the item.
/// </summary>
/// <param name="character">The Character who is looking for the interactable item, only items that are close enough to this character are returned</param>
/// <param name="simPosition">The item at the simPosition, with the lowest depth, is returned</param>
/// <param name="allowFindingNearestItem">If this is true and an item cannot be found at simPosition then a nearest item will be returned if possible</param>
/// <param name="hull">If a hull is specified, only items within that hull are returned</param>
public Item FindItemAtPosition(Vector2 simPosition, float aimAssistModifier = 0.0f, Item[] ignoredItems = null)
{
if (Submarine != null)
{
simPosition += Submarine.SimPosition;
}
debugInteractablesInRange.Clear();
debugInteractablesAtCursor.Clear();
debugInteractablesNearCursor.Clear();
//reduce the amount of aim assist if an item has been selected
//= can't switch selection to another item without deselecting the current one first UNLESS the cursor is directly on the item
//otherwise it would be too easy to accidentally switch the selected item when rewiring items
float aimAssistAmount = SelectedConstruction == null ? 100.0f * aimAssistModifier : 1.0f;
Vector2 displayPosition = ConvertUnits.ToDisplayUnits(simPosition);
//use the list of visible entities if it exists
var entityList = Submarine.VisibleEntities ?? Item.ItemList;
Item closestItem = null;
float closestItemDistance = aimAssistAmount;
foreach (MapEntity entity in entityList)
{
if (!(entity is Item item))
{
continue;
}
if (item.body != null && !item.body.Enabled) continue;
if (item.ParentInventory != null) continue;
if (ignoredItems != null && ignoredItems.Contains(item)) continue;
float distanceToItem = float.PositiveInfinity;
if (item.IsInsideTrigger(displayPosition, out Rectangle transformedTrigger))
{
debugInteractablesAtCursor.Add(item);
//distance is between 0-1 when the cursor is directly on the item
distanceToItem =
Math.Abs(transformedTrigger.Center.X - displayPosition.X) / transformedTrigger.Width +
Math.Abs((transformedTrigger.Y - transformedTrigger.Height / 2.0f) - displayPosition.Y) / transformedTrigger.Height;
//modify the distance based on the size of the trigger (preferring smaller items)
distanceToItem *= MathHelper.Lerp(0.05f, 2.0f, (transformedTrigger.Width + transformedTrigger.Height) / 250.0f);
}
else
{
Rectangle itemDisplayRect = new Rectangle(item.InteractionRect.X, item.InteractionRect.Y - item.InteractionRect.Height, item.InteractionRect.Width, item.InteractionRect.Height);
if (itemDisplayRect.Contains(displayPosition))
{
debugInteractablesAtCursor.Add(item);
//distance is between 0-1 when the cursor is directly on the item
distanceToItem =
Math.Abs(itemDisplayRect.Center.X - displayPosition.X) / itemDisplayRect.Width +
Math.Abs(itemDisplayRect.Center.Y - displayPosition.Y) / itemDisplayRect.Height;
//modify the distance based on the size of the item (preferring smaller ones)
distanceToItem *= MathHelper.Lerp(0.05f, 2.0f, (itemDisplayRect.Width + itemDisplayRect.Height) / 250.0f);
}
else
{
if (closestItemDistance < 2.0f) { continue; }
//get the point on the itemDisplayRect which is closest to the cursor
Vector2 rectIntersectionPoint = new Vector2(
MathHelper.Clamp(displayPosition.X, itemDisplayRect.X, itemDisplayRect.Right),
MathHelper.Clamp(displayPosition.Y, itemDisplayRect.Y, itemDisplayRect.Bottom));
distanceToItem = 2.0f + Vector2.Distance(rectIntersectionPoint, displayPosition);
}
}
if (distanceToItem > closestItemDistance) { continue; }
if (!CanInteractWith(item)) { continue; }
debugInteractablesNearCursor.Add(new Pair<Item, float>(item, 1.0f - distanceToItem / (100.0f * aimAssistModifier)));
closestItem = item;
closestItemDistance = distanceToItem;
}
return closestItem;
}
private Character FindCharacterAtPosition(Vector2 mouseSimPos, float maxDist = 150.0f)
{
Character closestCharacter = null;
float closestDist = 0.0f;
maxDist = ConvertUnits.ToSimUnits(maxDist);
foreach (Character c in CharacterList)
{
if (!CanInteractWith(c)) continue;
float dist = Vector2.DistanceSquared(mouseSimPos, c.SimPosition);
if (dist < maxDist * maxDist && (closestCharacter == null || dist < closestDist))
{
closestCharacter = c;
closestDist = dist;
}
/*FarseerPhysics.Common.Transform transform;
c.AnimController.Collider.FarseerBody.GetTransform(out transform);
for (int i = 0; i < c.AnimController.Collider.FarseerBody.FixtureList.Count; i++)
{
if (c.AnimController.Collider.FarseerBody.FixtureList[i].Shape.TestPoint(ref transform, ref mouseSimPos))
{
Console.WriteLine("Hit: " + i);
closestCharacter = c;
}
}*/
}
return closestCharacter;
}
partial void UpdateProjSpecific(float deltaTime, Camera cam) partial void UpdateProjSpecific(float deltaTime, Camera cam)
{ {
if (!IsDead && !IsUnconscious)
{
if (soundTimer > 0)
{
soundTimer -= deltaTime;
}
else if (AIController != null)
{
switch (AIController.State)
{
case AIController.AIState.Attack:
PlaySound(CharacterSound.SoundType.Attack);
break;
default:
PlaySound(CharacterSound.SoundType.Idle);
break;
}
}
}
if (info != null || Vitality < MaxVitality * 0.98f) if (info != null || Vitality < MaxVitality * 0.98f)
{ {
hudInfoTimer -= deltaTime; hudInfoTimer -= deltaTime;
@@ -421,7 +580,7 @@ namespace Barotrauma
float cursorDist = Vector2.Distance(WorldPosition, cam.ScreenToWorld(PlayerInput.MousePosition)); float cursorDist = Vector2.Distance(WorldPosition, cam.ScreenToWorld(PlayerInput.MousePosition));
float hudInfoAlpha = MathHelper.Clamp(1.0f - (cursorDist - (hoverRange - fadeOutRange)) / fadeOutRange, 0.2f, 1.0f); float hudInfoAlpha = MathHelper.Clamp(1.0f - (cursorDist - (hoverRange - fadeOutRange)) / fadeOutRange, 0.2f, 1.0f);
if (hudInfoVisible && info != null && if (!GUI.DisableCharacterNames && hudInfoVisible && info != null &&
(controlled == null || this != controlled.focusedCharacter)) (controlled == null || this != controlled.focusedCharacter))
{ {
string name = Info.DisplayName; string name = Info.DisplayName;
@@ -440,7 +599,7 @@ namespace Barotrauma
Color nameColor = Color.White; Color nameColor = Color.White;
if (Controlled != null && TeamID != Controlled.TeamID) if (Controlled != null && TeamID != Controlled.TeamID)
{ {
nameColor = Color.Red; nameColor = TeamID == TeamType.FriendlyNPC ? Color.SkyBlue : Color.Red;
} }
GUI.Font.DrawString(spriteBatch, 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, 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, name, namePos, nameColor * hudInfoAlpha, 0.0f, Vector2.Zero, 1.0f / cam.Zoom, SpriteEffects.None, 0.0f); GUI.Font.DrawString(spriteBatch, name, namePos, nameColor * hudInfoAlpha, 0.0f, Vector2.Zero, 1.0f / cam.Zoom, SpriteEffects.None, 0.0f);
@@ -471,8 +630,7 @@ namespace Barotrauma
{ {
if (controlled != this) return null; if (controlled != this) return null;
HUDProgressBar progressBar = null; if (!hudProgressBars.TryGetValue(linkedObject, out HUDProgressBar progressBar))
if (!hudProgressBars.TryGetValue(linkedObject, out progressBar))
{ {
progressBar = new HUDProgressBar(worldPosition, Submarine, emptyColor, fullColor); progressBar = new HUDProgressBar(worldPosition, Submarine, emptyColor, fullColor);
hudProgressBars.Add(linkedObject, progressBar); hudProgressBars.Add(linkedObject, progressBar);
@@ -485,15 +643,21 @@ namespace Barotrauma
return progressBar; return progressBar;
} }
private SoundChannel soundChannel;
public void PlaySound(CharacterSound.SoundType soundType) public void PlaySound(CharacterSound.SoundType soundType)
{ {
if (sounds == null || sounds.Count == 0) return; if (sounds == null || sounds.Count == 0) { return; }
if (soundChannel != null && soundChannel.IsPlaying) { return; }
var matchingSounds = sounds.FindAll(s => s.Type == soundType); var matchingSounds = sounds.Where(s =>
if (matchingSounds.Count == 0) return; s.Type == soundType &&
(s.Gender == Gender.None || (info != null && info.Gender == s.Gender)));
if (!matchingSounds.Any()) { return; }
var selectedSound = matchingSounds[Rand.Int(matchingSounds.Count)]; var matchingSoundsList = matchingSounds.ToList();
SoundPlayer.PlaySound(selectedSound.Sound, selectedSound.Volume, selectedSound.Range, AnimController.WorldPosition, CurrentHull); var selectedSound = matchingSoundsList[Rand.Int(matchingSoundsList.Count)];
soundChannel = SoundPlayer.PlaySound(selectedSound.Sound, selectedSound.Volume, selectedSound.Range, AnimController.WorldPosition, CurrentHull);
soundTimer = soundInterval;
} }
partial void ImplodeFX() partial void ImplodeFX()
@@ -60,7 +60,7 @@ namespace Barotrauma
var item = character.Inventory.Items[i]; var item = character.Inventory.Items[i];
if (item == null || character.Inventory.SlotTypes[i] == InvSlotType.Any) continue; if (item == null || character.Inventory.SlotTypes[i] == InvSlotType.Any) continue;
foreach (ItemComponent ic in item.components) foreach (ItemComponent ic in item.Components)
{ {
if (ic.DrawHudWhenEquipped) ic.AddToGUIUpdateList(); if (ic.DrawHudWhenEquipped) ic.AddToGUIUpdateList();
} }
@@ -94,7 +94,7 @@ namespace Barotrauma
var item = character.Inventory.Items[i]; var item = character.Inventory.Items[i];
if (item == null || character.Inventory.SlotTypes[i] == InvSlotType.Any) continue; if (item == null || character.Inventory.SlotTypes[i] == InvSlotType.Any) continue;
foreach (ItemComponent ic in item.components) foreach (ItemComponent ic in item.Components)
{ {
if (ic.DrawHudWhenEquipped) ic.UpdateHUD(character, deltaTime, cam); if (ic.DrawHudWhenEquipped) ic.UpdateHUD(character, deltaTime, cam);
} }
@@ -188,8 +188,14 @@ namespace Barotrauma
} }
Vector2 textPos = startPos; Vector2 textPos = startPos;
textPos -= new Vector2(GUI.Font.MeasureString(focusName).X / 2, 20); textPos -= new Vector2(GUI.Font.MeasureString(focusName).X / 2, 20);
Color nameColor = Color.White;
if (character.TeamID != character.FocusedCharacter.TeamID)
{
nameColor = character.FocusedCharacter.TeamID == Character.TeamType.FriendlyNPC ? Color.SkyBlue : Color.Red;
}
GUI.DrawString(spriteBatch, textPos, focusName, Color.White, Color.Black * 0.7f, 2); GUI.DrawString(spriteBatch, textPos, focusName, nameColor, Color.Black * 0.7f, 2);
textPos.Y += 20; textPos.Y += 20;
if (character.FocusedCharacter.CanInventoryBeAccessed) if (character.FocusedCharacter.CanInventoryBeAccessed)
{ {
@@ -237,30 +243,35 @@ namespace Barotrauma
scale: scale); scale: scale);
} }
var hudTexts = focusedItem.GetHUDTexts(character); if (!GUI.DisableItemHighlights)
int dir = Math.Sign(focusedItem.WorldPosition.X - character.WorldPosition.X);
Vector2 startPos = cam.WorldToScreen(focusedItem.DrawPosition);
startPos.Y -= (hudTexts.Count + 1) * 20;
if (focusedItem.Sprite != null)
{ {
startPos.X += (int)(circleSize * 0.4f * dir); var hudTexts = focusedItem.GetHUDTexts(character);
startPos.Y -= (int)(circleSize * 0.4f);
int dir = Math.Sign(focusedItem.WorldPosition.X - character.WorldPosition.X);
Vector2 startPos = cam.WorldToScreen(focusedItem.DrawPosition);
startPos.Y -= (hudTexts.Count + 1) * 20;
if (focusedItem.Sprite != null)
{
startPos.X += (int)(circleSize * 0.4f * dir);
startPos.Y -= (int)(circleSize * 0.4f);
}
Vector2 textPos = startPos;
if (dir == -1) textPos.X -= (int)GUI.Font.MeasureString(focusedItem.Name).X;
float alpha = MathHelper.Clamp((focusedItemOverlayTimer - ItemOverlayDelay) * 2.0f, 0.0f, 1.0f);
GUI.DrawString(spriteBatch, textPos, focusedItem.Name, Color.White * alpha, Color.Black * alpha * 0.7f, 2);
textPos.Y += 20.0f;
foreach (ColoredText coloredText in hudTexts)
{
if (dir == -1) textPos.X = (int)(startPos.X - GUI.SmallFont.MeasureString(coloredText.Text).X);
GUI.DrawString(spriteBatch, textPos, coloredText.Text, coloredText.Color * alpha, Color.Black * alpha * 0.7f, 2, GUI.SmallFont);
textPos.Y += 20;
}
} }
Vector2 textPos = startPos;
if (dir == -1) textPos.X -= (int)GUI.Font.MeasureString(focusedItem.Name).X;
float alpha = MathHelper.Clamp((focusedItemOverlayTimer - ItemOverlayDelay) * 2.0f, 0.0f, 1.0f);
GUI.DrawString(spriteBatch, textPos, focusedItem.Name, Color.White * alpha, Color.Black * alpha * 0.7f, 2);
textPos.Y += 20.0f;
foreach (ColoredText coloredText in hudTexts)
{
if (dir == -1) textPos.X = (int)(startPos.X - GUI.SmallFont.MeasureString(coloredText.Text).X);
GUI.DrawString(spriteBatch, textPos, coloredText.Text, coloredText.Color * alpha, Color.Black * alpha * 0.7f, 2, GUI.SmallFont);
textPos.Y += 20;
}
} }
foreach (HUDProgressBar progressBar in character.HUDProgressBars.Values) foreach (HUDProgressBar progressBar in character.HUDProgressBars.Values)
@@ -282,7 +293,7 @@ namespace Barotrauma
var item = character.Inventory.Items[i]; var item = character.Inventory.Items[i];
if (item == null || character.Inventory.SlotTypes[i] == InvSlotType.Any) continue; if (item == null || character.Inventory.SlotTypes[i] == InvSlotType.Any) continue;
foreach (ItemComponent ic in item.components) foreach (ItemComponent ic in item.Components)
{ {
if (ic.DrawHudWhenEquipped) ic.DrawHUD(spriteBatch, character); if (ic.DrawHudWhenEquipped) ic.DrawHUD(spriteBatch, character);
} }
@@ -397,9 +397,10 @@ namespace Barotrauma
partial void UpdateOxygenProjSpecific(float prevOxygen) partial void UpdateOxygenProjSpecific(float prevOxygen)
{ {
if (prevOxygen > 0.0f && OxygenAmount <= 0.0f && Character.Controlled == Character) if (prevOxygen > 0.0f && OxygenAmount <= 0.0f &&
Character.Controlled == Character)
{ {
SoundPlayer.PlaySound("drown"); SoundPlayer.PlaySound(Character.Info != null && Character.Info.Gender == Gender.Female ? "drownfemale" : "drownmale");
} }
} }
@@ -1110,7 +1111,7 @@ namespace Barotrauma
return medicalItems.Distinct().ToList(); return medicalItems.Distinct().ToList();
} }
private void UpdateLimbIndicators(float deltaTime, Rectangle drawArea) private void UpdateLimbIndicators(float deltaTime, Rectangle drawArea)
{ {
limbIndicatorOverlayAnimState += deltaTime * 8.0f; limbIndicatorOverlayAnimState += deltaTime * 8.0f;
@@ -1261,8 +1262,8 @@ namespace Barotrauma
private void DrawLimbAfflictionIcon(SpriteBatch spriteBatch, Affliction affliction, GUIComponentStyle slotStyle, float iconScale, ref Vector2 iconPos) private void DrawLimbAfflictionIcon(SpriteBatch spriteBatch, Affliction affliction, GUIComponentStyle slotStyle, float iconScale, ref Vector2 iconPos)
{ {
Vector2 iconSize = (affliction.Prefab.Icon.size * iconScale);
if (affliction.Strength < affliction.Prefab.ShowIconThreshold) return; if (affliction.Strength < affliction.Prefab.ShowIconThreshold) return;
Vector2 iconSize = (affliction.Prefab.Icon.size * iconScale);
//afflictions that have a strength of less than 10 are faded out slightly //afflictions that have a strength of less than 10 are faded out slightly
float alpha = MathHelper.Lerp(0.3f, 1.0f, float alpha = MathHelper.Lerp(0.3f, 1.0f,
@@ -1293,10 +1294,10 @@ namespace Barotrauma
byte afflictionCount = inc.ReadByte(); byte afflictionCount = inc.ReadByte();
for (int i = 0; i < afflictionCount; i++) for (int i = 0; i < afflictionCount; i++)
{ {
int afflictionPrefabIndex = inc.ReadRangedInteger(0, AfflictionPrefab.List.Count - 1); AfflictionPrefab afflictionPrefab = AfflictionPrefab.List[inc.ReadRangedInteger(0, AfflictionPrefab.List.Count - 1)];
float afflictionStrength = inc.ReadSingle(); float afflictionStrength = inc.ReadRangedSingle(0.0f, afflictionPrefab.MaxStrength, 8);
newAfflictions.Add(new Pair<AfflictionPrefab, float>(AfflictionPrefab.List[afflictionPrefabIndex], afflictionStrength)); newAfflictions.Add(new Pair<AfflictionPrefab, float>(afflictionPrefab, afflictionStrength));
} }
foreach (Affliction affliction in afflictions) foreach (Affliction affliction in afflictions)
@@ -1327,10 +1328,10 @@ namespace Barotrauma
for (int i = 0; i < limbAfflictionCount; i++) for (int i = 0; i < limbAfflictionCount; i++)
{ {
int limbIndex = inc.ReadRangedInteger(0, limbHealths.Count - 1); int limbIndex = inc.ReadRangedInteger(0, limbHealths.Count - 1);
int afflictionPrefabIndex = inc.ReadRangedInteger(0, AfflictionPrefab.List.Count - 1); AfflictionPrefab afflictionPrefab = AfflictionPrefab.List[inc.ReadRangedInteger(0, AfflictionPrefab.List.Count - 1)];
float afflictionStrength = inc.ReadSingle(); float afflictionStrength = inc.ReadRangedSingle(0.0f, afflictionPrefab.MaxStrength, 8);
newLimbAfflictions.Add(new Triplet<LimbHealth, AfflictionPrefab, float>(limbHealths[limbIndex], AfflictionPrefab.List[afflictionPrefabIndex], afflictionStrength)); newLimbAfflictions.Add(new Triplet<LimbHealth, AfflictionPrefab, float>(limbHealths[limbIndex], afflictionPrefab, afflictionStrength));
} }
foreach (LimbHealth limbHealth in limbHealths) foreach (LimbHealth limbHealth in limbHealths)
@@ -1,9 +1,10 @@
using Barotrauma.Extensions;
using Lidgren.Network;
using System; using System;
using System.Linq; using System.Linq;
using System.Collections.Generic; using System.Collections.Generic;
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Graphics;
using Barotrauma.Extensions;
namespace Barotrauma namespace Barotrauma
{ {
@@ -219,5 +220,55 @@ namespace Barotrauma
} }
attachment.Sprite.Draw(spriteBatch, drawPos, Color.White, origin, rotate: 0, scale: scale, depth: depth, spriteEffect: spriteEffects); attachment.Sprite.Draw(spriteBatch, drawPos, Color.White, origin, rotate: 0, scale: scale, depth: depth, spriteEffect: spriteEffects);
} }
public static CharacterInfo ClientRead(string configPath, NetBuffer inc)
{
ushort infoID = inc.ReadUInt16();
string newName = inc.ReadString();
int gender = inc.ReadByte();
int race = inc.ReadByte();
int headSpriteID = inc.ReadByte();
int hairIndex = inc.ReadByte();
int beardIndex = inc.ReadByte();
int moustacheIndex = inc.ReadByte();
int faceAttachmentIndex = inc.ReadByte();
string ragdollFile = inc.ReadString();
string jobIdentifier = inc.ReadString();
JobPrefab jobPrefab = null;
Dictionary<string, float> skillLevels = new Dictionary<string, float>();
if (!string.IsNullOrEmpty(jobIdentifier))
{
jobPrefab = JobPrefab.List.Find(jp => jp.Identifier == jobIdentifier);
for (int i = 0; i < jobPrefab.Skills.Count; i++)
{
float skillLevel = inc.ReadSingle();
skillLevels.Add(jobPrefab.Skills[i].Identifier, skillLevel);
}
}
// TODO: animations
CharacterInfo ch = new CharacterInfo(configPath, newName, jobPrefab, ragdollFile)
{
ID = infoID,
};
ch.RecreateHead(headSpriteID,(Race)race, (Gender)gender, hairIndex, beardIndex, moustacheIndex, faceAttachmentIndex);
System.Diagnostics.Debug.Assert(skillLevels.Count == ch.Job.Skills.Count);
if (ch.Job != null)
{
foreach (KeyValuePair<string, float> skill in skillLevels)
{
Skill matchingSkill = ch.Job.Skills.Find(s => s.Identifier == skill.Key);
if (matchingSkill == null)
{
DebugConsole.ThrowError("Skill \"" + skill.Key + "\" not found in character \"" + newName + "\"");
continue;
}
matchingSkill.Level = skill.Value;
}
}
return ch;
}
} }
} }
@@ -9,10 +9,88 @@ namespace Barotrauma
{ {
partial class Character partial class Character
{ {
partial void UpdateNetInput()
{
if (GameMain.Client != null)
{
if (this != Controlled)
{
//freeze AI characters if more than 1 seconds have passed since last update from the server
if (lastRecvPositionUpdateTime < NetTime.Now - 1.0f)
{
AnimController.Frozen = true;
memState.Clear();
//hide after 2 seconds
if (lastRecvPositionUpdateTime < NetTime.Now - 2.0f)
{
Enabled = false;
return;
}
}
}
else
{
var posInfo = new CharacterStateInfo(
SimPosition,
AnimController.Collider.Rotation,
LastNetworkUpdateID,
AnimController.TargetDir,
SelectedCharacter == null ? (Entity)SelectedConstruction : (Entity)SelectedCharacter,
AnimController.Anim);
memLocalState.Add(posInfo);
InputNetFlags newInput = InputNetFlags.None;
if (IsKeyDown(InputType.Left)) newInput |= InputNetFlags.Left;
if (IsKeyDown(InputType.Right)) newInput |= InputNetFlags.Right;
if (IsKeyDown(InputType.Up)) newInput |= InputNetFlags.Up;
if (IsKeyDown(InputType.Down)) newInput |= InputNetFlags.Down;
if (IsKeyDown(InputType.Run)) newInput |= InputNetFlags.Run;
if (IsKeyDown(InputType.Crouch)) newInput |= InputNetFlags.Crouch;
if (IsKeyHit(InputType.Select)) newInput |= InputNetFlags.Select; //TODO: clean up the way this input is registered
if (IsKeyHit(InputType.Health)) newInput |= InputNetFlags.Health;
if (IsKeyHit(InputType.Grab)) newInput |= InputNetFlags.Grab;
if (IsKeyDown(InputType.Use)) newInput |= InputNetFlags.Use;
if (IsKeyDown(InputType.Aim)) newInput |= InputNetFlags.Aim;
if (IsKeyDown(InputType.Attack)) newInput |= InputNetFlags.Attack;
if (IsKeyDown(InputType.Ragdoll)) newInput |= InputNetFlags.Ragdoll;
if (AnimController.TargetDir == Direction.Left) newInput |= InputNetFlags.FacingLeft;
Vector2 relativeCursorPos = cursorPosition - AimRefPosition;
relativeCursorPos.Normalize();
UInt16 intAngle = (UInt16)(65535.0 * Math.Atan2(relativeCursorPos.Y, relativeCursorPos.X) / (2.0 * Math.PI));
NetInputMem newMem = new NetInputMem
{
states = newInput,
intAim = intAngle
};
if (focusedItem != null && (!newMem.states.HasFlag(InputNetFlags.Grab) && !newMem.states.HasFlag(InputNetFlags.Health)))
{
newMem.interact = focusedItem.ID;
}
else if (focusedCharacter != null)
{
newMem.interact = focusedCharacter.ID;
}
memInput.Insert(0, newMem);
LastNetworkUpdateID++;
if (memInput.Count > 60)
{
memInput.RemoveRange(60, memInput.Count - 60);
}
}
}
else //this == Character.Controlled && GameMain.Client == null
{
AnimController.Frozen = false;
}
}
public virtual void ClientWrite(NetBuffer msg, object[] extraData = null) public virtual void ClientWrite(NetBuffer msg, object[] extraData = null)
{ {
if (GameMain.Server != null) return;
if (extraData != null) if (extraData != null)
{ {
switch ((NetEntityEvent.Type)extraData[0]) switch ((NetEntityEvent.Type)extraData[0])
@@ -63,8 +141,6 @@ namespace Barotrauma
public virtual void ClientRead(ServerNetObject type, NetBuffer msg, float sendingTime) public virtual void ClientRead(ServerNetObject type, NetBuffer msg, float sendingTime)
{ {
if (GameMain.Server != null) return;
switch (type) switch (type)
{ {
case ServerNetObject.ENTITY_POSITION: case ServerNetObject.ENTITY_POSITION:
@@ -97,13 +173,9 @@ namespace Barotrauma
keys[(int)InputType.Crouch].SetState(false, crouching); keys[(int)InputType.Crouch].SetState(false, crouching);
} }
bool hasAttackLimb = msg.ReadBoolean(); bool attackInput = msg.ReadBoolean();
if (hasAttackLimb) keys[(int)InputType.Attack].Held = attackInput;
{ keys[(int)InputType.Attack].SetState(false, attackInput);
bool attackInput = msg.ReadBoolean();
keys[(int)InputType.Attack].Held = attackInput;
keys[(int)InputType.Attack].SetState(false, attackInput);
}
if (aimInput) if (aimInput)
{ {
@@ -139,28 +211,44 @@ namespace Barotrauma
Vector2 pos = new Vector2( Vector2 pos = new Vector2(
msg.ReadFloat(), msg.ReadFloat(),
msg.ReadFloat()); msg.ReadFloat());
float MaxVel = NetConfig.MaxPhysicsBodyVelocity;
Vector2 linearVelocity = new Vector2(
msg.ReadRangedSingle(-MaxVel, MaxVel, 12),
msg.ReadRangedSingle(-MaxVel, MaxVel, 12));
float rotation = msg.ReadFloat(); bool fixedRotation = msg.ReadBoolean();
float rotation = AnimController.Collider.Rotation;
float angularVelocity = AnimController.Collider.AngularVelocity;
if (!fixedRotation)
{
rotation = msg.ReadFloat();
float MaxAngularVel = NetConfig.MaxPhysicsBodyAngularVelocity;
angularVelocity = msg.ReadRangedSingle(-MaxAngularVel, MaxAngularVel, 8);
}
ReadStatus(msg); bool readStatus = msg.ReadBoolean();
if (readStatus)
{
ReadStatus(msg);
}
msg.ReadPadBits(); msg.ReadPadBits();
int index = 0; int index = 0;
if (GameMain.NetworkMember.Character == this && AllowInput) if (GameMain.Client.Character == this && AllowInput)
{ {
var posInfo = new CharacterStateInfo(pos, rotation, networkUpdateID, facingRight ? Direction.Right : Direction.Left, selectedEntity, animation); var posInfo = new CharacterStateInfo(pos, rotation, networkUpdateID, facingRight ? Direction.Right : Direction.Left, selectedEntity, animation);
while (index < memState.Count && NetIdUtils.IdMoreRecent(posInfo.ID, memState[index].ID)) while (index < memState.Count && NetIdUtils.IdMoreRecent(posInfo.ID, memState[index].ID))
index++; index++;
memState.Insert(index, posInfo); memState.Insert(index, posInfo);
} }
else else
{ {
var posInfo = new CharacterStateInfo(pos, rotation, sendingTime, facingRight ? Direction.Right : Direction.Left, selectedEntity, animation); var posInfo = new CharacterStateInfo(pos, rotation, linearVelocity, angularVelocity, sendingTime, facingRight ? Direction.Right : Direction.Left, selectedEntity, animation);
while (index < memState.Count && posInfo.Timestamp > memState[index].Timestamp) while (index < memState.Count && posInfo.Timestamp > memState[index].Timestamp)
index++; index++;
memState.Insert(index, posInfo); memState.Insert(index, posInfo);
} }
@@ -198,10 +286,13 @@ namespace Barotrauma
GameMain.Client.Character = this; GameMain.Client.Character = this;
GameMain.LightManager.LosEnabled = true; GameMain.LightManager.LosEnabled = true;
} }
else if (controlled == this) else
{ {
Controlled = null; if (controlled == this)
IsRemotePlayer = ownerID > 0; {
Controlled = null;
IsRemotePlayer = ownerID > 0;
}
} }
break; break;
case 2: case 2:
@@ -221,45 +312,59 @@ namespace Barotrauma
break; break;
} }
} }
public static Character ReadSpawnData(NetBuffer inc, bool spawn = true) public static Character ReadSpawnData(NetBuffer inc, bool spawn = true)
{ {
DebugConsole.NewMessage("READING CHARACTER SPAWN DATA", Color.Cyan); DebugConsole.NewMessage("READING CHARACTER SPAWN DATA", Color.Cyan);
if (GameMain.Server != null) return null; if (GameMain.Client == null) return null;
bool noInfo = inc.ReadBoolean(); bool noInfo = inc.ReadBoolean();
ushort id = inc.ReadUInt16(); ushort id = inc.ReadUInt16();
string configPath = inc.ReadString(); string speciesName = inc.ReadString();
string seed = inc.ReadString(); string seed = inc.ReadString();
Vector2 position = new Vector2(inc.ReadFloat(), inc.ReadFloat()); Vector2 position = new Vector2(inc.ReadFloat(), inc.ReadFloat());
bool enabled = inc.ReadBoolean(); bool enabled = inc.ReadBoolean();
DebugConsole.Log("Received spawn data for " + configPath); DebugConsole.Log("Received spawn data for " + speciesName);
string configPath = GetConfigFile(speciesName);
if (string.IsNullOrEmpty(configPath))
{
throw new Exception("Error in character spawn data - could not find a config file for the character \"" + configPath + "\"!");
}
Character character = null; Character character = null;
if (noInfo) if (noInfo)
{ {
if (!spawn) return null; if (!spawn) return null;
character = Character.Create(configPath, position, seed, null, true); character = Create(configPath, position, seed, null, true);
character.ID = id; character.ID = id;
} }
else else
{ {
bool hasOwner = inc.ReadBoolean(); bool hasOwner = inc.ReadBoolean();
int ownerId = hasOwner ? inc.ReadByte() : -1; int ownerId = hasOwner ? inc.ReadByte() : -1;
byte teamID = inc.ReadByte(); byte teamID = inc.ReadByte();
bool hasAi = inc.ReadBoolean(); bool hasAi = inc.ReadBoolean();
string infoSpeciesName = inc.ReadString();
if (!spawn) return null; if (!spawn) return null;
CharacterInfo info = CharacterInfo.ClientRead(configPath, inc); string infoConfigPath = GetConfigFile(infoSpeciesName);
if (string.IsNullOrEmpty(infoConfigPath))
{
throw new Exception("Error in character spawn data - could not find a config file for the character info \"" + configPath + "\"!");
}
CharacterInfo info = CharacterInfo.ClientRead(infoConfigPath, inc);
character = Create(configPath, position, seed, info, GameMain.Client.ID != ownerId, hasAi); character = Create(configPath, position, seed, info, GameMain.Client.ID != ownerId, hasAi);
character.ID = id; character.ID = id;
character.TeamID = teamID; character.TeamID = (TeamType)teamID;
if (configPath == HumanConfigFile) if (configPath == HumanConfigFile)
{ {
@@ -267,7 +372,7 @@ namespace Barotrauma
GameMain.GameSession.CrewManager.RemoveCharacterInfo(duplicateCharacterInfo); GameMain.GameSession.CrewManager.RemoveCharacterInfo(duplicateCharacterInfo);
GameMain.GameSession.CrewManager.AddCharacter(character); GameMain.GameSession.CrewManager.AddCharacter(character);
} }
if (GameMain.Client.ID == ownerId) if (GameMain.Client.ID == ownerId)
{ {
GameMain.Client.HasSpawned = true; GameMain.Client.HasSpawned = true;
@@ -286,7 +391,7 @@ namespace Barotrauma
return character; return character;
} }
private void ReadStatus(NetBuffer msg) private void ReadStatus(NetBuffer msg)
{ {
bool isDead = msg.ReadBoolean(); bool isDead = msg.ReadBoolean();
@@ -324,9 +429,6 @@ namespace Barotrauma
if (IsDead) Revive(); if (IsDead) Revive();
CharacterHealth.ClientRead(msg); CharacterHealth.ClientRead(msg);
bool ragdolled = msg.ReadBoolean();
IsRagdolled = ragdolled;
} }
} }
} }
@@ -8,7 +8,7 @@ namespace Barotrauma
{ {
public enum SoundType public enum SoundType
{ {
Idle, Attack, Die Idle, Attack, Die, Damage
} }
private readonly RoundSound roundSound; private readonly RoundSound roundSound;
@@ -28,10 +28,13 @@ namespace Barotrauma
get { return roundSound.Sound; } get { return roundSound.Sound; }
} }
public readonly Gender Gender;
public CharacterSound(XElement element) public CharacterSound(XElement element)
{ {
roundSound = Submarine.LoadRoundSound(element); roundSound = Submarine.LoadRoundSound(element);
Enum.TryParse<SoundType>(element.GetAttributeString("state", "Idle"), true, out Type); Enum.TryParse(element.GetAttributeString("state", "Idle"), true, out Type);
Enum.TryParse(element.GetAttributeString("gender", "None"), true, out Gender);
} }
} }
} }
@@ -0,0 +1,34 @@
using Microsoft.Xna.Framework;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml.Linq;
namespace Barotrauma
{
partial class AfflictionHusk : Affliction
{
partial void UpdateMessages(float prevStrength, Character character)
{
if (Strength < Prefab.MaxStrength * 0.5f)
{
if (prevStrength % 10.0f > 0.05f && Strength % 10.0f < 0.05f)
{
GUI.AddMessage(TextManager.Get("HuskDormant"), Color.Red);
}
}
else if (Strength < Prefab.MaxStrength)
{
if (state == InfectionState.Dormant && Character.Controlled == character)
{
GUI.AddMessage(TextManager.Get("HuskCantSpeak"), Color.Red);
}
}
else if (state != InfectionState.Active && Character.Controlled == character)
{
GUI.AddMessage(TextManager.Get("HuskActivate").Replace("[Attack]", GameMain.Config.KeyBind(InputType.Attack).ToString()),
Color.Red);
}
}
}
}
@@ -0,0 +1,22 @@
namespace Barotrauma
{
partial class CharacterHealth
{
partial void UpdateLimbAfflictionOverlays()
{
foreach (Limb limb in Character.AnimController.Limbs)
{
limb.BurnOverlayStrength = 0.0f;
limb.DamageOverlayStrength = 0.0f;
if (limbHealths[limb.HealthIndex].Afflictions.Count == 0) continue;
foreach (Affliction a in limbHealths[limb.HealthIndex].Afflictions)
{
limb.BurnOverlayStrength += a.Strength / a.Prefab.MaxStrength * a.Prefab.BurnOverlayAlpha;
limb.DamageOverlayStrength += a.Strength / a.Prefab.MaxStrength * a.Prefab.DamageOverlayAlpha;
}
limb.BurnOverlayStrength /= limbHealths[limb.HealthIndex].Afflictions.Count;
limb.DamageOverlayStrength /= limbHealths[limb.HealthIndex].Afflictions.Count;
}
}
}
}
@@ -0,0 +1,12 @@
namespace Barotrauma
{
partial class DamageModifier
{
[Serialize("", false)]
public string DamageSound
{
get;
private set;
}
}
}
@@ -110,11 +110,28 @@ namespace Barotrauma
public Sprite Sprite { get; protected set; } public Sprite Sprite { get; protected set; }
public DeformableSprite DeformSprite { get; protected set; } public DeformableSprite DeformSprite { get; protected set; }
public Sprite ActiveSprite => DeformSprite != null ? DeformSprite.Sprite : Sprite; public Sprite ActiveSprite
{
get
{
// TODO: should we optimize this? No need to check all the conditionals each time the property is accessed.
var conditionalSprite = ConditionalSprites.FirstOrDefault(c => c.IsActive);
if (conditionalSprite != null)
{
return conditionalSprite;
}
else
{
return DeformSprite != null ? DeformSprite.Sprite : Sprite;
}
}
}
public float TextureScale => limbParams.Ragdoll.TextureScale; public float TextureScale => limbParams.Ragdoll.TextureScale;
public Sprite DamagedSprite { get; set; } public Sprite DamagedSprite { get; private set; }
public List<ConditionalSprite> ConditionalSprites { get; private set; } = new List<ConditionalSprite>();
public Color InitialLightSourceColor public Color InitialLightSourceColor
{ {
@@ -156,6 +173,9 @@ namespace Barotrauma
case "damagedsprite": case "damagedsprite":
DamagedSprite = new Sprite(subElement, "", GetSpritePath(subElement)); DamagedSprite = new Sprite(subElement, "", GetSpritePath(subElement));
break; break;
case "conditionalsprite":
ConditionalSprites.Add(new ConditionalSprite(subElement, character, file: GetSpritePath(subElement)));
break;
case "deformablesprite": case "deformablesprite":
DeformSprite = new DeformableSprite(subElement, filePath: GetSpritePath(subElement)); DeformSprite = new DeformableSprite(subElement, filePath: GetSpritePath(subElement));
foreach (XElement animationElement in subElement.Elements()) foreach (XElement animationElement in subElement.Elements())
@@ -241,28 +261,28 @@ namespace Barotrauma
DeformSprite?.Sprite.LoadParams(limbParams.deformSpriteParams, isFlipped); DeformSprite?.Sprite.LoadParams(limbParams.deformSpriteParams, isFlipped);
} }
partial void AddDamageProjSpecific(Vector2 position, List<Affliction> afflictions, bool playSound, List<DamageModifier> appliedDamageModifiers) partial void AddDamageProjSpecific(Vector2 simPosition, List<Affliction> afflictions, bool playSound, List<DamageModifier> appliedDamageModifiers)
{ {
float bleedingDamage = afflictions.FindAll(a => a is AfflictionBleeding).Sum(a => a.GetVitalityDecrease(character.CharacterHealth)); float bleedingDamage = character.CharacterHealth.DoesBleed ? afflictions.FindAll(a => a is AfflictionBleeding).Sum(a => a.GetVitalityDecrease(character.CharacterHealth)) : 0;
float damage = afflictions.FindAll(a => a.Prefab.AfflictionType == "damage").Sum(a => a.GetVitalityDecrease(character.CharacterHealth)); float damage = afflictions.FindAll(a => a.Prefab.AfflictionType == "damage").Sum(a => a.GetVitalityDecrease(character.CharacterHealth));
float damageMultiplier = 1;
if (playSound) if (playSound)
{ {
string damageSoundType = (bleedingDamage > damage) ? "LimbSlash" : "LimbBlunt"; string damageSoundType = (bleedingDamage > damage) ? "LimbSlash" : "LimbBlunt";
foreach (DamageModifier damageModifier in appliedDamageModifiers) foreach (DamageModifier damageModifier in appliedDamageModifiers)
{ {
if (!string.IsNullOrWhiteSpace(damageModifier.DamageSound)) if (!string.IsNullOrWhiteSpace(damageModifier.DamageSound))
{ {
damageSoundType = damageModifier.DamageSound; damageSoundType = damageModifier.DamageSound;
SoundPlayer.PlayDamageSound(damageSoundType, Math.Max(damage, bleedingDamage), WorldPosition);
damageMultiplier *= damageModifier.DamageMultiplier;
break; break;
} }
} }
SoundPlayer.PlayDamageSound(damageSoundType, Math.Max(damage, bleedingDamage), position);
} }
float damageParticleAmount = Math.Min(damage / 10, 1.0f); // Always spawn damage particles
float damageParticleAmount = Math.Min(damage / 10, 1.0f) * damageMultiplier;
foreach (ParticleEmitter emitter in character.DamageEmitters) foreach (ParticleEmitter emitter in character.DamageEmitters)
{ {
if (inWater && emitter.Prefab.ParticlePrefab.DrawTarget == ParticlePrefab.DrawTargetType.Air) continue; if (inWater && emitter.Prefab.ParticlePrefab.DrawTarget == ParticlePrefab.DrawTargetType.Air) continue;
@@ -271,20 +291,25 @@ namespace Barotrauma
emitter.Emit(1.0f, WorldPosition, character.CurrentHull, amountMultiplier: damageParticleAmount); emitter.Emit(1.0f, WorldPosition, character.CurrentHull, amountMultiplier: damageParticleAmount);
} }
float bloodParticleAmount = Math.Min(bleedingDamage / 5, 1.0f); if (bleedingDamage > 0)
float bloodParticleSize = MathHelper.Clamp(bleedingDamage / 5, 0.1f, 1.0f);
foreach (ParticleEmitter emitter in character.BloodEmitters)
{ {
if (inWater && emitter.Prefab.ParticlePrefab.DrawTarget == ParticlePrefab.DrawTargetType.Air) continue; float bloodParticleAmount = Math.Min(bleedingDamage / 5, 1.0f) * damageMultiplier;
if (!inWater && emitter.Prefab.ParticlePrefab.DrawTarget == ParticlePrefab.DrawTargetType.Water) continue; float bloodParticleSize = MathHelper.Clamp(bleedingDamage / 5, 0.1f, 1.0f);
emitter.Emit(1.0f, WorldPosition, character.CurrentHull, sizeMultiplier: bloodParticleSize, amountMultiplier: bloodParticleAmount); foreach (ParticleEmitter emitter in character.BloodEmitters)
{
if (inWater && emitter.Prefab.ParticlePrefab.DrawTarget == ParticlePrefab.DrawTargetType.Air) continue;
if (!inWater && emitter.Prefab.ParticlePrefab.DrawTarget == ParticlePrefab.DrawTargetType.Water) continue;
emitter.Emit(1.0f, WorldPosition, character.CurrentHull, sizeMultiplier: bloodParticleSize, amountMultiplier: bloodParticleAmount);
}
if (bloodParticleAmount > 0 && character.CurrentHull != null && !string.IsNullOrEmpty(character.BloodDecalName))
{
character.CurrentHull.AddDecal(character.BloodDecalName, WorldPosition, MathHelper.Clamp(bloodParticleSize, 0.5f, 1.0f));
}
} }
if (bloodParticleAmount > 0 && character.CurrentHull != null && !string.IsNullOrEmpty(character.BloodDecalName))
{
character.CurrentHull.AddDecal(character.BloodDecalName, WorldPosition, MathHelper.Clamp(bloodParticleSize, 0.5f, 1.0f));
}
} }
partial void UpdateProjSpecific(float deltaTime) partial void UpdateProjSpecific(float deltaTime)
@@ -353,7 +378,8 @@ namespace Barotrauma
if (!hideLimb) if (!hideLimb)
{ {
if (DeformSprite != null) var activeSprite = ActiveSprite;
if (DeformSprite != null && activeSprite == DeformSprite.Sprite)
{ {
if (Deformations != null && Deformations.Any()) if (Deformations != null && Deformations.Any())
{ {
@@ -368,7 +394,7 @@ namespace Barotrauma
} }
else else
{ {
body.Draw(spriteBatch, Sprite, color, null, Scale * TextureScale); body.Draw(spriteBatch, activeSprite, color, null, Scale * TextureScale);
} }
} }
@@ -401,11 +427,12 @@ namespace Barotrauma
{ {
float depth = ActiveSprite.Depth - 0.0000015f; float depth = ActiveSprite.Depth - 0.0000015f;
DamagedSprite.Draw(spriteBatch, // TODO: enable when the damage overlay textures have been remade.
new Vector2(body.DrawPosition.X, -body.DrawPosition.Y), //DamagedSprite.Draw(spriteBatch,
color * Math.Min(damageOverlayStrength / 50.0f, 1.0f), ActiveSprite.Origin, // new Vector2(body.DrawPosition.X, -body.DrawPosition.Y),
-body.DrawRotation, // color * Math.Min(damageOverlayStrength, 1.0f), ActiveSprite.Origin,
1.0f, spriteEffect, depth); // -body.DrawRotation,
// 1.0f, spriteEffect, depth);
} }
if (GameMain.DebugDraw) if (GameMain.DebugDraw)
@@ -415,6 +442,8 @@ namespace Barotrauma
Vector2 pos = ConvertUnits.ToDisplayUnits(pullJoint.WorldAnchorB); Vector2 pos = ConvertUnits.ToDisplayUnits(pullJoint.WorldAnchorB);
GUI.DrawRectangle(spriteBatch, new Rectangle((int)pos.X, (int)-pos.Y, 5, 5), Color.Red, true); GUI.DrawRectangle(spriteBatch, new Rectangle((int)pos.X, (int)-pos.Y, 5, 5), Color.Red, true);
} }
var bodyDrawPos = body.DrawPosition;
bodyDrawPos.Y = -bodyDrawPos.Y;
if (IsStuck) if (IsStuck)
{ {
Vector2 from = ConvertUnits.ToDisplayUnits(attachJoint.WorldAnchorA); Vector2 from = ConvertUnits.ToDisplayUnits(attachJoint.WorldAnchorA);
@@ -424,9 +453,7 @@ namespace Barotrauma
var localFront = body.GetLocalFront(MathHelper.ToRadians(limbParams.Ragdoll.SpritesheetOrientation)); var localFront = body.GetLocalFront(MathHelper.ToRadians(limbParams.Ragdoll.SpritesheetOrientation));
var front = ConvertUnits.ToDisplayUnits(body.FarseerBody.GetWorldPoint(localFront)); var front = ConvertUnits.ToDisplayUnits(body.FarseerBody.GetWorldPoint(localFront));
front.Y = -front.Y; front.Y = -front.Y;
var drawPos = body.DrawPosition; GUI.DrawLine(spriteBatch, bodyDrawPos, front, Color.Yellow, width: 2);
drawPos.Y = -drawPos.Y;
GUI.DrawLine(spriteBatch, drawPos, front, Color.Yellow, width: 2);
GUI.DrawLine(spriteBatch, from, to, Color.Red, width: 1); GUI.DrawLine(spriteBatch, from, to, Color.Red, width: 1);
GUI.DrawRectangle(spriteBatch, new Rectangle((int)from.X, (int)from.Y, 12, 12), Color.White, true); GUI.DrawRectangle(spriteBatch, new Rectangle((int)from.X, (int)from.Y, 12, 12), Color.White, true);
GUI.DrawRectangle(spriteBatch, new Rectangle((int)to.X, (int)to.Y, 12, 12), Color.White, true); GUI.DrawRectangle(spriteBatch, new Rectangle((int)to.X, (int)to.Y, 12, 12), Color.White, true);
@@ -440,7 +467,19 @@ namespace Barotrauma
//mainLimbDrawPos.Y = -mainLimbDrawPos.Y; //mainLimbDrawPos.Y = -mainLimbDrawPos.Y;
//GUI.DrawLine(spriteBatch, mainLimbDrawPos, mainLimbFront, Color.White, width: 5); //GUI.DrawLine(spriteBatch, mainLimbDrawPos, mainLimbFront, Color.White, width: 5);
//GUI.DrawRectangle(spriteBatch, new Rectangle((int)mainLimbFront.X, (int)mainLimbFront.Y, 10, 10), Color.Yellow, true); //GUI.DrawRectangle(spriteBatch, new Rectangle((int)mainLimbFront.X, (int)mainLimbFront.Y, 10, 10), Color.Yellow, true);
}
foreach (var modifier in damageModifiers)
{
//float midAngle = MathUtils.GetMidAngle(modifier.ArmorSector.X, modifier.ArmorSector.Y);
//float spritesheetOrientation = MathHelper.ToRadians(limbParams.Ragdoll.SpritesheetOrientation);
//float offset = -body.Rotation - (midAngle + spritesheetOrientation) * Dir;
float offset = GetArmorSectorRotationOffset(modifier.ArmorSector, -body.Rotation);
Vector2 forward = Vector2.Transform(-Vector2.UnitY, Matrix.CreateRotationZ(offset));
float size = ConvertUnits.ToDisplayUnits(body.GetSize().Length() / 2);
color = modifier.DamageMultiplier > 1 ? Color.Red : Color.GreenYellow;
GUI.DrawLine(spriteBatch, bodyDrawPos, bodyDrawPos + Vector2.Normalize(forward) * size, color, width: (int)Math.Round(4 / cam.Zoom));
if (Dir == -1) { offset += MathHelper.Pi; }
ShapeExtensions.DrawSector(spriteBatch, bodyDrawPos, size, GetArmorSectorSize(modifier.ArmorSector) * Dir, 40, color, offset + MathHelper.Pi, thickness: 2 / cam.Zoom);
} }
} }
} }
@@ -521,6 +560,9 @@ namespace Barotrauma
DeformSprite?.Sprite?.Remove(); DeformSprite?.Sprite?.Remove();
DeformSprite = null; DeformSprite = null;
ConditionalSprites.ForEach(s => s.Remove());
ConditionalSprites.Clear();
LightSource?.Remove(); LightSource?.Remove();
LightSource = null; LightSource = null;
@@ -7,6 +7,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Text;
using System.Xml.Linq; using System.Xml.Linq;
using System.Globalization; using System.Globalization;
@@ -14,13 +15,43 @@ namespace Barotrauma
{ {
static partial class DebugConsole static partial class DebugConsole
{ {
public partial class Command
{
/// <summary>
/// Executed when a client uses the command. If not set, the command is relayed to the server as-is.
/// </summary>
public Action<string[]> OnClientExecute;
public bool RelayToServer = true;
public void ClientExecute(string[] args)
{
if (!CheatsEnabled && IsCheat)
{
NewMessage("You need to enable cheats using the command \"enablecheats\" before you can use the command \"" + names[0] + "\".", Color.Red);
if (GameMain.Config.UseSteam)
{
NewMessage("Enabling cheats will disable Steam achievements during this play session.", Color.Red);
}
return;
}
if (OnClientExecute != null)
{
OnClientExecute(args);
}
else
{
OnExecute(args);
}
}
}
private static bool isOpen; private static bool isOpen;
public static bool IsOpen => isOpen; public static bool IsOpen => isOpen;
private static Queue<ColoredText> queuedMessages = new Queue<ColoredText>();
private static GUITextBlock activeQuestionText; private static GUITextBlock activeQuestionText;
private static GUIFrame frame; private static GUIFrame frame;
private static GUIListBox listBox; private static GUIListBox listBox;
private static GUITextBox textBox; private static GUITextBox textBox;
@@ -29,7 +60,7 @@ namespace Barotrauma
public static void Init() public static void Init()
{ {
frame = new GUIFrame(new RectTransform(new Vector2(0.5f, 0.45f), GUI.Canvas) { MinSize = new Point(400, 300), AbsoluteOffset = new Point(10, 10) }, frame = new GUIFrame(new RectTransform(new Vector2(0.5f, 0.45f), GUI.Canvas) { MinSize = new Point(400, 300), AbsoluteOffset = new Point(10, 10) },
color: new Color(0.4f, 0.4f, 0.4f, 0.8f)); color: new Color(0.4f, 0.4f, 0.4f, 0.8f));
var paddedFrame = new GUIFrame(new RectTransform(new Vector2(0.95f, 0.9f), frame.RectTransform, Anchor.Center), style: null); var paddedFrame = new GUIFrame(new RectTransform(new Vector2(0.95f, 0.9f), frame.RectTransform, Anchor.Center), style: null);
@@ -116,7 +147,7 @@ namespace Barotrauma
} }
else if (PlayerInput.KeyHit(Keys.Tab)) else if (PlayerInput.KeyHit(Keys.Tab))
{ {
textBox.Text = AutoComplete(textBox.Text); textBox.Text = AutoComplete(textBox.Text, increment: string.IsNullOrEmpty(currentAutoCompletedCommand) ? 0 : 1 );
} }
if (PlayerInput.KeyHit(Keys.Enter)) if (PlayerInput.KeyHit(Keys.Enter))
@@ -211,7 +242,7 @@ namespace Barotrauma
selectedIndex = Messages.Count; selectedIndex = Messages.Count;
} }
private static void AddHelpMessage(Command command) static partial void ShowHelpMessage(Command command)
{ {
if (listBox.Content.CountChildren > MaxMessages) if (listBox.Content.CountChildren > MaxMessages)
{ {
@@ -233,15 +264,40 @@ namespace Barotrauma
textBlock.SetTextPos(); textBlock.SetTextPos();
var nameBlock = new GUITextBlock(new RectTransform(new Point(150, textContainer.Rect.Height), textContainer.RectTransform), var nameBlock = new GUITextBlock(new RectTransform(new Point(150, textContainer.Rect.Height), textContainer.RectTransform),
command.names[0], textAlignment: Alignment.TopLeft); command.names[0], textAlignment: Alignment.TopLeft);
listBox.UpdateScrollBarSize(); listBox.UpdateScrollBarSize();
listBox.BarScroll = 1.0f; listBox.BarScroll = 1.0f;
selectedIndex = Messages.Count; selectedIndex = Messages.Count;
} }
private static void AssignOnClientExecute(string names, Action<string[]> onClientExecute)
{
Command command = commands.First(c => c.names.Intersect(names.Split('|')).Count() > 0);
command.OnClientExecute = onClientExecute;
command.RelayToServer = false;
}
private static void AssignRelayToServer(string names, bool relay)
{
commands.First(c => c.names.Intersect(names.Split('|')).Count() > 0).RelayToServer = relay;
}
private static void InitProjectSpecific() private static void InitProjectSpecific()
{ {
#if WINDOWS
commands.Add(new Command("copyitemnames", "", (string[] args) =>
{
StringBuilder sb = new StringBuilder();
foreach (MapEntityPrefab mp in MapEntityPrefab.List)
{
if (!(mp is ItemPrefab)) continue;
sb.AppendLine(mp.Name);
}
System.Windows.Clipboard.SetText(sb.ToString());
}));
#endif
commands.Add(new Command("autohull", "", (string[] args) => commands.Add(new Command("autohull", "", (string[] args) =>
{ {
if (Screen.Selected != GameMain.SubEditorScreen) return; if (Screen.Selected != GameMain.SubEditorScreen) return;
@@ -249,10 +305,10 @@ namespace Barotrauma
if (MapEntity.mapEntityList.Any(e => e is Hull || e is Gap)) if (MapEntity.mapEntityList.Any(e => e is Hull || e is Gap))
{ {
ShowQuestionPrompt("This submarine already has hulls and/or gaps. This command will delete them. Do you want to continue? Y/N", ShowQuestionPrompt("This submarine already has hulls and/or gaps. This command will delete them. Do you want to continue? Y/N",
(option) => (option) =>
{ {
ShowQuestionPrompt("The automatic hull generation may not work correctly if your submarine uses curved walls. Do you want to continue? Y/N", ShowQuestionPrompt("The automatic hull generation may not work correctly if your submarine uses curved walls. Do you want to continue? Y/N",
(option2) => (option2) =>
{ {
if (option2.ToLower() == "y") { GameMain.SubEditorScreen.AutoHull(); } if (option2.ToLower() == "y") { GameMain.SubEditorScreen.AutoHull(); }
}); });
@@ -271,8 +327,19 @@ namespace Barotrauma
if (GameMain.Client == null) if (GameMain.Client == null)
{ {
GameMain.NetworkMember = new GameClient("Name"); GameMain.Client = new GameClient("Name", args[0]);
GameMain.Client.ConnectToServer(args[0]); }
}));
commands.Add(new Command("enablecheats", "enablecheats: Enables cheat commands and disables Steam achievements during this play session.", (string[] args) =>
{
CheatsEnabled = true;
SteamAchievementManager.CheatsEnabled = true;
NewMessage("Enabled cheat commands.", Color.Red);
if (GameMain.Config.UseSteam)
{
NewMessage("Steam achievements have been disabled during this play session.", Color.Red);
} }
})); }));
@@ -323,41 +390,62 @@ namespace Barotrauma
GameMain.CharacterEditorScreen.Select(); GameMain.CharacterEditorScreen.Select();
})); }));
commands.Add(new Command("control|controlcharacter", "control [character name]: Start controlling the specified character.", (string[] args) => AssignRelayToServer("kick", false);
AssignRelayToServer("kickid", false);
AssignRelayToServer("ban", false);
AssignRelayToServer("banid", false);
AssignRelayToServer("dumpids", false);
AssignRelayToServer("findentityids", false);
AssignRelayToServer("campaigninfo", false);
AssignRelayToServer("help", false);
AssignRelayToServer("verboselogging", false);
AssignRelayToServer("freecam", false);
commands.Add(new Command("clientlist", "", (string[] args) => { }));
AssignRelayToServer("clientlist", true);
AssignOnExecute("control", (string[] args) =>
{ {
if (args.Length < 1) return; if (args.Length < 1) return;
var character = FindMatchingCharacter(args, true); var character = FindMatchingCharacter(args, true);
if (character != null) if (character != null)
{ {
Character.Controlled = character; Character.Controlled = character;
} }
}, });
() => AssignRelayToServer("control", true);
{
return new string[][]
{
Character.CharacterList.Select(c => c.Name).Distinct().ToArray()
};
}, isCheat: true));
commands.Add(new Command("shake", "", (string[] args) => commands.Add(new Command("shake", "", (string[] args) =>
{ {
GameMain.GameScreen.Cam.Shake = 10.0f; GameMain.GameScreen.Cam.Shake = 10.0f;
})); }));
commands.Add(new Command("los", "los: Toggle the line of sight effect on/off.", (string[] args) => AssignOnExecute("los", (string[] args) =>
{ {
GameMain.LightManager.LosEnabled = !GameMain.LightManager.LosEnabled; GameMain.LightManager.LosEnabled = !GameMain.LightManager.LosEnabled;
NewMessage("Line of sight effect " + (GameMain.LightManager.LosEnabled ? "enabled" : "disabled"), Color.White); NewMessage("Line of sight effect " + (GameMain.LightManager.LosEnabled ? "enabled" : "disabled"), Color.White);
}, isCheat: true)); });
AssignRelayToServer("los", false);
commands.Add(new Command("lighting|lights", "Toggle lighting on/off.", (string[] args) => AssignOnExecute("lighting|lights", (string[] args) =>
{ {
GameMain.LightManager.LightingEnabled = !GameMain.LightManager.LightingEnabled; GameMain.LightManager.LightingEnabled = !GameMain.LightManager.LightingEnabled;
NewMessage("Lighting " + (GameMain.LightManager.LightingEnabled ? "enabled" : "disabled"), Color.White); NewMessage("Lighting " + (GameMain.LightManager.LightingEnabled ? "enabled" : "disabled"), Color.White);
}, isCheat: true)); });
AssignRelayToServer("lighting|lights", false);
AssignOnExecute("ambientlight", (string[] args) =>
{
if (Level.Loaded == null)
{
ThrowError("Could not set ambient light color (no level loaded).");
return;
}
Color color = XMLExtensions.ParseColor(string.Join("", args));
Level.Loaded.GenerationParams.AmbientLightColor = color;
NewMessage("Set ambient light color to " + color + ".", Color.White);
});
AssignRelayToServer("ambientlight", false);
commands.Add(new Command("multiplylights", "Multiplies the colors of all the static lights in the sub with the given Vector4 value (for example, 1,1,1,0.5).", (string[] args) => commands.Add(new Command("multiplylights", "Multiplies the colors of all the static lights in the sub with the given Vector4 value (for example, 1,1,1,0.5).", (string[] args) =>
{ {
@@ -373,9 +461,9 @@ namespace Barotrauma
{ {
if (item.ParentInventory != null || item.body != null) continue; if (item.ParentInventory != null || item.body != null) continue;
var lightComponent = item.GetComponent<LightComponent>(); var lightComponent = item.GetComponent<LightComponent>();
if (lightComponent != null) lightComponent.LightColor = if (lightComponent != null) lightComponent.LightColor =
new Color( new Color(
(lightComponent.LightColor.R / 255.0f) * value.X, (lightComponent.LightColor.R / 255.0f) * value.X,
(lightComponent.LightColor.G / 255.0f) * value.Y, (lightComponent.LightColor.G / 255.0f) * value.Y,
(lightComponent.LightColor.B / 255.0f) * value.Z, (lightComponent.LightColor.B / 255.0f) * value.Z,
(lightComponent.LightColor.A / 255.0f) * value.W); (lightComponent.LightColor.A / 255.0f) * value.W);
@@ -434,7 +522,7 @@ namespace Barotrauma
} }
} }
}, isCheat: true)); }, isCheat: true));
commands.Add(new Command("alpha", "Change the alpha (as bytes from 0 to 255) of the selected item/structure instances. Applied only in the subeditor.", (string[] args) => commands.Add(new Command("alpha", "Change the alpha (as bytes from 0 to 255) of the selected item/structure instances. Applied only in the subeditor.", (string[] args) =>
{ {
if (Screen.Selected == GameMain.SubEditorScreen) if (Screen.Selected == GameMain.SubEditorScreen)
@@ -548,11 +636,12 @@ namespace Barotrauma
new GUIMessageBox("", string.Join(" ", args)); new GUIMessageBox("", string.Join(" ", args));
})); }));
commands.Add(new Command("debugdraw", "debugdraw: Toggle the debug drawing mode on/off.", (string[] args) => AssignOnExecute("debugdraw", (string[] args) =>
{ {
GameMain.DebugDraw = !GameMain.DebugDraw; GameMain.DebugDraw = !GameMain.DebugDraw;
NewMessage("Debug draw mode " + (GameMain.DebugDraw ? "enabled" : "disabled"), Color.White); NewMessage("Debug draw mode " + (GameMain.DebugDraw ? "enabled" : "disabled"), Color.White);
}, isCheat: true)); });
AssignRelayToServer("debugdraw", false);
commands.Add(new Command("fpscounter", "fpscounter: Toggle the FPS counter.", (string[] args) => commands.Add(new Command("fpscounter", "fpscounter: Toggle the FPS counter.", (string[] args) =>
{ {
@@ -565,6 +654,12 @@ namespace Barotrauma
NewMessage("Performance statistics " + (GameMain.ShowPerf ? "enabled" : "disabled"), Color.White); NewMessage("Performance statistics " + (GameMain.ShowPerf ? "enabled" : "disabled"), Color.White);
})); }));
AssignOnClientExecute("netstats", (string[] args) =>
{
if (GameMain.Client == null) return;
GameMain.Client.ShowNetStats = !GameMain.Client.ShowNetStats;
});
commands.Add(new Command("hudlayoutdebugdraw|debugdrawhudlayout", "hudlayoutdebugdraw: Toggle the debug drawing mode of HUD layout areas on/off.", (string[] args) => commands.Add(new Command("hudlayoutdebugdraw|debugdrawhudlayout", "hudlayoutdebugdraw: Toggle the debug drawing mode of HUD layout areas on/off.", (string[] args) =>
{ {
HUDLayoutSettings.DebugDraw = !HUDLayoutSettings.DebugDraw; HUDLayoutSettings.DebugDraw = !HUDLayoutSettings.DebugDraw;
@@ -577,24 +672,72 @@ namespace Barotrauma
NewMessage("Interact debug draw mode " + (Character.DebugDrawInteract ? "enabled" : "disabled"), Color.White); NewMessage("Interact debug draw mode " + (Character.DebugDrawInteract ? "enabled" : "disabled"), Color.White);
}, isCheat: true)); }, isCheat: true));
commands.Add(new Command("togglehud|hud", "togglehud/hud: Toggle the character HUD (inventories, icons, buttons, etc) on/off.", (string[] args) => AssignOnExecute("togglehud|hud", (string[] args) =>
{ {
GUI.DisableHUD = !GUI.DisableHUD; GUI.DisableHUD = !GUI.DisableHUD;
GameMain.Instance.IsMouseVisible = !GameMain.Instance.IsMouseVisible; GameMain.Instance.IsMouseVisible = !GameMain.Instance.IsMouseVisible;
NewMessage(GUI.DisableHUD ? "Disabled HUD" : "Enabled HUD", Color.White); NewMessage(GUI.DisableHUD ? "Disabled HUD" : "Enabled HUD", Color.White);
})); });
AssignRelayToServer("togglehud|hud", false);
commands.Add(new Command("followsub", "followsub: Toggle whether the camera should follow the nearest submarine.", (string[] args) => AssignOnExecute("toggleupperhud", (string[] args) =>
{
GUI.DisableUpperHUD = !GUI.DisableUpperHUD;
NewMessage(GUI.DisableUpperHUD ? "Disabled upper HUD" : "Enabled upper HUD", Color.White);
});
AssignRelayToServer("toggleupperhud", false);
AssignOnExecute("toggleitemhighlights", (string[] args) =>
{
GUI.DisableItemHighlights = !GUI.DisableItemHighlights;
NewMessage(GUI.DisableItemHighlights ? "Disabled item highlights" : "Enabled item highlights", Color.White);
});
AssignRelayToServer("toggleitemhighlights", false);
AssignOnExecute("togglecharacternames", (string[] args) =>
{
GUI.DisableCharacterNames = !GUI.DisableCharacterNames;
NewMessage(GUI.DisableCharacterNames ? "Disabled character names" : "Enabled character names", Color.White);
});
AssignRelayToServer("togglecharacternames", false);
AssignOnExecute("followsub", (string[] args) =>
{ {
Camera.FollowSub = !Camera.FollowSub; Camera.FollowSub = !Camera.FollowSub;
NewMessage(Camera.FollowSub ? "Set the camera to follow the closest submarine" : "Disabled submarine following.", Color.White); NewMessage(Camera.FollowSub ? "Set the camera to follow the closest submarine" : "Disabled submarine following.", Color.White);
})); });
AssignRelayToServer("followsub", false);
commands.Add(new Command("toggleaitargets|aitargets", "toggleaitargets/aitargets: Toggle the visibility of AI targets (= targets that enemies can detect and attack/escape from).", (string[] args) => AssignOnExecute("toggleaitargets|aitargets", (string[] args) =>
{ {
AITarget.ShowAITargets = !AITarget.ShowAITargets; AITarget.ShowAITargets = !AITarget.ShowAITargets;
NewMessage(AITarget.ShowAITargets ? "Enabled AI target drawing" : "Disabled AI target drawing", Color.White); NewMessage(AITarget.ShowAITargets ? "Enabled AI target drawing" : "Disabled AI target drawing", Color.White);
}, isCheat: true)); });
AssignRelayToServer("toggleaitargets|aitargets", false);
AssignRelayToServer("water|editwater", false);
AssignRelayToServer("fire|editfire", false);
commands.Add(new Command("mute", "mute [name]: Prevent the client from speaking to anyone through the voice chat. Using this command requires a permission from the server host.",
null,
() =>
{
if (GameMain.Client == null) return null;
return new string[][]
{
GameMain.Client.ConnectedClients.Select(c => c.Name).ToArray()
};
}));
commands.Add(new Command("unmute", "unmute [name]: Allow the client to speak to anyone through the voice chat. Using this command requires a permission from the server host.",
null,
() =>
{
if (GameMain.Client == null) return null;
return new string[][]
{
GameMain.Client.ConnectedClients.Select(c => c.Name).ToArray()
};
}));
commands.Add(new Command("checkcrafting", "checkcrafting: Checks item deconstruction & crafting recipes for inconsistencies.", (string[] args) => commands.Add(new Command("checkcrafting", "checkcrafting: Checks item deconstruction & crafting recipes for inconsistencies.", (string[] args) =>
{ {
@@ -696,7 +839,6 @@ namespace Barotrauma
} }
}, isCheat: false)); }, isCheat: false));
#if DEBUG #if DEBUG
commands.Add(new Command("spamchatmessages", "", (string[] args) => commands.Add(new Command("spamchatmessages", "", (string[] args) =>
{ {
@@ -707,11 +849,7 @@ namespace Barotrauma
for (int i = 0; i < msgCount; i++) for (int i = 0; i < msgCount; i++)
{ {
if (GameMain.Server != null) if (GameMain.Client != null)
{
GameMain.Server.SendChatMessage(ToolBox.RandomSeed(msgLength), ChatMessageType.Default);
}
else if (GameMain.Client != null)
{ {
GameMain.Client.SendChatMessage(ToolBox.RandomSeed(msgLength)); GameMain.Client.SendChatMessage(ToolBox.RandomSeed(msgLength));
} }
@@ -739,7 +877,7 @@ namespace Barotrauma
Screen.Selected.Cam.MinZoom = minZoom; Screen.Selected.Cam.MinZoom = minZoom;
Screen.Selected.Cam.MaxZoom = maxZoom; Screen.Selected.Cam.MaxZoom = maxZoom;
})); }));
commands.Add(new Command("waterparams", "waterparams [distortionscalex] [distortionscaley] [distortionstrengthx] [distortionstrengthy] [bluramount]: default 0.5 0.5 0.5 0.5 1", (string[] args) => commands.Add(new Command("waterparams", "waterparams [distortionscalex] [distortionscaley] [distortionstrengthx] [distortionstrengthy] [bluramount]: default 0.5 0.5 0.5 0.5 1", (string[] args) =>
{ {
float distortScaleX = 0.5f, distortScaleY = 0.5f; float distortScaleX = 0.5f, distortScaleY = 0.5f;
@@ -753,8 +891,7 @@ namespace Barotrauma
WaterRenderer.DistortionScale = new Vector2(distortScaleX, distortScaleY); WaterRenderer.DistortionScale = new Vector2(distortScaleX, distortScaleY);
WaterRenderer.DistortionStrength = new Vector2(distortStrengthX, distortStrengthY); WaterRenderer.DistortionStrength = new Vector2(distortStrengthX, distortStrengthY);
WaterRenderer.BlurAmount = blurAmount; WaterRenderer.BlurAmount = blurAmount;
}, }));
null, null));
commands.Add(new Command("refreshrect", "Updates the dimensions of the selected items to match the ones defined in the prefab. Applied only in the subeditor.", (string[] args) => commands.Add(new Command("refreshrect", "Updates the dimensions of the selected items to match the ones defined in the prefab. Applied only in the subeditor.", (string[] args) =>
@@ -767,13 +904,13 @@ namespace Barotrauma
ThrowError("You have to select item(s) first!"); ThrowError("You have to select item(s) first!");
} }
else else
{ {
foreach (var mapEntity in MapEntity.SelectedList) foreach (var mapEntity in MapEntity.SelectedList)
{ {
if (mapEntity is Item item) if (mapEntity is Item item)
{ {
item.Rect = new Rectangle(item.Rect.X, item.Rect.Y, item.Rect = new Rectangle(item.Rect.X, item.Rect.Y,
(int)(item.Prefab.sprite.size.X * item.Prefab.Scale), (int)(item.Prefab.sprite.size.X * item.Prefab.Scale),
(int)(item.Prefab.sprite.size.Y * item.Prefab.Scale)); (int)(item.Prefab.sprite.size.Y * item.Prefab.Scale));
} }
else if (mapEntity is Structure structure) else if (mapEntity is Structure structure)
@@ -875,7 +1012,7 @@ namespace Barotrauma
destinationElement.AddAfterSelf(element); destinationElement.AddAfterSelf(element);
} }
XNode nextNode = destinationElement.NextNode; XNode nextNode = destinationElement.NextNode;
while ((!(nextNode is XElement) || nextNode == element) && nextNode != null) nextNode = nextNode.NextNode; while ((!(nextNode is XElement) || nextNode == element) && nextNode != null) nextNode = nextNode.NextNode;
destinationElement = nextNode as XElement; destinationElement = nextNode as XElement;
} }
destinationDoc.Save(destinationPath); destinationDoc.Save(destinationPath);
@@ -901,7 +1038,97 @@ namespace Barotrauma
} }
File.WriteAllLines(filePath, lines); File.WriteAllLines(filePath, lines);
})); }));
#if DEBUG
commands.Add(new Command("checkduplicates", "Checks the given language for duplicate translation keys and writes to file.", (string[] args) =>
{
if (args.Length != 1) return;
TextManager.CheckForDuplicates(args[0]);
}));
commands.Add(new Command("writetocsv", "Writes the default language (English) to a .csv file.", (string[] args) =>
{
TextManager.WriteToCSV();
NPCConversation.WriteToCSV();
}));
commands.Add(new Command("camerasettings", "camerasettings [defaultzoom] [zoomsmoothness] [movesmoothness] [minzoom] [maxzoom]: debug command for testing camera settings. The values default to 1.1, 8.0, 8.0, 0.1 and 2.0.", (string[] args) =>
{
float defaultZoom = Screen.Selected.Cam.DefaultZoom;
if (args.Length > 0) float.TryParse(args[0], NumberStyles.Number, CultureInfo.InvariantCulture, out defaultZoom);
float zoomSmoothness = Screen.Selected.Cam.ZoomSmoothness;
if (args.Length > 1) float.TryParse(args[1], NumberStyles.Number, CultureInfo.InvariantCulture, out zoomSmoothness);
float moveSmoothness = Screen.Selected.Cam.MoveSmoothness;
if (args.Length > 2) float.TryParse(args[2], NumberStyles.Number, CultureInfo.InvariantCulture, out moveSmoothness);
float minZoom = Screen.Selected.Cam.MinZoom;
if (args.Length > 3) float.TryParse(args[3], NumberStyles.Number, CultureInfo.InvariantCulture, out minZoom);
float maxZoom = Screen.Selected.Cam.MaxZoom;
if (args.Length > 4) float.TryParse(args[4], NumberStyles.Number, CultureInfo.InvariantCulture, out maxZoom);
Screen.Selected.Cam.DefaultZoom = defaultZoom;
Screen.Selected.Cam.ZoomSmoothness = zoomSmoothness;
Screen.Selected.Cam.MoveSmoothness = moveSmoothness;
Screen.Selected.Cam.MinZoom = minZoom;
Screen.Selected.Cam.MaxZoom = maxZoom;
}));
commands.Add(new Command("waterparams", "waterparams [distortionscalex] [distortionscaley] [distortionstrengthx] [distortionstrengthy] [bluramount]: default 0.5 0.5 0.5 0.5 1", (string[] args) =>
{
float distortScaleX = 0.5f, distortScaleY = 0.5f;
float distortStrengthX = 0.5f, distortStrengthY = 0.5f;
float blurAmount = 0.0f;
if (args.Length > 0) float.TryParse(args[0], NumberStyles.Number, CultureInfo.InvariantCulture, out distortScaleX);
if (args.Length > 1) float.TryParse(args[1], NumberStyles.Number, CultureInfo.InvariantCulture, out distortScaleY);
if (args.Length > 2) float.TryParse(args[2], NumberStyles.Number, CultureInfo.InvariantCulture, out distortStrengthX);
if (args.Length > 3) float.TryParse(args[3], NumberStyles.Number, CultureInfo.InvariantCulture, out distortStrengthY);
if (args.Length > 4) float.TryParse(args[4], NumberStyles.Number, CultureInfo.InvariantCulture, out blurAmount);
WaterRenderer.DistortionScale = new Vector2(distortScaleX, distortScaleY);
WaterRenderer.DistortionStrength = new Vector2(distortStrengthX, distortStrengthY);
WaterRenderer.BlurAmount = blurAmount;
},
null, null));
commands.Add(new Command("refreshrect", "Updates the dimensions of the selected items to match the ones defined in the prefab. Applied only in the subeditor.", (string[] args) =>
{
//TODO: maybe do this automatically during loading when possible?
if (Screen.Selected == GameMain.SubEditorScreen)
{
if (!MapEntity.SelectedAny)
{
ThrowError("You have to select item(s) first!");
}
else
{
foreach (var mapEntity in MapEntity.SelectedList)
{
if (mapEntity is Item item)
{
item.Rect = new Rectangle(item.Rect.X, item.Rect.Y,
(int)(item.Prefab.sprite.size.X * item.Prefab.Scale),
(int)(item.Prefab.sprite.size.Y * item.Prefab.Scale));
}
else if (mapEntity is Structure structure)
{
if (!structure.ResizeHorizontal)
{
structure.Rect = new Rectangle(structure.Rect.X, structure.Rect.Y,
(int)structure.Prefab.ScaledSize.X,
structure.Rect.Height);
}
if (!structure.ResizeVertical)
{
structure.Rect = new Rectangle(structure.Rect.X, structure.Rect.Y,
structure.Rect.Width,
(int)structure.Prefab.ScaledSize.Y);
}
}
}
}
}
}, isCheat: false));
#endif
commands.Add(new Command("cleanbuild", "", (string[] args) => commands.Add(new Command("cleanbuild", "", (string[] args) =>
{ {
@@ -924,7 +1151,7 @@ namespace Barotrauma
ThrowError("MasterServerUrl \"" + GameMain.Config.MasterServerUrl + "\"!"); ThrowError("MasterServerUrl \"" + GameMain.Config.MasterServerUrl + "\"!");
} }
GameMain.Config.Save(); GameMain.Config.SaveNewPlayerConfig();
var saveFiles = System.IO.Directory.GetFiles(SaveUtil.SaveFolder); var saveFiles = System.IO.Directory.GetFiles(SaveUtil.SaveFolder);
@@ -970,7 +1197,7 @@ namespace Barotrauma
NewMessage("Deleted TutorialSub from the submarine folder", Color.Green); NewMessage("Deleted TutorialSub from the submarine folder", Color.Green);
} }
if (System.IO.File.Exists(GameServer.SettingsFile)) /*if (System.IO.File.Exists(GameServer.SettingsFile))
{ {
System.IO.File.Delete(GameServer.SettingsFile); System.IO.File.Delete(GameServer.SettingsFile);
NewMessage("Deleted server settings", Color.Green); NewMessage("Deleted server settings", Color.Green);
@@ -980,7 +1207,7 @@ namespace Barotrauma
{ {
System.IO.File.Delete(GameServer.ClientPermissionsFile); System.IO.File.Delete(GameServer.ClientPermissionsFile);
NewMessage("Deleted client permission file", Color.Green); NewMessage("Deleted client permission file", Color.Green);
} }*/
if (System.IO.File.Exists("crashreport.log")) if (System.IO.File.Exists("crashreport.log"))
{ {
@@ -993,6 +1220,221 @@ namespace Barotrauma
ThrowError("TutorialSub.sub not found!"); ThrowError("TutorialSub.sub not found!");
} }
})); }));
AssignOnClientExecute(
"giveperm",
(string[] args) =>
{
if (args.Length < 1) return;
if (!int.TryParse(args[0], out int id))
{
ThrowError("\"" + id + "\" is not a valid client ID.");
return;
}
NewMessage("Valid permissions are:", Color.White);
foreach (ClientPermissions permission in Enum.GetValues(typeof(ClientPermissions)))
{
NewMessage(" - " + permission.ToString(), Color.White);
}
ShowQuestionPrompt("Permission to grant to client #" + id + "?", (perm) =>
{
GameMain.Client.SendConsoleCommand("giveperm " + id + " " + perm);
});
}
);
AssignOnClientExecute(
"revokeperm",
(string[] args) =>
{
if (args.Length < 1) return;
if (!int.TryParse(args[0], out int id))
{
ThrowError("\"" + id + "\" is not a valid client ID.");
return;
}
NewMessage("Valid permissions are:", Color.White);
foreach (ClientPermissions permission in Enum.GetValues(typeof(ClientPermissions)))
{
NewMessage(" - " + permission.ToString(), Color.White);
}
ShowQuestionPrompt("Permission to revoke from client #" + id + "?", (perm) =>
{
GameMain.Client.SendConsoleCommand("revokeperm " + id + " " + perm);
});
}
);
AssignOnClientExecute(
"giverank",
(string[] args) =>
{
if (args.Length < 1) return;
if (!int.TryParse(args[0], out int id))
{
ThrowError("\"" + id + "\" is not a valid client ID.");
return;
}
NewMessage("Valid ranks are:", Color.White);
foreach (PermissionPreset permissionPreset in PermissionPreset.List)
{
NewMessage(" - " + permissionPreset.Name, Color.White);
}
ShowQuestionPrompt("Rank to grant to client #" + id + "?", (rank) =>
{
GameMain.Client.SendConsoleCommand("giverank " + id + " " + rank);
});
}
);
AssignOnClientExecute(
"givecommandperm",
(string[] args) =>
{
if (args.Length < 1) return;
if (!int.TryParse(args[0], out int id))
{
ThrowError("\"" + id + "\" is not a valid client ID.");
return;
}
ShowQuestionPrompt("Console command permissions to grant to client #" + id + "? You may enter multiple commands separated with a space.", (commandNames) =>
{
GameMain.Client.SendConsoleCommand("givecommandperm " + id + " " + commandNames);
});
}
);
AssignOnClientExecute(
"revokecommandperm",
(string[] args) =>
{
if (args.Length < 1) return;
if (!int.TryParse(args[0], out int id))
{
ThrowError("\"" + id + "\" is not a valid client ID.");
return;
}
ShowQuestionPrompt("Console command permissions to revoke from client #" + id + "? You may enter multiple commands separated with a space.", (commandNames) =>
{
GameMain.Client.SendConsoleCommand("revokecommandperm " + id + " " + commandNames);
});
}
);
AssignOnClientExecute(
"showperm",
(string[] args) =>
{
if (args.Length < 1) return;
if (!int.TryParse(args[0], out int id))
{
ThrowError("\"" + id + "\" is not a valid client ID.");
return;
}
GameMain.Client.SendConsoleCommand("showperm " + id);
}
);
AssignOnClientExecute(
"banip",
(string[] args) =>
{
if (GameMain.Client == null || args.Length == 0) return;
ShowQuestionPrompt("Reason for banning the ip \"" + args[0] + "\"?", (reason) =>
{
ShowQuestionPrompt("Enter the duration of the ban (leave empty to ban permanently, or use the format \"[days] d [hours] h\")", (duration) =>
{
TimeSpan? banDuration = null;
if (!string.IsNullOrWhiteSpace(duration))
{
if (!TryParseTimeSpan(duration, out TimeSpan parsedBanDuration))
{
ThrowError("\"" + duration + "\" is not a valid ban duration. Use the format \"[days] d [hours] h\", \"[days] d\" or \"[hours] h\".");
return;
}
banDuration = parsedBanDuration;
}
GameMain.Client.SendConsoleCommand(
"banip " +
args[0] + " " +
(banDuration.HasValue ? banDuration.Value.TotalSeconds.ToString() : "0") + " " +
reason);
});
});
}
);
commands.Add(new Command("unban", "unban [name]: Unban a specific client.", (string[] args) =>
{
if (GameMain.Client == null || args.Length == 0) return;
string clientName = string.Join(" ", args);
GameMain.Client.UnbanPlayer(clientName, "");
}));
commands.Add(new Command("unbanip", "unbanip [ip]: Unban a specific IP.", (string[] args) =>
{
if (GameMain.Client == null || args.Length == 0) return;
GameMain.Client.UnbanPlayer("", args[0]);
}));
AssignOnClientExecute(
"campaigndestination|setcampaigndestination",
(string[] args) =>
{
var campaign = GameMain.GameSession?.GameMode as CampaignMode;
if (campaign == null)
{
ThrowError("No campaign active!");
return;
}
if (args.Length == 0)
{
int i = 0;
foreach (LocationConnection connection in campaign.Map.CurrentLocation.Connections)
{
NewMessage(" " + i + ". " + connection.OtherLocation(campaign.Map.CurrentLocation).Name, Color.White);
i++;
}
ShowQuestionPrompt("Select a destination (0 - " + (campaign.Map.CurrentLocation.Connections.Count - 1) + "):", (string selectedDestination) =>
{
int destinationIndex = -1;
if (!int.TryParse(selectedDestination, out destinationIndex)) return;
if (destinationIndex < 0 || destinationIndex >= campaign.Map.CurrentLocation.Connections.Count)
{
NewMessage("Index out of bounds!", Color.Red);
return;
}
GameMain.Client.SendConsoleCommand("campaigndestination " + destinationIndex);
});
}
else
{
int destinationIndex = -1;
if (!int.TryParse(args[0], out destinationIndex)) return;
if (destinationIndex < 0 || destinationIndex >= campaign.Map.CurrentLocation.Connections.Count)
{
NewMessage("Index out of bounds!", Color.Red);
return;
}
GameMain.Client.SendConsoleCommand("campaigndestination " + destinationIndex);
}
}
);
commands.Add(new Command("limbscale", "Define the limbscale for the controlled character. Provide id or name if you want to target another character. Note: the changes are not saved!", (string[] args) => commands.Add(new Command("limbscale", "Define the limbscale for the controlled character. Provide id or name if you want to target another character. Note: the changes are not saved!", (string[] args) =>
{ {
@@ -178,11 +178,12 @@ namespace EventInput
private static void ReceiveInput(object sender, TextInputEventArgs e) private static void ReceiveInput(object sender, TextInputEventArgs e)
{ {
OnCharEntered(e.Character); OnCharEntered(e.Character);
KeyDown?.Invoke(sender, new KeyEventArgs(e.Key));
} }
public static void OnCharEntered(char character) public static void OnCharEntered(char character)
{ {
if (CharEntered != null) CharEntered(null, new CharacterEventArgs(character, 0)); CharEntered?.Invoke(null, new CharacterEventArgs(character, 0));
} }
#if WINDOWS #if WINDOWS
static IntPtr HookProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam) static IntPtr HookProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam)
@@ -27,7 +27,7 @@ namespace EventInput
EventInput.KeyDown += EventInput_KeyDown; EventInput.KeyDown += EventInput_KeyDown;
} }
void EventInput_KeyDown(object sender, KeyEventArgs e) public void EventInput_KeyDown(object sender, KeyEventArgs e)
{ {
if (_subscriber == null) if (_subscriber == null)
return; return;
@@ -74,6 +74,7 @@ namespace EventInput
get { return _subscriber; } get { return _subscriber; }
set set
{ {
if (_subscriber == value) return;
if (_subscriber != null) if (_subscriber != null)
_subscriber.Selected = false; _subscriber.Selected = false;
_subscriber = value; _subscriber = value;
@@ -17,8 +17,9 @@ namespace Barotrauma
Vector2 drawPos = ev.DebugDrawPos; Vector2 drawPos = ev.DebugDrawPos;
drawPos.Y = -drawPos.Y; drawPos.Y = -drawPos.Y;
GUI.SubmarineIcon.Draw(spriteBatch, drawPos, Color.White * 0.5f, GUI.SubmarineIcon.size / 2, 0.0f, 40.0f); var textOffset = new Vector2(-150, 0);
GUI.DrawString(spriteBatch, drawPos, ev.ToString(), Color.White, Color.Black, 0, GUI.LargeFont); ShapeExtensions.DrawCircle(spriteBatch, drawPos, 600, 6, Color.White, thickness: 20);
GUI.DrawString(spriteBatch, drawPos + textOffset, ev.ToString(), Color.White, Color.Black, 0, GUI.LargeFont);
} }
} }
@@ -0,0 +1,22 @@
namespace Barotrauma
{
partial class CombatMission
{
public override string Description
{
get
{
if (descriptions == null) return "";
if (GameMain.Client?.Character == null)
{
//non-team-specific description
return descriptions[0];
}
//team specific
return descriptions[GameMain.Client.Character.TeamID == Character.TeamType.Team1 ? 1 : 2];
}
}
}
}
@@ -11,7 +11,8 @@ namespace Barotrauma
string header = index < Headers.Count ? Headers[index] : ""; string header = index < Headers.Count ? Headers[index] : "";
string message = index < Messages.Count ? Messages[index] : ""; string message = index < Messages.Count ? Messages[index] : "";
GameServer.Log(TextManager.Get("MissionInfo") + ": " + header + " - " + message, ServerLog.MessageType.ServerMessage); //TODO: reimplement
//GameServer.Log(TextManager.Get("MissionInfo") + ": " + header + " - " + message, ServerLog.MessageType.ServerMessage);
new GUIMessageBox(header, message); new GUIMessageBox(header, message);
} }
@@ -9,8 +9,10 @@
var missionMsg = new GUIMessageBox(mission.Name, mission.Description, 400, 400); var missionMsg = new GUIMessageBox(mission.Name, mission.Description, 400, 400);
missionMsg.UserData = "missionstartmessage"; missionMsg.UserData = "missionstartmessage";
#if SERVER
Networking.GameServer.Log(TextManager.Get("Mission") + ": " + mission.Name, Networking.ServerLog.MessageType.ServerMessage); Networking.GameServer.Log(TextManager.Get("Mission") + ": " + mission.Name, Networking.ServerLog.MessageType.ServerMessage);
Networking.GameServer.Log(mission.Description, Networking.ServerLog.MessageType.ServerMessage); Networking.GameServer.Log(mission.Description, Networking.ServerLog.MessageType.ServerMessage);
#endif
} }
} }
} }
@@ -172,7 +172,7 @@ namespace Barotrauma
float prevSize = chatBox.BarSize; float prevSize = chatBox.BarSize;
string displayedText = message.Text; string displayedText = message.TranslatedText;
string senderName = ""; string senderName = "";
if (!string.IsNullOrWhiteSpace(message.SenderName)) if (!string.IsNullOrWhiteSpace(message.SenderName))
{ {
@@ -245,7 +245,7 @@ namespace Barotrauma
if ((prevSize == 1.0f && chatBox.BarScroll == 0.0f) || (prevSize < 1.0f && chatBox.BarScroll == 1.0f)) chatBox.BarScroll = 1.0f; if ((prevSize == 1.0f && chatBox.BarScroll == 0.0f) || (prevSize < 1.0f && chatBox.BarScroll == 1.0f)) chatBox.BarScroll = 1.0f;
GUISoundType soundType = GUISoundType.Message; GUISoundType soundType = GUISoundType.ChatMessage;
if (message.Type == ChatMessageType.Radio) if (message.Type == ChatMessageType.Radio)
{ {
soundType = GUISoundType.RadioMessage; soundType = GUISoundType.RadioMessage;
+19 -18
View File
@@ -13,7 +13,8 @@ namespace Barotrauma
{ {
public enum GUISoundType public enum GUISoundType
{ {
Message, UIMessage,
ChatMessage,
RadioMessage, RadioMessage,
DeadMessage, DeadMessage,
Click, Click,
@@ -58,7 +59,7 @@ namespace Barotrauma
private static GUIFrame pauseMenu; private static GUIFrame pauseMenu;
private static Sprite arrow, lockIcon, checkmarkIcon, timerIcon; private static Sprite arrow, lockIcon, checkmarkIcon, timerIcon;
public static KeyboardDispatcher KeyboardDispatcher { get; private set; } public static KeyboardDispatcher KeyboardDispatcher { get; set; }
/// <summary> /// <summary>
/// Has the selected Screen changed since the last time the GUI was drawn. /// Has the selected Screen changed since the last time the GUI was drawn.
@@ -131,12 +132,11 @@ namespace Barotrauma
set; set;
} }
public static bool DisableHUD; public static bool DisableHUD, DisableUpperHUD, DisableItemHighlights, DisableCharacterNames;
public static void Init(GameWindow window, IEnumerable<ContentPackage> selectedContentPackages, GraphicsDevice graphicsDevice) public static void Init(GameWindow window, IEnumerable<ContentPackage> selectedContentPackages, GraphicsDevice graphicsDevice)
{ {
GUI.graphicsDevice = graphicsDevice; GUI.graphicsDevice = graphicsDevice;
KeyboardDispatcher = new KeyboardDispatcher(window);
var uiStyles = ContentPackage.GetFilesOfType(selectedContentPackages, ContentType.UIStyle).ToList(); var uiStyles = ContentPackage.GetFilesOfType(selectedContentPackages, ContentType.UIStyle).ToList();
if (uiStyles.Count == 0) if (uiStyles.Count == 0)
{ {
@@ -157,14 +157,15 @@ namespace Barotrauma
{ {
sounds = new Sound[Enum.GetValues(typeof(GUISoundType)).Length]; sounds = new Sound[Enum.GetValues(typeof(GUISoundType)).Length];
sounds[(int)GUISoundType.Message] = GameMain.SoundManager.LoadSound("Content/Sounds/UI/UImsg.ogg", false); sounds[(int)GUISoundType.UIMessage] = GameMain.SoundManager.LoadSound("Content/Sounds/UI/UImsg.ogg", false);
sounds[(int)GUISoundType.RadioMessage] = GameMain.SoundManager.LoadSound("Content/Sounds/UI/radiomsg.ogg", false); sounds[(int)GUISoundType.ChatMessage] = GameMain.SoundManager.LoadSound("Content/Sounds/UI/ChatMsg.ogg", false);
sounds[(int)GUISoundType.DeadMessage] = GameMain.SoundManager.LoadSound("Content/Sounds/UI/deadmsg.ogg", false); sounds[(int)GUISoundType.RadioMessage] = GameMain.SoundManager.LoadSound("Content/Sounds/UI/RadioMsg.ogg", false);
sounds[(int)GUISoundType.Click] = GameMain.SoundManager.LoadSound("Content/Sounds/UI/beep-shinymetal.ogg", false); sounds[(int)GUISoundType.DeadMessage] = GameMain.SoundManager.LoadSound("Content/Sounds/UI/DeadMsg.ogg", false);
sounds[(int)GUISoundType.Click] = GameMain.SoundManager.LoadSound("Content/Sounds/UI/Click.ogg", false);
sounds[(int)GUISoundType.PickItem] = GameMain.SoundManager.LoadSound("Content/Sounds/pickItem.ogg", false); sounds[(int)GUISoundType.PickItem] = GameMain.SoundManager.LoadSound("Content/Sounds/PickItem.ogg", false);
sounds[(int)GUISoundType.PickItemFail] = GameMain.SoundManager.LoadSound("Content/Sounds/pickItemFail.ogg", false); sounds[(int)GUISoundType.PickItemFail] = GameMain.SoundManager.LoadSound("Content/Sounds/PickItemFail.ogg", false);
sounds[(int)GUISoundType.DropItem] = GameMain.SoundManager.LoadSound("Content/Sounds/dropItem.ogg", false); sounds[(int)GUISoundType.DropItem] = GameMain.SoundManager.LoadSound("Content/Sounds/DropItem.ogg", false);
} }
// create 1x1 texture for line drawing // create 1x1 texture for line drawing
t = new Texture2D(GraphicsDevice, 1, 1); t = new Texture2D(GraphicsDevice, 1, 1);
@@ -290,7 +291,7 @@ namespace Barotrauma
{ {
Color clr = Color.White; Color clr = Color.White;
string soundStr = i + ": "; string soundStr = i + ": ";
SoundChannel playingSoundChannel = GameMain.SoundManager.GetSoundChannelFromIndex(i); SoundChannel playingSoundChannel = GameMain.SoundManager.GetSoundChannelFromIndex(SoundManager.SourcePoolIndex.Default, i);
if (playingSoundChannel == null) if (playingSoundChannel == null)
{ {
soundStr += "none"; soundStr += "none";
@@ -363,7 +364,7 @@ namespace Barotrauma
if (HUDLayoutSettings.DebugDraw) HUDLayoutSettings.Draw(spriteBatch); if (HUDLayoutSettings.DebugDraw) HUDLayoutSettings.Draw(spriteBatch);
if (GameMain.NetworkMember != null) GameMain.NetworkMember.Draw(spriteBatch); if (GameMain.Client != null) GameMain.Client.Draw(spriteBatch);
if (Character.Controlled?.Inventory != null) if (Character.Controlled?.Inventory != null)
{ {
@@ -1527,10 +1528,10 @@ namespace Barotrauma
SaveUtil.SaveGame(GameMain.GameSession.SavePath); SaveUtil.SaveGame(GameMain.GameSession.SavePath);
} }
if (GameMain.NetworkMember != null) if (GameMain.Client != null)
{ {
GameMain.NetworkMember.Disconnect(); GameMain.Client.Disconnect();
GameMain.NetworkMember = null; GameMain.Client = null;
} }
CoroutineManager.StopCoroutines("EndCinematic"); CoroutineManager.StopCoroutines("EndCinematic");
@@ -1563,13 +1564,13 @@ namespace Barotrauma
{ {
if (messages.Any(msg => msg.Text == message)) { return; } if (messages.Any(msg => msg.Text == message)) { return; }
messages.Add(new GUIMessage(message, color, lifeTime ?? MathHelper.Clamp(message.Length / 5.0f, 3.0f, 10.0f), font ?? LargeFont)); messages.Add(new GUIMessage(message, color, lifeTime ?? MathHelper.Clamp(message.Length / 5.0f, 3.0f, 10.0f), font ?? LargeFont));
if (playSound) PlayUISound(GUISoundType.Message); if (playSound) PlayUISound(GUISoundType.UIMessage);
} }
public static void AddMessage(string message, Color color, Vector2 worldPos, Vector2 velocity, float lifeTime = 3.0f, bool playSound = true) public static void AddMessage(string message, Color color, Vector2 worldPos, Vector2 velocity, float lifeTime = 3.0f, bool playSound = true)
{ {
messages.Add(new GUIMessage(message, color, worldPos, velocity, lifeTime, Alignment.Center, LargeFont)); messages.Add(new GUIMessage(message, color, worldPos, velocity, lifeTime, Alignment.Center, LargeFont));
if (playSound) PlayUISound(GUISoundType.Message); if (playSound) PlayUISound(GUISoundType.UIMessage);
} }
public static void ClearMessages() public static void ClearMessages()
@@ -36,6 +36,12 @@ namespace Barotrauma
set { listBox.Enabled = value; } set { listBox.Enabled = value; }
} }
public bool ButtonEnabled
{
get { return button.Enabled; }
set { button.Enabled = value; }
}
public GUIComponent Selected public GUIComponent Selected
{ {
get { return listBox.SelectedComponent; } get { return listBox.SelectedComponent; }
@@ -0,0 +1,74 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Xna.Framework;
namespace Barotrauma
{
public class GUIRadioButtonGroup : GUIComponent
{
private Dictionary<Enum, GUITickBox> radioButtons; //TODO: use children list instead?
public GUIRadioButtonGroup() : base("GUIFrame")
{
radioButtons = new Dictionary<Enum, GUITickBox>();
}
public void AddRadioButton(Enum key, GUITickBox radioButton)
{
if (selected == key) radioButton.Selected = true;
else if (radioButton.Selected) selected = key;
radioButton.SetRadioButtonGroup(this);
radioButtons.Add(key, radioButton);
}
public delegate void RadioButtonGroupDelegate(GUIRadioButtonGroup rbg, Enum val);
public RadioButtonGroupDelegate OnSelect = null;
public void SelectRadioButton(GUITickBox radioButton)
{
foreach (KeyValuePair<Enum, GUITickBox> rbPair in radioButtons)
{
if (radioButton == rbPair.Value)
{
Selected = rbPair.Key;
return;
}
}
}
private Enum selected;
public Enum Selected
{
get
{
return selected;
}
set
{
OnSelect?.Invoke(this, value);
if (selected != null && selected.Equals((Enum)value)) return;
selected = value;
foreach (KeyValuePair<Enum, GUITickBox> radioButton in radioButtons)
{
if (radioButton.Key.Equals((Enum)value))
{
radioButton.Value.Selected = true;
}
else if (radioButton.Value.Selected) radioButton.Value.Selected = false;
}
}
}
public GUITickBox SelectedRadioButton
{
get
{
return radioButtons[selected];
}
}
}
}
@@ -20,6 +20,7 @@ namespace Barotrauma
public delegate bool OnMovedHandler(GUIScrollBar scrollBar, float barScroll); public delegate bool OnMovedHandler(GUIScrollBar scrollBar, float barScroll);
public OnMovedHandler OnMoved; public OnMovedHandler OnMoved;
public OnMovedHandler OnReleased;
public bool IsBooleanSwitch; public bool IsBooleanSwitch;
@@ -87,6 +88,39 @@ namespace Barotrauma
} }
} }
private Vector2 range;
public Vector2 Range
{
get
{
return range;
}
set
{
float oldBarScrollValue = BarScrollValue;
range = value;
BarScrollValue = oldBarScrollValue;
}
}
public delegate float ScrollConversion(GUIScrollBar scrollBar, float f);
public ScrollConversion ScrollToValue = null;
public ScrollConversion ValueToScroll = null;
public float BarScrollValue
{
get
{
if (ScrollToValue==null) return (BarScroll * (Range.Y - Range.X)) + Range.X;
return ScrollToValue(this, BarScroll);
}
set
{
if (ValueToScroll==null) BarScroll = (value - Range.X) / (Range.Y - Range.X);
else BarScroll = ValueToScroll(this, value);
}
}
public float BarScroll public float BarScroll
{ {
get { return step == 0.0f ? barScroll : MathUtils.RoundTowardsClosest(barScroll, step); } get { return step == 0.0f ? barScroll : MathUtils.RoundTowardsClosest(barScroll, step); }
@@ -187,7 +221,11 @@ namespace Barotrauma
if (draggingBar == this) if (draggingBar == this)
{ {
if (!PlayerInput.LeftButtonHeld()) draggingBar = null; if (!PlayerInput.LeftButtonHeld())
{
OnReleased?.Invoke(this, BarScroll);
draggingBar = null;
}
if ((isHorizontal && PlayerInput.MousePosition.X > Rect.X && PlayerInput.MousePosition.X < Rect.Right) || if ((isHorizontal && PlayerInput.MousePosition.X > Rect.X && PlayerInput.MousePosition.X < Rect.Right) ||
(!isHorizontal && PlayerInput.MousePosition.Y > Rect.Y && PlayerInput.MousePosition.Y < Rect.Bottom)) (!isHorizontal && PlayerInput.MousePosition.Y > Rect.Y && PlayerInput.MousePosition.Y < Rect.Bottom))
{ {
@@ -198,6 +236,7 @@ namespace Barotrauma
{ {
if (PlayerInput.LeftButtonClicked()) if (PlayerInput.LeftButtonClicked())
{ {
draggingBar?.OnReleased?.Invoke(draggingBar, draggingBar.BarScroll);
MoveButton(new Vector2( MoveButton(new Vector2(
Math.Sign(PlayerInput.MousePosition.X - Bar.Rect.Center.X) * Bar.Rect.Width, Math.Sign(PlayerInput.MousePosition.X - Bar.Rect.Center.X) * Bar.Rect.Width,
Math.Sign(PlayerInput.MousePosition.Y - Bar.Rect.Center.Y) * Bar.Rect.Height)); Math.Sign(PlayerInput.MousePosition.Y - Bar.Rect.Center.Y) * Bar.Rect.Height));
@@ -1,5 +1,6 @@
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Graphics;
using System;
namespace Barotrauma namespace Barotrauma
{ {
@@ -216,25 +217,36 @@ namespace Barotrauma
if (autoScale && textScale > 0.1f && if (autoScale && textScale > 0.1f &&
(TextSize.X * textScale > rect.Width - padding.X - padding.Z || TextSize.Y * textScale > rect.Height - padding.Y - padding.W)) (TextSize.X * textScale > rect.Width - padding.X - padding.Z || TextSize.Y * textScale > rect.Height - padding.Y - padding.W))
{ {
TextScale -= 0.05f; TextScale = Math.Max(0.1f, Math.Min(
(rect.Width - padding.X - padding.Z) / TextSize.X,
(rect.Height - padding.Y - padding.W) / TextSize.Y)) - 0.01f;
return; return;
} }
textPos = new Vector2(rect.Width / 2.0f, rect.Height / 2.0f); textPos = new Vector2(rect.Width / 2.0f, rect.Height / 2.0f);
origin = TextSize / textScale * 0.5f; origin = TextSize * 0.5f;
if (textAlignment.HasFlag(Alignment.Left) && !overflowClipActive) if (textAlignment.HasFlag(Alignment.Left) && !overflowClipActive)
origin.X += (rect.Width / 2.0f - TextSize.X / 2) / textScale - padding.X; {
textPos.X = padding.X;
origin.X = 0;
}
if (textAlignment.HasFlag(Alignment.Right) || overflowClipActive) if (textAlignment.HasFlag(Alignment.Right) || overflowClipActive)
origin.X -= (rect.Width / 2.0f - TextSize.X / 2) / textScale - padding.Z; {
textPos.X = rect.Width - padding.Z;
origin.X = TextSize.X;
}
if (textAlignment.HasFlag(Alignment.Top)) if (textAlignment.HasFlag(Alignment.Top))
origin.Y += (rect.Height / 2.0f - TextSize.Y / 2) / textScale - padding.Y; {
textPos.Y = padding.Y;
origin.Y = 0;
}
if (textAlignment.HasFlag(Alignment.Bottom)) if (textAlignment.HasFlag(Alignment.Bottom))
origin.Y -= (rect.Height / 2.0f - TextSize.Y / 2) / textScale - padding.W; {
textPos.Y = rect.Height - padding.W;
origin.Y = TextSize.Y;
}
origin.X = (int)(origin.X); origin.X = (int)(origin.X);
origin.Y = (int)(origin.Y); origin.Y = (int)(origin.Y);
@@ -15,7 +15,7 @@ namespace Barotrauma
{ {
public event TextBoxEvent OnSelected; public event TextBoxEvent OnSelected;
public event TextBoxEvent OnDeselected; public event TextBoxEvent OnDeselected;
bool caretVisible; bool caretVisible;
float caretTimer; float caretTimer;
@@ -76,10 +76,24 @@ namespace Barotrauma
set { textBlock.TextGetter = value; } set { textBlock.TextGetter = value; }
} }
private bool selected;
public bool Selected public bool Selected
{ {
get; get
set; {
return selected;
}
set
{
if (!selected && value)
{
Select();
}
else if (selected && !value)
{
Deselect();
}
}
} }
public bool Wrap public bool Wrap
@@ -326,9 +340,9 @@ namespace Barotrauma
{ {
memento.Store(Text); memento.Store(Text);
} }
Selected = true;
CaretIndex = GetCaretIndexFromScreenPos(PlayerInput.MousePosition); CaretIndex = GetCaretIndexFromScreenPos(PlayerInput.MousePosition);
ClearSelection(); ClearSelection();
selected = true;
GUI.KeyboardDispatcher.Subscriber = this; GUI.KeyboardDispatcher.Subscriber = this;
OnSelected?.Invoke(this, Keys.None); OnSelected?.Invoke(this, Keys.None);
} }
@@ -336,7 +350,8 @@ namespace Barotrauma
public void Deselect() public void Deselect()
{ {
memento.Clear(); memento.Clear();
Selected = false; selected = false;
if (GUI.KeyboardDispatcher.Subscriber == this) if (GUI.KeyboardDispatcher.Subscriber == this)
{ {
GUI.KeyboardDispatcher.Subscriber = null; GUI.KeyboardDispatcher.Subscriber = null;
@@ -382,6 +397,7 @@ namespace Barotrauma
} }
else else
{ {
if (PlayerInput.LeftButtonClicked() && selected) Deselect();
isSelecting = false; isSelecting = false;
state = ComponentState.None; state = ComponentState.None;
} }
@@ -14,7 +14,7 @@ namespace Barotrauma
public static int size = 20; public static int size = 20;
private List<GUITickBox> radioButtonGroup; private GUIRadioButtonGroup radioButtonGroup;
private bool selected; private bool selected;
@@ -24,30 +24,21 @@ namespace Barotrauma
set set
{ {
if (value == selected) return; if (value == selected) return;
if (radioButtonGroup != null && !value) return; if (radioButtonGroup != null && radioButtonGroup.SelectedRadioButton == this)
{
selected = true;
return;
}
selected = value; selected = value;
state = (selected) ? ComponentState.Selected : ComponentState.None; state = (selected) ? ComponentState.Selected : ComponentState.None;
box.State = state; box.State = state;
if (radioButtonGroup != null) if (value && radioButtonGroup != null)
{ {
foreach (GUITickBox tickBox in radioButtonGroup) radioButtonGroup.SelectRadioButton(this);
{
if (tickBox == this) continue;
tickBox.selected = false;
tickBox.state = tickBox.box.State = ComponentState.None;
}
} }
OnSelected?.Invoke(this); OnSelected?.Invoke(this);
if (radioButtonGroup != null)
{
foreach (GUITickBox tickBox in radioButtonGroup)
{
if (tickBox == this) continue;
tickBox.OnSelected?.Invoke(tickBox);
}
}
} }
} }
@@ -123,14 +114,10 @@ namespace Barotrauma
rectT.ScaleChanged += ResizeBox; rectT.ScaleChanged += ResizeBox;
rectT.SizeChanged += ResizeBox; rectT.SizeChanged += ResizeBox;
} }
public static void CreateRadioButtonGroup(IEnumerable<GUITickBox> tickBoxes) public void SetRadioButtonGroup(GUIRadioButtonGroup rbg)
{ {
var group = new List<GUITickBox>(tickBoxes); radioButtonGroup = rbg;
foreach (GUITickBox tickBox in tickBoxes)
{
tickBox.radioButtonGroup = group;
}
} }
private void ResizeBox() private void ResizeBox()
@@ -140,8 +140,8 @@ namespace Barotrauma
} }
AfflictionAreaRight = new Rectangle(HealthBarAreaRight.X, HealthBarAreaRight.Y - Padding - afflictionAreaHeight, healthBarWidth, afflictionAreaHeight); AfflictionAreaRight = new Rectangle(HealthBarAreaRight.X, HealthBarAreaRight.Y - Padding - afflictionAreaHeight, healthBarWidth, afflictionAreaHeight);
int messageAreaPos = GameMain.GraphicsWidth - HealthBarAreaRight.X; int messageAreaWidth = GameMain.GraphicsWidth / 3;
MessageAreaTop = new Rectangle(messageAreaPos + Padding, ButtonAreaTop.Bottom, GameMain.GraphicsWidth - (messageAreaPos + Padding) * 2, ButtonAreaTop.Height); MessageAreaTop = new Rectangle((GameMain.GraphicsWidth - messageAreaWidth) / 2, ButtonAreaTop.Bottom, messageAreaWidth, ButtonAreaTop.Height);
//slice for the upper slots of the inventory (clothes, id card, headset) //slice for the upper slots of the inventory (clothes, id card, headset)
int inventoryAreaUpperWidth = (int)(GameMain.GraphicsWidth * 0.2f); int inventoryAreaUpperWidth = (int)(GameMain.GraphicsWidth * 0.2f);
@@ -1,10 +1,10 @@
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input; using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Xml.Linq; using System.Xml.Linq;
using Barotrauma.Media;
namespace Barotrauma namespace Barotrauma
{ {
@@ -14,6 +14,25 @@ namespace Barotrauma
private RenderTarget2D renderTarget; private RenderTarget2D renderTarget;
private Video splashScreen;
public Video SplashScreen
{
get
{
lock (loadMutex)
{
return splashScreen;
}
}
set
{
lock (loadMutex)
{
splashScreen = value;
}
}
}
private float state; private float state;
private string selectedTip; private string selectedTip;
@@ -22,11 +41,9 @@ namespace Barotrauma
public Vector2 TitlePosition; public Vector2 TitlePosition;
private object loadMutex = new object();
private float? loadState; private float? loadState;
#if !(LINUX || OSX)
Video splashScreenVideo;
VideoPlayer videoPlayer;
#endif
public Vector2 TitleSize public Vector2 TitleSize
{ {
get { return new Vector2(titleTexture.Width, titleTexture.Height); } get { return new Vector2(titleTexture.Width, titleTexture.Height); }
@@ -40,15 +57,20 @@ namespace Barotrauma
public float? LoadState public float? LoadState
{ {
get { return loadState; } get
{
lock (loadMutex)
{
return loadState;
}
}
set set
{ {
loadState = value; lock (loadMutex)
if (GameSettings.VerboseLogging)
{ {
DebugConsole.NewMessage("Loading: " + value.ToString() + "%", Color.Yellow); loadState = value;
DrawLoadingText = true;
} }
DrawLoadingText = true;
} }
} }
@@ -60,24 +82,6 @@ namespace Barotrauma
public LoadingScreen(GraphicsDevice graphics) public LoadingScreen(GraphicsDevice graphics)
{ {
#if !(LINUX || OSX)
if (GameMain.Config.EnableSplashScreen)
{
try
{
splashScreenVideo = GameMain.Instance.Content.Load<Video>("splashscreen");
}
catch (Exception e)
{
DebugConsole.ThrowError("Failed to load splashscreen", e);
GameMain.Config.EnableSplashScreen = false;
}
}
#endif
backgroundTexture = TextureLoader.FromFile("Content/UI/titleBackground.png"); backgroundTexture = TextureLoader.FromFile("Content/UI/titleBackground.png");
monsterTexture = TextureLoader.FromFile("Content/UI/titleMonster.png"); monsterTexture = TextureLoader.FromFile("Content/UI/titleMonster.png");
titleTexture = TextureLoader.FromFile("Content/UI/titleText.png"); titleTexture = TextureLoader.FromFile("Content/UI/titleText.png");
@@ -96,14 +100,12 @@ namespace Barotrauma
public void Draw(SpriteBatch spriteBatch, GraphicsDevice graphics, float deltaTime) public void Draw(SpriteBatch spriteBatch, GraphicsDevice graphics, float deltaTime)
{ {
#if !(LINUX || OSX) if (GameMain.Config.EnableSplashScreen)
if (GameMain.Config.EnableSplashScreen && splashScreenVideo != null)
{ {
try try
{ {
DrawSplashScreen(spriteBatch); DrawSplashScreen(spriteBatch);
if (videoPlayer != null && videoPlayer.State == MediaState.Playing) if (SplashScreen!=null && SplashScreen.IsPlaying) return;
return;
} }
catch (Exception e) catch (Exception e)
{ {
@@ -111,7 +113,6 @@ namespace Barotrauma
GameMain.Config.EnableSplashScreen = false; GameMain.Config.EnableSplashScreen = false;
} }
} }
#endif
drawn = true; drawn = true;
@@ -162,16 +163,16 @@ namespace Barotrauma
if (DrawLoadingText) if (DrawLoadingText)
{ {
string loadText = ""; string loadText = "";
if (loadState == 100.0f) if (LoadState == 100.0f)
{ {
loadText = TextManager.Get("PressAnyKey"); loadText = TextManager.Get("PressAnyKey");
} }
else else
{ {
loadText = TextManager.Get("Loading"); loadText = TextManager.Get("Loading");
if (loadState != null) if (LoadState != null)
{ {
loadText += " " + (int)loadState + " %"; loadText += " " + (int)LoadState + " %";
} }
} }
@@ -198,56 +199,27 @@ namespace Barotrauma
} }
#if !(LINUX || OSX)
private void DrawSplashScreen(SpriteBatch spriteBatch) private void DrawSplashScreen(SpriteBatch spriteBatch)
{ {
bool vsync = GameMain.Config.VSyncEnabled; if (SplashScreen != null)
if (videoPlayer == null)
{ {
// Enforce the vsync so that the video player doesn't eat all the vram if (SplashScreen.IsPlaying)
if (!GameMain.Config.VSyncEnabled)
{ {
GameMain.Config.VSyncEnabled = true;
GameMain.Instance.ApplyGraphicsSettings();
}
videoPlayer = new VideoPlayer();
videoPlayer.Play(splashScreenVideo);
videoPlayer.Volume = GameMain.Config.SoundVolume;
}
else
{
Texture2D videoTexture = null;
if (videoPlayer.State == MediaState.Stopped)
{
videoPlayer.Dispose();
videoPlayer = null;
splashScreenVideo.Dispose();
splashScreenVideo = null;
// If the vsync was enforced, restore the user preference
if (GameMain.Config.VSyncEnabled != vsync)
{
GameMain.Config.VSyncEnabled = vsync;
GameMain.Instance.ApplyGraphicsSettings();
}
}
else
{
videoTexture = videoPlayer.GetTexture();
spriteBatch.Begin(); spriteBatch.Begin();
spriteBatch.Draw(videoTexture, new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight), Color.White); spriteBatch.Draw(SplashScreen.GetTexture(), new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight), Color.White);
spriteBatch.End(); spriteBatch.End();
if (PlayerInput.KeyHit(Keys.Space) || PlayerInput.KeyHit(Keys.Enter) || PlayerInput.LeftButtonDown()) if (PlayerInput.KeyHit(Keys.Space) || PlayerInput.KeyHit(Keys.Enter) || PlayerInput.LeftButtonDown())
{ {
videoPlayer.Stop(); SplashScreen.Dispose(); SplashScreen = null;
} }
} }
} else
{
SplashScreen.Dispose(); SplashScreen = null;
}
}
} }
#endif
bool drawn; bool drawn;
public IEnumerable<object> DoLoading(IEnumerable<object> loader) public IEnumerable<object> DoLoading(IEnumerable<object> loader)
@@ -270,7 +242,7 @@ namespace Barotrauma
yield return CoroutineStatus.Running; yield return CoroutineStatus.Running;
} }
loadState = 100.0f; LoadState = 100.0f;
yield return CoroutineStatus.Success; yield return CoroutineStatus.Success;
} }
@@ -64,7 +64,7 @@ namespace Barotrauma
var length = Vector2.Distance(point1, point2); var length = Vector2.Distance(point1, point2);
var angle = (float)Math.Atan2(point2.Y - point1.Y, point2.X - point1.X); var angle = (float)Math.Atan2(point2.Y - point1.Y, point2.X - point1.X);
var scale = new Vector2(length, thickness); var scale = new Vector2(length, thickness);
spriteBatch.Draw(texture, point1, color: color, rotation: angle, scale: scale); spriteBatch.Draw(GetTexture(spriteBatch), point1, null, color, angle, Vector2.Zero, scale, SpriteEffects.None, 0);
} }
/// <summary> /// <summary>
@@ -117,7 +117,7 @@ namespace Barotrauma
{ {
var scale = Vector2.One * size; var scale = Vector2.One * size;
var offset = new Vector2(0.5f) - new Vector2(size * 0.5f); var offset = new Vector2(0.5f) - new Vector2(size * 0.5f);
spriteBatch.Draw(GetTexture(spriteBatch), position + offset, color: color, scale: scale); spriteBatch.Draw(GetTexture(spriteBatch), position + offset, null, color, 0.0f, Vector2.Zero, Vector2.One, SpriteEffects.None, 0);
} }
public static void DrawCircle(this SpriteBatch spriteBatch, Vector2 center, float radius, int sides, Color color, public static void DrawCircle(this SpriteBatch spriteBatch, Vector2 center, float radius, int sides, Color color,
+121 -93
View File
@@ -15,6 +15,7 @@ using GameAnalyticsSDK.Net;
using System.IO; using System.IO;
using System.Threading; using System.Threading;
using Barotrauma.Tutorials; using Barotrauma.Tutorials;
using Barotrauma.Media;
namespace Barotrauma namespace Barotrauma
{ {
@@ -23,7 +24,7 @@ namespace Barotrauma
public static bool ShowFPS = false; public static bool ShowFPS = false;
public static bool ShowPerf = false; public static bool ShowPerf = false;
public static bool DebugDraw; public static bool DebugDraw;
public static bool IsMultiplayer => Client != null || Server != null; public static bool IsMultiplayer => NetworkMember != null;
public static PerformanceCounter PerformanceCounter; public static PerformanceCounter PerformanceCounter;
@@ -37,10 +38,10 @@ namespace Barotrauma
public static ServerListScreen ServerListScreen; public static ServerListScreen ServerListScreen;
public static SteamWorkshopScreen SteamWorkshopScreen; public static SteamWorkshopScreen SteamWorkshopScreen;
public static SubEditorScreen SubEditorScreen; public static SubEditorScreen SubEditorScreen;
public static ParticleEditorScreen ParticleEditorScreen; public static ParticleEditorScreen ParticleEditorScreen;
public static LevelEditorScreen LevelEditorScreen; public static LevelEditorScreen LevelEditorScreen;
public static SpriteEditorScreen SpriteEditorScreen; public static SpriteEditorScreen SpriteEditorScreen;
public static CharacterEditorScreen CharacterEditorScreen; public static CharacterEditorScreen CharacterEditorScreen;
public static Lights.LightManager LightManager; public static Lights.LightManager LightManager;
@@ -60,7 +61,7 @@ namespace Barotrauma
if (vanillaContent == null) if (vanillaContent == null)
{ {
// TODO: Dynamic method for defining and finding the vanilla content package. // TODO: Dynamic method for defining and finding the vanilla content package.
vanillaContent = SelectedPackages.Single(cp => Path.GetFileName(cp.Path).ToLowerInvariant() == "vanilla 0.9.xml"); vanillaContent = SelectedPackages.SingleOrDefault(cp => Path.GetFileName(cp.Path).ToLowerInvariant() == "vanilla 0.9.xml");
} }
return vanillaContent; return vanillaContent;
} }
@@ -81,8 +82,6 @@ namespace Barotrauma
} }
} }
public static NetworkMember NetworkMember;
public static ParticleManager ParticleManager; public static ParticleManager ParticleManager;
public static DecalManager DecalManager; public static DecalManager DecalManager;
@@ -115,9 +114,7 @@ namespace Barotrauma
get; get;
private set; private set;
} }
private static bool FullscreenOnTabIn;
public static WindowMode WindowMode public static WindowMode WindowMode
{ {
get; get;
@@ -141,15 +138,13 @@ namespace Barotrauma
get { return Instance == null || Instance.IsActive; } get { return Instance == null || Instance.IsActive; }
} }
public static GameServer Server public static GameClient Client;
public static NetworkMember NetworkMember
{ {
get { return NetworkMember as GameServer; } get { return Client; }
} }
public static GameClient Client public static Process ServerChildProcess;
{
get { return NetworkMember as GameClient; }
}
public static RasterizerState ScissorTestEnable public static RasterizerState ScissorTestEnable
{ {
@@ -170,15 +165,9 @@ namespace Barotrauma
Instance = this; Instance = this;
Config = new GameSettings("config.xml"); Config = new GameSettings();
if (Config.WasGameUpdated)
{ GUI.KeyboardDispatcher = new EventInput.KeyboardDispatcher(Window);
UpdaterUtil.CleanOldFiles();
Config.WasGameUpdated = false;
Config.Save();
}
ApplyGraphicsSettings();
Content.RootDirectory = "Content"; Content.RootDirectory = "Content";
@@ -186,9 +175,9 @@ namespace Barotrauma
IsFixedTimeStep = false; IsFixedTimeStep = false;
Timing.Accumulator = 0.0f; GameMain.ResetFrameTime();
fixedTime = new GameTime(); fixedTime = new GameTime();
World = new World(new Vector2(0, -9.82f)); World = new World(new Vector2(0, -9.82f));
FarseerPhysics.Settings.AllowSleep = true; FarseerPhysics.Settings.AllowSleep = true;
FarseerPhysics.Settings.ContinuousPhysics = false; FarseerPhysics.Settings.ContinuousPhysics = false;
@@ -200,23 +189,17 @@ namespace Barotrauma
{ {
GraphicsWidth = Config.GraphicsWidth; GraphicsWidth = Config.GraphicsWidth;
GraphicsHeight = Config.GraphicsHeight; GraphicsHeight = Config.GraphicsHeight;
if (Config.WindowMode == WindowMode.BorderlessWindowed)
{
GraphicsWidth = GraphicsDevice.DisplayMode.Width;
GraphicsHeight = GraphicsDevice.DisplayMode.Height;
}
GraphicsDeviceManager.GraphicsProfile = GraphicsProfile.Reach; GraphicsDeviceManager.GraphicsProfile = GraphicsProfile.Reach;
GraphicsDeviceManager.PreferredBackBufferFormat = SurfaceFormat.Color; GraphicsDeviceManager.PreferredBackBufferFormat = SurfaceFormat.Color;
GraphicsDeviceManager.PreferMultiSampling = false; GraphicsDeviceManager.PreferMultiSampling = false;
GraphicsDeviceManager.SynchronizeWithVerticalRetrace = Config.VSyncEnabled; GraphicsDeviceManager.SynchronizeWithVerticalRetrace = Config.VSyncEnabled;
if (Config.WindowMode == WindowMode.Windowed)
{
//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.PreferredBackBufferWidth = GraphicsWidth; GraphicsDeviceManager.PreferredBackBufferWidth = GraphicsWidth;
GraphicsDeviceManager.PreferredBackBufferHeight = GraphicsHeight; GraphicsDeviceManager.PreferredBackBufferHeight = GraphicsHeight;
SetWindowMode(Config.WindowMode); SetWindowMode(Config.WindowMode);
defaultViewport = GraphicsDevice.Viewport; defaultViewport = GraphicsDevice.Viewport;
@@ -236,6 +219,9 @@ namespace Barotrauma
GraphicsDeviceManager.IsFullScreen = Config.WindowMode == WindowMode.Fullscreen || Config.WindowMode == WindowMode.BorderlessWindowed; GraphicsDeviceManager.IsFullScreen = Config.WindowMode == WindowMode.Fullscreen || Config.WindowMode == WindowMode.BorderlessWindowed;
Window.IsBorderless = !GraphicsDeviceManager.HardwareModeSwitch; Window.IsBorderless = !GraphicsDeviceManager.HardwareModeSwitch;
GraphicsDeviceManager.PreferredBackBufferWidth = GraphicsWidth;
GraphicsDeviceManager.PreferredBackBufferHeight = GraphicsHeight;
GraphicsDeviceManager.ApplyChanges(); GraphicsDeviceManager.ApplyChanges();
} }
@@ -253,7 +239,9 @@ namespace Barotrauma
protected override void Initialize() protected override void Initialize()
{ {
base.Initialize(); base.Initialize();
ApplyGraphicsSettings();
ScissorTestEnable = new RasterizerState() { ScissorTestEnable = true }; ScissorTestEnable = new RasterizerState() { ScissorTestEnable = true };
Hyper.ComponentModel.HyperTypeDescriptionProvider.Add(typeof(Character)); Hyper.ComponentModel.HyperTypeDescriptionProvider.Add(typeof(Character));
@@ -270,7 +258,7 @@ namespace Barotrauma
{ {
GraphicsWidth = GraphicsDevice.Viewport.Width; GraphicsWidth = GraphicsDevice.Viewport.Width;
GraphicsHeight = GraphicsDevice.Viewport.Height; GraphicsHeight = GraphicsDevice.Viewport.Height;
ConvertUnits.SetDisplayUnitToSimUnitRatio(Physics.DisplayToSimRation); ConvertUnits.SetDisplayUnitToSimUnitRatio(Physics.DisplayToSimRation);
spriteBatch = new SpriteBatch(GraphicsDevice); spriteBatch = new SpriteBatch(GraphicsDevice);
@@ -279,39 +267,14 @@ namespace Barotrauma
loadingScreenOpen = true; loadingScreenOpen = true;
TitleScreen = new LoadingScreen(GraphicsDevice); TitleScreen = new LoadingScreen(GraphicsDevice);
loadingCoroutine = CoroutineManager.StartCoroutine(Load()); bool canLoadInSeparateThread = false;
#if WINDOWS #if WINDOWS
var myForm = (System.Windows.Forms.Form)System.Windows.Forms.Form.FromHandle(Window.Handle); canLoadInSeparateThread = true;
myForm.Deactivate += new EventHandler(HandleDefocus);
myForm.Activated += new EventHandler(HandleFocus);
#endif #endif
loadingCoroutine = CoroutineManager.StartCoroutine(Load(), "", canLoadInSeparateThread);
} }
private void HandleDefocus(object sender, EventArgs e)
{
if (GraphicsDeviceManager.IsFullScreen && GraphicsDeviceManager.HardwareModeSwitch)
{
GraphicsDeviceManager.IsFullScreen = false;
GraphicsDeviceManager.ApplyChanges();
FullscreenOnTabIn = true;
Thread.Sleep(500);
}
}
private void HandleFocus(object sender, EventArgs e)
{
if (FullscreenOnTabIn)
{
GraphicsDeviceManager.HardwareModeSwitch = true;
GraphicsDeviceManager.IsFullScreen = true;
GraphicsDeviceManager.ApplyChanges();
FullscreenOnTabIn = false;
Thread.Sleep(500);
}
}
private void InitUserStats() private void InitUserStats()
{ {
if (GameSettings.ShowUserStatisticsPrompt) if (GameSettings.ShowUserStatisticsPrompt)
@@ -326,6 +289,7 @@ namespace Barotrauma
GameSettings.ShowUserStatisticsPrompt = false; GameSettings.ShowUserStatisticsPrompt = false;
GameSettings.SendUserStatistics = true; GameSettings.SendUserStatistics = true;
GameAnalyticsManager.Init(); GameAnalyticsManager.Init();
Config.SaveNewPlayerConfig();
return true; return true;
}; };
userStatsPrompt.Buttons[0].OnClicked += userStatsPrompt.Close; userStatsPrompt.Buttons[0].OnClicked += userStatsPrompt.Close;
@@ -333,6 +297,7 @@ namespace Barotrauma
{ {
GameSettings.ShowUserStatisticsPrompt = false; GameSettings.ShowUserStatisticsPrompt = false;
GameSettings.SendUserStatistics = false; GameSettings.SendUserStatistics = false;
Config.SaveNewPlayerConfig();
return true; return true;
}; };
userStatsPrompt.Buttons[1].OnClicked += userStatsPrompt.Close; userStatsPrompt.Buttons[1].OnClicked += userStatsPrompt.Close;
@@ -349,17 +314,29 @@ namespace Barotrauma
{ {
DebugConsole.NewMessage("LOADING COROUTINE", Color.Lime); DebugConsole.NewMessage("LOADING COROUTINE", Color.Lime);
} }
SoundManager = new Sounds.SoundManager(); SoundManager = new Sounds.SoundManager();
SoundManager.SetCategoryGainMultiplier("default", Config.SoundVolume); SoundManager.SetCategoryGainMultiplier("default", Config.SoundVolume);
SoundManager.SetCategoryGainMultiplier("ui", Config.SoundVolume); SoundManager.SetCategoryGainMultiplier("ui", Config.SoundVolume);
SoundManager.SetCategoryGainMultiplier("waterambience", Config.SoundVolume); SoundManager.SetCategoryGainMultiplier("waterambience", Config.SoundVolume);
SoundManager.SetCategoryGainMultiplier("music", Config.MusicVolume); SoundManager.SetCategoryGainMultiplier("music", Config.MusicVolume);
if (Config.EnableSplashScreen)
{
(TitleScreen as LoadingScreen).SplashScreen = new Video(base.GraphicsDevice, SoundManager, "Content/splashscreen.mp4", 1280, 720);
}
GUI.Init(Window, Config.SelectedContentPackages, GraphicsDevice); GUI.Init(Window, Config.SelectedContentPackages, GraphicsDevice);
DebugConsole.Init(); DebugConsole.Init();
SteamManager.Initialize(); SteamManager.Initialize();
if (Config.AutoUpdateWorkshopItems)
{
if (SteamManager.AutoUpdateWorkshopItems())
{
ContentPackage.LoadAll(ContentPackage.Folder);
Config.ReloadContentPackages();
}
}
if (SelectedPackages.Count == 0) if (SelectedPackages.Count == 0)
{ {
@@ -370,10 +347,16 @@ namespace Barotrauma
DebugConsole.Log("Selected content packages: " + string.Join(", ", SelectedPackages.Select(cp => cp.Name))); DebugConsole.Log("Selected content packages: " + string.Join(", ", SelectedPackages.Select(cp => cp.Name)));
} }
#if DEBUG
GameSettings.ShowUserStatisticsPrompt = false;
GameSettings.SendUserStatistics = false;
#endif
InitUserStats(); InitUserStats();
yield return CoroutineStatus.Running; yield return CoroutineStatus.Running;
LightManager = new Lights.LightManager(base.GraphicsDevice, Content); LightManager = new Lights.LightManager(base.GraphicsDevice, Content);
WaterRenderer.Instance = new WaterRenderer(base.GraphicsDevice, Content); WaterRenderer.Instance = new WaterRenderer(base.GraphicsDevice, Content);
@@ -382,6 +365,7 @@ namespace Barotrauma
GUI.LoadContent(); GUI.LoadContent();
TitleScreen.LoadState = 2.0f; TitleScreen.LoadState = 2.0f;
yield return CoroutineStatus.Running; yield return CoroutineStatus.Running;
MissionPrefab.Init(); MissionPrefab.Init();
@@ -416,20 +400,18 @@ namespace Barotrauma
yield return CoroutineStatus.Running; yield return CoroutineStatus.Running;
Debug.WriteLine("sounds"); Debug.WriteLine("sounds");
var soundLoadingCoroutine = CoroutineManager.StartCoroutine(SoundPlayer.Init());
int i = 0; int i = 0;
while (!SoundPlayer.Initialized) foreach (object crObj in SoundPlayer.Init())
{ {
if (soundLoadingCoroutine.Exception != null) CoroutineStatus status = (CoroutineStatus)crObj;
{ if (status == CoroutineStatus.Success) break;
throw soundLoadingCoroutine.Exception;
}
i++; i++;
TitleScreen.LoadState = SoundPlayer.SoundCount == 0 ? TitleScreen.LoadState = SoundPlayer.SoundCount == 0 ?
30.0f : 30.0f :
Math.Min(30.0f + 40.0f * i / Math.Max(SoundPlayer.SoundCount, 1), 70.0f); Math.Min(30.0f + 40.0f * i / Math.Max(SoundPlayer.SoundCount, 1), 70.0f);
yield return CoroutineStatus.Running; yield return CoroutineStatus.Running;
} }
@@ -439,15 +421,19 @@ namespace Barotrauma
GameModePreset.Init(); GameModePreset.Init();
Submarine.RefreshSavedSubs(); Submarine.RefreshSavedSubs();
TitleScreen.LoadState = 80.0f; TitleScreen.LoadState = 80.0f;
yield return CoroutineStatus.Running; yield return CoroutineStatus.Running;
GameScreen = new GameScreen(GraphicsDeviceManager.GraphicsDevice, Content); GameScreen = new GameScreen(GraphicsDeviceManager.GraphicsDevice, Content);
TitleScreen.LoadState = 90.0f; TitleScreen.LoadState = 90.0f;
yield return CoroutineStatus.Running; yield return CoroutineStatus.Running;
MainMenuScreen = new MainMenuScreen(this); MainMenuScreen = new MainMenuScreen(this);
LobbyScreen = new LobbyScreen(); LobbyScreen = new LobbyScreen();
ServerListScreen = new ServerListScreen(); ServerListScreen = new ServerListScreen();
if (SteamManager.USE_STEAM) if (SteamManager.USE_STEAM)
@@ -463,10 +449,13 @@ namespace Barotrauma
yield return CoroutineStatus.Running; yield return CoroutineStatus.Running;
TitleScreen.LoadState = 95.0f;
ParticleManager = new ParticleManager(GameScreen.Cam); ParticleManager = new ParticleManager(GameScreen.Cam);
ParticleManager.LoadPrefabs(); ParticleManager.LoadPrefabs();
TitleScreen.LoadState = 97.0f;
LevelObjectPrefab.LoadAll(); LevelObjectPrefab.LoadAll();
DecalManager = new DecalManager(); DecalManager = new DecalManager();
TitleScreen.LoadState = 99.0f;
yield return CoroutineStatus.Running; yield return CoroutineStatus.Running;
LocationType.Init(); LocationType.Init();
@@ -489,7 +478,7 @@ namespace Barotrauma
foreach (ContentPackage contentPackage in Config.SelectedContentPackages) foreach (ContentPackage contentPackage in Config.SelectedContentPackages)
{ {
var exePaths = contentPackage.GetFilesOfType(ContentType.Executable); var exePaths = contentPackage.GetFilesOfType(ContentType.Executable);
if (exePaths.Count() > 0 && AppDomain.CurrentDomain.FriendlyName != exePaths.First()) if (exePaths.Any() && AppDomain.CurrentDomain.FriendlyName != exePaths.First())
{ {
var msgBox = new GUIMessageBox(TextManager.Get("Error"), var msgBox = new GUIMessageBox(TextManager.Get("Error"),
TextManager.Get("IncorrectExe") TextManager.Get("IncorrectExe")
@@ -515,6 +504,7 @@ namespace Barotrauma
/// </summary> /// </summary>
protected override void UnloadContent() protected override void UnloadContent()
{ {
Video.Close();
SoundManager.Dispose(); SoundManager.Dispose();
} }
@@ -525,7 +515,7 @@ namespace Barotrauma
{ {
return ContentPackage.GetFilesOfType(SelectedPackages, type); return ContentPackage.GetFilesOfType(SelectedPackages, type);
} }
/// <summary> /// <summary>
/// Allows the game to run logic such as updating the world, /// Allows the game to run logic such as updating the world,
/// checking for collisions, gathering input, and playing audio. /// checking for collisions, gathering input, and playing audio.
@@ -547,6 +537,18 @@ namespace Barotrauma
bool paused = true; bool paused = true;
if (SoundManager != null)
{
if (WindowActive || !Config.MuteOnFocusLost)
{
SoundManager.ListenerGain = 1.0f;
}
else
{
SoundManager.ListenerGain = 0.0f;
}
}
while (Timing.Accumulator >= Timing.Step) while (Timing.Accumulator >= Timing.Step)
{ {
Stopwatch sw = new Stopwatch(); Stopwatch sw = new Stopwatch();
@@ -557,17 +559,17 @@ namespace Barotrauma
fixedTime.ElapsedGameTime = addTime; fixedTime.ElapsedGameTime = addTime;
fixedTime.TotalGameTime.Add(addTime); fixedTime.TotalGameTime.Add(addTime);
base.Update(fixedTime); base.Update(fixedTime);
PlayerInput.Update(Timing.Step); PlayerInput.Update(Timing.Step);
if (loadingScreenOpen) if (loadingScreenOpen)
{ {
//reset accumulator if loading //reset accumulator if loading
// -> less choppy loading screens because the screen is rendered after each update // -> less choppy loading screens because the screen is rendered after each update
// -> no pause caused by leftover time in the accumulator when starting a new shift // -> no pause caused by leftover time in the accumulator when starting a new shift
Timing.Accumulator = 0.0f; GameMain.ResetFrameTime();
if (TitleScreen.LoadState >= 100.0f && if (TitleScreen.LoadState >= 100.0f &&
(!waitForKeyHit || PlayerInput.GetKeyboardState.GetPressedKeys().Length>0 || PlayerInput.LeftButtonClicked())) (!waitForKeyHit || PlayerInput.GetKeyboardState.GetPressedKeys().Length>0 || PlayerInput.LeftButtonClicked()))
{ {
loadingScreenOpen = false; loadingScreenOpen = false;
@@ -587,7 +589,28 @@ namespace Barotrauma
{ {
SoundPlayer.Update((float)Timing.Step); SoundPlayer.Update((float)Timing.Step);
if (PlayerInput.KeyHit(Keys.Escape)) GUI.TogglePauseMenu(); if (PlayerInput.KeyHit(Keys.Escape))
{
// Check if a text input is selected.
if (GUI.KeyboardDispatcher.Subscriber != null)
{
if (GUI.KeyboardDispatcher.Subscriber is GUITextBox textBox)
{
textBox.Deselect();
}
GUI.KeyboardDispatcher.Subscriber = null;
}
//if a verification prompt (are you sure you want to x) is open, close it
else if (GUIMessageBox.VisibleBox as GUIMessageBox != null &&
GUIMessageBox.VisibleBox.UserData as string == "verificationprompt")
{
((GUIMessageBox)GUIMessageBox.VisibleBox).Close();
}
else // Otherwise toggle pausing.
{
GUI.TogglePauseMenu();
}
}
GUI.ClearUpdateList(); GUI.ClearUpdateList();
paused = (DebugConsole.IsOpen || GUI.PauseMenuOpen || GUI.SettingsMenuOpen || ContextualTutorial.ContentRunning) && paused = (DebugConsole.IsOpen || GUI.PauseMenuOpen || GUI.SettingsMenuOpen || ContextualTutorial.ContentRunning) &&
@@ -595,16 +618,16 @@ namespace Barotrauma
Screen.Selected.AddToGUIUpdateList(); Screen.Selected.AddToGUIUpdateList();
if (NetworkMember != null) if (Client != null)
{ {
NetworkMember.AddToGUIUpdateList(); Client.AddToGUIUpdateList();
} }
DebugConsole.AddToGUIUpdateList(); DebugConsole.AddToGUIUpdateList();
DebugConsole.Update(this, (float)Timing.Step); DebugConsole.Update(this, (float)Timing.Step);
paused = paused || (DebugConsole.IsOpen && (NetworkMember == null || !NetworkMember.GameStarted)); paused = paused || (DebugConsole.IsOpen && (NetworkMember == null || !NetworkMember.GameStarted));
if (!paused) if (!paused)
{ {
Screen.Selected.Update(Timing.Step); Screen.Selected.Update(Timing.Step);
@@ -637,6 +660,10 @@ namespace Barotrauma
if (!paused) Timing.Alpha = Timing.Accumulator / Timing.Step; if (!paused) Timing.Alpha = Timing.Accumulator / Timing.Step;
} }
public static void ResetFrameTime()
{
Timing.Accumulator = 0.0f;
}
/// <summary> /// <summary>
/// This is called when the game should draw itself. /// This is called when the game should draw itself.
@@ -666,6 +693,7 @@ namespace Barotrauma
spriteBatch.End(); spriteBatch.End();
} }
sw.Stop(); sw.Stop();
PerformanceCounter.AddElapsedTicks("Draw total", sw.ElapsedTicks); PerformanceCounter.AddElapsedTicks("Draw total", sw.ElapsedTicks);
PerformanceCounter.DrawTimeGraph.Update(sw.ElapsedTicks / (float)TimeSpan.TicksPerMillisecond); PerformanceCounter.DrawTimeGraph.Update(sw.ElapsedTicks / (float)TimeSpan.TicksPerMillisecond);
@@ -4,6 +4,7 @@ using Barotrauma.Networking;
using FarseerPhysics; using FarseerPhysics;
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
@@ -25,10 +26,7 @@ namespace Barotrauma
private List<Character> characters = new List<Character>(); private List<Character> characters = new List<Character>();
private Point screenResolution; private Point screenResolution;
public int WinningTeam = 1;
#region UI #region UI
private GUIFrame guiFrame; private GUIFrame guiFrame;
@@ -47,7 +45,7 @@ namespace Barotrauma
private ChatBox chatBox; private ChatBox chatBox;
private float prevUIScale; private float prevUIScale;
private GUIComponent orderTargetFrame, orderTargetFrameShadow; private GUIComponent orderTargetFrame, orderTargetFrameShadow;
public bool ToggleCrewAreaOpen public bool ToggleCrewAreaOpen
@@ -76,6 +74,20 @@ namespace Barotrauma
break; break;
} }
} }
screenResolution = new Point(GameMain.GraphicsWidth, GameMain.GraphicsHeight);
prevUIScale = GUI.Scale;
}
#endregion
#region Character list management
public Rectangle GetCharacterListArea()
{
return characterListBox.Rect;
} }
partial void InitProjectSpecific() partial void InitProjectSpecific()
@@ -144,11 +156,20 @@ namespace Barotrauma
msg, msg,
((msgCommand == "r" || msgCommand == "radio") && ChatMessage.CanUseRadio(Character.Controlled)) ? ChatMessageType.Radio : ChatMessageType.Default, ((msgCommand == "r" || msgCommand == "radio") && ChatMessage.CanUseRadio(Character.Controlled)) ? ChatMessageType.Radio : ChatMessageType.Default,
Character.Controlled); Character.Controlled);
var headset = GetHeadset(Character.Controlled, true);
if (headset != null && headset.CanTransmit())
{
headset.TransmitSignal(stepsTaken: 0, signal: msg, source: headset.Item, sender: Character.Controlled, sendToChat: false);
}
} }
textbox.Deselect(); textbox.Deselect();
textbox.Text = ""; textbox.Text = "";
return true; return true;
} }
};
chatBox.InputBox.OnDeselected += (gui, Keys) =>
{
this.chatBox.InputBox.Text = "";
}; };
chatBox.InputBox.OnTextChanged += chatBox.TypingChatMessage; chatBox.InputBox.OnTextChanged += chatBox.TypingChatMessage;
} }
@@ -328,7 +349,7 @@ namespace Barotrauma
int spacing = (int)(10 * GUI.Scale); int spacing = (int)(10 * GUI.Scale);
int height = (int)(45 * GUI.Scale); int height = (int)(45 * GUI.Scale);
characterInfoWidth = (int)(170 * GUI.Scale); characterInfoWidth = (int)(200 * GUI.Scale);
float charactersPerView = characterListBox.Rect.Height / (float)(height + characterListBox.Spacing); float charactersPerView = characterListBox.Rect.Height / (float)(height + characterListBox.Spacing);
@@ -341,6 +362,7 @@ namespace Barotrauma
int iconSize = (int)(height * 0.8f); int iconSize = (int)(height * 0.8f);
var frame = new GUIFrame(new RectTransform(new Point(GameMain.GraphicsWidth, height), parent.RectTransform), style: "InnerFrame") var frame = new GUIFrame(new RectTransform(new Point(GameMain.GraphicsWidth, height), parent.RectTransform), style: "InnerFrame")
{ {
UserData = character, UserData = character,
@@ -349,7 +371,16 @@ namespace Barotrauma
frame.Color = character.Info.Job.Prefab.UIColor; frame.Color = character.Info.Job.Prefab.UIColor;
frame.SelectedColor = Color.Lerp(frame.Color, Color.White, 0.5f); frame.SelectedColor = Color.Lerp(frame.Color, Color.White, 0.5f);
frame.HoverColor = Color.Lerp(frame.Color, Color.White, 0.9f); frame.HoverColor = Color.Lerp(frame.Color, Color.White, 0.9f);
new GUIFrame(new RectTransform(new Point(characterInfoWidth, (int)(frame.Rect.Height * 1.3f)), frame.RectTransform, Anchor.CenterLeft), style: "OuterGlow")
{
UserData = "highlight",
Color = frame.SelectedColor,
HoverColor = frame.SelectedColor,
PressedColor = frame.SelectedColor,
SelectedColor = frame.SelectedColor,
CanBeFocused = false
};
//---------------- character area ---------------- //---------------- character area ----------------
string characterToolTip = character.Info.Name; string characterToolTip = character.Info.Name;
@@ -365,6 +396,23 @@ namespace Barotrauma
HoverColor = frame.HoverColor, HoverColor = frame.HoverColor,
ToolTip = characterToolTip ToolTip = characterToolTip
}; };
var soundIcon = new GUIImage(new RectTransform(new Point((int)(characterArea.Rect.Height * 0.5f)), characterArea.RectTransform, Anchor.CenterRight) { AbsoluteOffset = new Point(5, 0) },
"GUISoundIcon")
{
UserData = "soundicon",
CanBeFocused = false,
Visible = true
};
soundIcon.Color = new Color(soundIcon.Color, 0.0f);
new GUIImage(new RectTransform(new Point((int)(characterArea.Rect.Height * 0.5f)), characterArea.RectTransform, Anchor.CenterRight) { AbsoluteOffset = new Point(5, 0) },
"GUISoundIconDisabled")
{
UserData = "soundicondisabled",
CanBeFocused = true,
Visible = false
};
if (isSinglePlayer) if (isSinglePlayer)
{ {
characterArea.OnClicked = CharacterClicked; characterArea.OnClicked = CharacterClicked;
@@ -375,7 +423,7 @@ namespace Barotrauma
characterArea.CanBeSelected = false; characterArea.CanBeSelected = false;
} }
var characterImage = new GUICustomComponent(new RectTransform(new Point(characterArea.Rect.Height, characterArea.Rect.Height), characterArea.RectTransform, Anchor.CenterLeft), var characterImage = new GUICustomComponent(new RectTransform(new Point(characterArea.Rect.Height), characterArea.RectTransform, Anchor.CenterLeft),
onDraw: (sb, component) => character.Info.DrawIcon(sb, component.Rect.Center.ToVector2(), targetAreaSize: component.Rect.Size.ToVector2())) onDraw: (sb, component) => character.Info.DrawIcon(sb, component.Rect.Center.ToVector2(), targetAreaSize: component.Rect.Size.ToVector2()))
{ {
CanBeFocused = false, CanBeFocused = false,
@@ -384,7 +432,8 @@ namespace Barotrauma
ToolTip = characterToolTip ToolTip = characterToolTip
}; };
var characterName = new GUITextBlock(new RectTransform(new Point(characterArea.Rect.Width - characterImage.Rect.Width, characterArea.Rect.Height), characterArea.RectTransform, Anchor.CenterRight), var characterName = new GUITextBlock(new RectTransform(new Point(characterArea.Rect.Width - characterImage.Rect.Width - soundIcon.Rect.Width - 10, characterArea.Rect.Height),
characterArea.RectTransform, Anchor.CenterRight) { AbsoluteOffset = new Point(soundIcon.Rect.Width + 10, 0) },
character.Name, textColor: frame.Color, font: GUI.SmallFont, wrap: true) character.Name, textColor: frame.Color, font: GUI.SmallFont, wrap: true)
{ {
Color = frame.Color, Color = frame.Color,
@@ -423,8 +472,8 @@ namespace Barotrauma
var order = orders[i]; var order = orders[i];
if (order.TargetAllCharacters) continue; if (order.TargetAllCharacters) continue;
RectTransform btnParent = (i >= correctOrderCount + neutralOrderCount) ? RectTransform btnParent = (i >= correctOrderCount + neutralOrderCount) ?
wrongOrderList.Content.RectTransform : wrongOrderList.Content.RectTransform :
orderButtonFrame.RectTransform; orderButtonFrame.RectTransform;
var btn = new GUIButton(new RectTransform(new Point(iconSize, iconSize), btnParent, Anchor.CenterLeft), var btn = new GUIButton(new RectTransform(new Point(iconSize, iconSize), btnParent, Anchor.CenterLeft),
@@ -445,11 +494,11 @@ namespace Barotrauma
img.Color = Color.Lerp(order.Color, frame.Color, 0.5f); img.Color = Color.Lerp(order.Color, frame.Color, 0.5f);
img.ToolTip = order.Name; img.ToolTip = order.Name;
img.HoverColor = Color.Lerp(img.Color, Color.White, 0.5f); img.HoverColor = Color.Lerp(img.Color, Color.White, 0.5f);
btn.OnClicked += (GUIButton button, object userData) => btn.OnClicked += (GUIButton button, object userData) =>
{ {
if (Character.Controlled == null || Character.Controlled.SpeechImpediment >= 100.0f) return false; if (Character.Controlled == null || Character.Controlled.SpeechImpediment >= 100.0f) return false;
if (btn.GetChildByUserData("selected").Visible) if (btn.GetChildByUserData("selected").Visible)
{ {
SetCharacterOrder(character, Order.PrefabList.Find(o => o.AITag == "dismissed"), null, Character.Controlled); SetCharacterOrder(character, Order.PrefabList.Find(o => o.AITag == "dismissed"), null, Character.Controlled);
@@ -526,23 +575,6 @@ namespace Barotrauma
return true; return true;
} }
/// <summary>
/// Sets which character is selected in the crew UI (highlight effect etc)
/// </summary>
public void SetCharacterSelected(Character character)
{
if (character != null && !characters.Contains(character)) return;
//GUIComponent selectedCharacterFrame = null;
foreach (GUIComponent child in characterListBox.Content.Children)
{
GUIButton button = child.Children.FirstOrDefault(c => c.UserData is Character) as GUIButton;
if (button == null) continue;
child.Visible = (Character)button.UserData != character;
}
}
public void ReviveCharacter(Character revivedCharacter) public void ReviveCharacter(Character revivedCharacter)
{ {
if (characterListBox.Content.GetChildByUserData(revivedCharacter) is GUIComponent characterBlock) if (characterListBox.Content.GetChildByUserData(revivedCharacter) is GUIComponent characterBlock)
@@ -566,13 +598,14 @@ namespace Barotrauma
if (characterListBox.Content.CountChildren == 0) return false; if (characterListBox.Content.CountChildren == 0) return false;
int dir = (int)obj; int dir = (int)obj;
float step = float step =
(characterListBox.Content.Children.First().Rect.Height + characterListBox.Spacing) / (characterListBox.Content.Children.First().Rect.Height + characterListBox.Spacing) /
(characterListBox.TotalSize - characterListBox.Rect.Height); (characterListBox.TotalSize - characterListBox.Rect.Height);
characterListBox.BarScroll -= characterListBox.BarScroll % step; characterListBox.BarScroll -= characterListBox.BarScroll % step;
characterListBox.BarScroll += dir * step; characterListBox.BarScroll += dir * step;
return false; child.Visible = (Character)button.UserData != character;
}
} }
private IEnumerable<object> KillCharacterAnim(GUIComponent component) private IEnumerable<object> KillCharacterAnim(GUIComponent component)
@@ -583,6 +616,8 @@ namespace Barotrauma
{ {
comp.Color = Color.DarkRed; comp.Color = Color.DarkRed;
} }
if (characterInfos.Contains(revivedCharacter.Info)) AddCharacter(revivedCharacter);
}
yield return new WaitForSeconds(1.0f); yield return new WaitForSeconds(1.0f);
@@ -606,7 +641,6 @@ namespace Barotrauma
#endregion #endregion
#region Dialog #region Dialog
/// <summary> /// <summary>
/// Adds the message to the single player chatbox. /// Adds the message to the single player chatbox.
/// </summary> /// </summary>
@@ -617,6 +651,7 @@ namespace Barotrauma
DebugConsole.ThrowError("Cannot add messages to single player chat box in multiplayer mode!\n" + Environment.StackTrace); DebugConsole.ThrowError("Cannot add messages to single player chat box in multiplayer mode!\n" + Environment.StackTrace);
return; return;
} }
if (string.IsNullOrEmpty(text)) { return; }
chatBox.AddMessage(ChatMessage.Create(senderName, text, messageType, sender)); chatBox.AddMessage(ChatMessage.Create(senderName, text, messageType, sender));
} }
@@ -632,6 +667,52 @@ namespace Barotrauma
return radioItem.GetComponent<WifiComponent>(); return radioItem.GetComponent<WifiComponent>();
} }
partial void CreateRandomConversation()
{
if (GameMain.Client != null)
{
//let the server create random conversations in MP
return;
}
List<Character> availableSpeakers = Character.CharacterList.FindAll(c =>
c.AIController is HumanAIController &&
!c.IsDead &&
c.SpeechImpediment <= 100.0f);
pendingConversationLines.AddRange(NPCConversation.CreateRandom(availableSpeakers));
}
#endregion
#region Voice chat
public void SetPlayerVoiceIconState(Client client, bool muted, bool mutedLocally)
{
if (client?.Character == null) { return; }
var playerFrame = characterListBox.Content.FindChild(client.Character)?.FindChild(client.Character);
if (playerFrame == null) { return; }
var soundIcon = playerFrame.FindChild("soundicon");
var soundIconDisabled = playerFrame.FindChild("soundicondisabled");
if (!soundIcon.Visible)
{
soundIcon.Color = new Color(soundIcon.Color, 0.0f);
}
soundIcon.Visible = !muted && !mutedLocally;
soundIconDisabled.Visible = muted || mutedLocally;
soundIconDisabled.ToolTip = TextManager.Get(mutedLocally ? "MutedLocally" : "MutedGlobally");
}
public void SetPlayerSpeaking(Client client)
{
if (client?.Character == null) { return; }
var playerFrame = characterListBox.Content.FindChild(client.Character)?.FindChild(client.Character);
if (playerFrame == null) { return; }
var soundIcon = playerFrame.FindChild("soundicon");
soundIcon.Color = new Color(soundIcon.Color, 1.0f);
}
#endregion #endregion
/// <summary> /// <summary>
@@ -648,7 +729,7 @@ namespace Barotrauma
if (IsSinglePlayer) if (IsSinglePlayer)
{ {
orderGiver.Speak( orderGiver.Speak(
order.GetChatMessage("", orderGiver.CurrentHull?.RoomName), ChatMessageType.Order); order.GetChatMessage("", orderGiver.CurrentHull?.RoomName, givingOrderToSelf: character == orderGiver), ChatMessageType.Order);
} }
else else
{ {
@@ -657,19 +738,15 @@ namespace Barotrauma
{ {
GameMain.Client.SendChatMessage(msg); GameMain.Client.SendChatMessage(msg);
} }
else if (GameMain.Server != null)
{
GameMain.Server.SendOrderChatMessage(msg);
}
} }
return; return;
} }
character.SetOrder(order, option, orderGiver); character.SetOrder(order, option, orderGiver, speak: orderGiver != character);
if (IsSinglePlayer) if (IsSinglePlayer)
{ {
orderGiver?.Speak( orderGiver?.Speak(
order.GetChatMessage(character.Name, orderGiver.CurrentHull?.RoomName, option), null); order.GetChatMessage(character.Name, orderGiver.CurrentHull?.RoomName, givingOrderToSelf: character == orderGiver, orderOption: option), null);
} }
else if (orderGiver != null) else if (orderGiver != null)
{ {
@@ -678,16 +755,12 @@ namespace Barotrauma
{ {
GameMain.Client.SendChatMessage(msg); GameMain.Client.SendChatMessage(msg);
} }
else if (GameMain.Server != null)
{
GameMain.Server.SendOrderChatMessage(msg);
}
} }
DisplayCharacterOrder(character, order); DisplayCharacterOrder(character, order);
} }
/// <summary> /// <summary>
/// Displays the specified order in the crew UI next to the character. /// Displays the specified order in the crew UI next to the character.
/// </summary> /// </summary>
public void DisplayCharacterOrder(Character character, Order order) public void DisplayCharacterOrder(Character character, Order order)
{ {
@@ -697,7 +770,7 @@ namespace Barotrauma
if (characterFrame == null) continue; if (characterFrame == null) continue;
var orderButtonFrame = characterListElement.GetChildByUserData("orderbuttons"); var orderButtonFrame = characterListElement.GetChildByUserData("orderbuttons");
//get all order buttons from the frame //get all order buttons from the frame
List<GUIButton> orderButtons = new List<GUIButton>(); List<GUIButton> orderButtons = new List<GUIButton>();
foreach (GUIComponent child in orderButtonFrame.Children) foreach (GUIComponent child in orderButtonFrame.Children)
@@ -728,13 +801,13 @@ namespace Barotrauma
} }
/// <summary> /// <summary>
/// Create the UI panel that's used to select the target and options for a given order /// Create the UI panel that's used to select the target and options for a given order
/// (which railgun to use, whether to power up the reactor or shut it down...) /// (which railgun to use, whether to power up the reactor or shut it down...)
/// </summary> /// </summary>
private void CreateOrderTargetFrame(GUIComponent orderButton, Character character, Order order) private void CreateOrderTargetFrame(GUIComponent orderButton, Character character, Order order)
{ {
Submarine submarine = Character.Controlled != null && Character.Controlled.TeamID > 1 && Submarine.MainSubs.Length > 1 ? Submarine submarine = Character.Controlled != null && Character.Controlled.TeamID == Character.TeamType.Team2 && Submarine.MainSubs.Length > 1 ?
Submarine.MainSubs[1] : Submarine.MainSubs[1] :
Submarine.MainSub; Submarine.MainSub;
List<Item> matchingItems = new List<Item>(); List<Item> matchingItems = new List<Item>();
@@ -742,12 +815,12 @@ namespace Barotrauma
{ {
matchingItems = order.ItemIdentifiers.Length > 0 ? matchingItems = order.ItemIdentifiers.Length > 0 ?
Item.ItemList.FindAll(it => order.ItemIdentifiers.Contains(it.Prefab.Identifier) || it.HasTag(order.ItemIdentifiers)) : Item.ItemList.FindAll(it => order.ItemIdentifiers.Contains(it.Prefab.Identifier) || it.HasTag(order.ItemIdentifiers)) :
Item.ItemList.FindAll(it => it.components.Any(ic => ic.GetType() == order.ItemComponentType)); Item.ItemList.FindAll(it => it.Components.Any(ic => ic.GetType() == order.ItemComponentType));
matchingItems.RemoveAll(it => it.Submarine != submarine && !submarine.DockedTo.Contains(it.Submarine)); matchingItems.RemoveAll(it => it.Submarine != submarine && !submarine.DockedTo.Contains(it.Submarine));
matchingItems.RemoveAll(it => it.Submarine != null && it.Submarine.IsOutpost); matchingItems.RemoveAll(it => it.Submarine != null && it.Submarine.IsOutpost);
} }
//more than one target item -> create a minimap-like selection with a pic of the sub //more than one target item -> create a minimap-like selection with a pic of the sub
if (matchingItems.Count > 1) if (matchingItems.Count > 1)
{ {
@@ -819,7 +892,7 @@ namespace Barotrauma
var optionButton = new GUIButton(new RectTransform(new Vector2(1.0f, 0.2f), optionContainer.RectTransform), var optionButton = new GUIButton(new RectTransform(new Vector2(1.0f, 0.2f), optionContainer.RectTransform),
order.OptionNames[i], style: "GUITextBox") order.OptionNames[i], style: "GUITextBox")
{ {
UserData = item == null ? order : new Order(order, item, item.components.Find(ic => ic.GetType() == order.ItemComponentType)), UserData = item == null ? order : new Order(order, item, item.Components.FirstOrDefault(ic => ic.GetType() == order.ItemComponentType)),
Font = GUI.SmallFont, Font = GUI.SmallFont,
OnClicked = (btn, userData) => OnClicked = (btn, userData) =>
{ {
@@ -847,7 +920,7 @@ namespace Barotrauma
//line connecting the order button to the option buttons //line connecting the order button to the option buttons
//TODO: sprite //TODO: sprite
new GUIFrame(new RectTransform(new Vector2(0.5f, 1.0f), orderTargetFrame.RectTransform), style: null); new GUIFrame(new RectTransform(new Vector2(0.5f, 1.0f), orderTargetFrame.RectTransform), style: null);
for (int i = 0; i < order.Options.Length; i++) for (int i = 0; i < order.Options.Length; i++)
{ {
Item item = matchingItems.Count > 0 ? matchingItems[0] : null; Item item = matchingItems.Count > 0 ? matchingItems[0] : null;
@@ -855,7 +928,7 @@ namespace Barotrauma
var optionButton = new GUIButton(new RectTransform(new Vector2(0.5f, 0.5f), orderTargetFrame.RectTransform), var optionButton = new GUIButton(new RectTransform(new Vector2(0.5f, 0.5f), orderTargetFrame.RectTransform),
order.OptionNames[i], style: "GUITextBox") order.OptionNames[i], style: "GUITextBox")
{ {
UserData = item == null ? order : new Order(order, item, item.components.Find(ic => ic.GetType() == order.ItemComponentType)), UserData = item == null ? order : new Order(order, item, item.Components.FirstOrDefault(ic => ic.GetType() == order.ItemComponentType)),
OnClicked = (btn, userData) => OnClicked = (btn, userData) =>
{ {
if (Character.Controlled == null) return false; if (Character.Controlled == null) return false;
@@ -874,11 +947,13 @@ namespace Barotrauma
} }
int shadowSize = (int)(200 * GUI.Scale); int shadowSize = (int)(200 * GUI.Scale);
orderTargetFrameShadow = new GUIFrame(new RectTransform(orderTargetFrame.Rect.Size + new Point(shadowSize * 2), GUI.Canvas) orderTargetFrameShadow = new GUIFrame(new RectTransform(orderTargetFrame.Rect.Size + new Point(shadowSize * 2), GUI.Canvas)
{ AbsoluteOffset = orderTargetFrame.Rect.Location - new Point(shadowSize) }, { AbsoluteOffset = orderTargetFrame.Rect.Location - new Point(shadowSize) },
style: "OuterGlow", style: "OuterGlow",
color: matchingItems.Count > 1 ? Color.Black * 0.9f : Color.Black * 0.7f); color: matchingItems.Count > 1 ? Color.Black * 0.9f : Color.Black * 0.7f);
} }
#region Updating and drawing the UI
private void DrawMiniMapOverlay(SpriteBatch spriteBatch, GUICustomComponent container) private void DrawMiniMapOverlay(SpriteBatch spriteBatch, GUICustomComponent container)
{ {
Submarine sub = container.UserData as Submarine; Submarine sub = container.UserData as Submarine;
@@ -895,7 +970,7 @@ namespace Barotrauma
float displayScale = ConvertUnits.ToDisplayUnits(scale); float displayScale = ConvertUnits.ToDisplayUnits(scale);
Vector2 offset = (sub.WorldPosition - new Vector2(dockedBorders.Center.X, dockedBorders.Y - dockedBorders.Height / 2)) * scale; Vector2 offset = (sub.WorldPosition - new Vector2(dockedBorders.Center.X, dockedBorders.Y - dockedBorders.Height / 2)) * scale;
Vector2 center = container.Rect.Center.ToVector2(); Vector2 center = container.Rect.Center.ToVector2();
for (int i = 0; i < sub.HullVertices.Count; i++) for (int i = 0; i < sub.HullVertices.Count; i++)
{ {
Vector2 start = (sub.HullVertices[i] * displayScale + offset); Vector2 start = (sub.HullVertices[i] * displayScale + offset);
@@ -903,14 +978,12 @@ namespace Barotrauma
Vector2 end = (sub.HullVertices[(i + 1) % sub.HullVertices.Count] * displayScale + offset); Vector2 end = (sub.HullVertices[(i + 1) % sub.HullVertices.Count] * displayScale + offset);
end.Y = -end.Y; end.Y = -end.Y;
GUI.DrawLine(spriteBatch, center + start, center + end, Color.DarkCyan * Rand.Range(0.3f, 0.35f), width: 10); GUI.DrawLine(spriteBatch, center + start, center + end, Color.DarkCyan * Rand.Range(0.3f, 0.35f), width: 10);
} }
} }
#region Updating and drawing the UI
public void AddToGUIUpdateList() public void AddToGUIUpdateList()
{ {
if (GUI.DisableHUD) return; if (GUI.DisableHUD || GUI.DisableUpperHUD) return;
if (GameMain.GraphicsWidth != screenResolution.X || GameMain.GraphicsHeight != screenResolution.Y || if (GameMain.GraphicsWidth != screenResolution.X || GameMain.GraphicsHeight != screenResolution.Y ||
prevUIScale != GUI.Scale) prevUIScale != GUI.Scale)
{ {
@@ -989,7 +1062,7 @@ namespace Barotrauma
} }
} }
if (GUI.DisableHUD) return; if (GUI.DisableHUD || GUI.DisableUpperHUD) return;
if (chatBox != null) if (chatBox != null)
{ {
chatBox.Update(deltaTime); chatBox.Update(deltaTime);
@@ -997,23 +1070,17 @@ namespace Barotrauma
if (!DebugConsole.IsOpen && chatBox.InputBox.Visible) if (!DebugConsole.IsOpen && chatBox.InputBox.Visible)
{ {
if (PlayerInput.KeyHit(InputType.Chat)) if (PlayerInput.KeyHit(InputType.Chat) && !chatBox.InputBox.Selected)
{ {
if (chatBox.InputBox.Selected) chatBox.GUIFrame.Flash(Color.DarkGreen, 0.5f);
{ chatBox.InputBox.Select();
chatBox.InputBox.Text = "";
chatBox.InputBox.Deselect();
}
else
{
chatBox.InputBox.Select();
}
} }
if (PlayerInput.KeyHit(InputType.RadioChat) && !chatBox.InputBox.Selected) if (PlayerInput.KeyHit(InputType.RadioChat) && !chatBox.InputBox.Selected)
{ {
chatBox.GUIFrame.Flash(Color.YellowGreen, 0.5f);
chatBox.InputBox.Select(); chatBox.InputBox.Select();
chatBox.InputBox.Text = "r; "; chatBox.InputBox.Text = "r; ";
} }
} }
} }
@@ -1026,12 +1093,22 @@ namespace Barotrauma
foreach (GUIComponent child in characterListBox.Content.Children) foreach (GUIComponent child in characterListBox.Content.Children)
{ {
child.Visible = Character character = (Character)child.UserData;
Character.Controlled == null || child.Visible =
(Character.Controlled != ((Character)child.UserData) && Character.Controlled.TeamID == ((Character)child.UserData).TeamID); Character.Controlled == null ||
(Character.Controlled.TeamID == character.TeamID);
if (child.Visible) if (child.Visible)
{ {
child.GetChildByUserData("highlight").Visible = character == Character.Controlled;
var soundIcon = child.FindChild(character)?.FindChild("soundicon");
if (soundIcon != null)
{
soundIcon.Color = new Color(soundIcon.Color, (soundIcon.Color.A / 255.0f) - deltaTime);
}
GUIListBox wrongOrderList = child.GetChildByUserData("orderbuttons")?.GetChild<GUIListBox>(); GUIListBox wrongOrderList = child.GetChildByUserData("orderbuttons")?.GetChild<GUIListBox>();
if (wrongOrderList != null) if (wrongOrderList != null)
{ {
@@ -1046,8 +1123,8 @@ namespace Barotrauma
hoverRect.Inflate((int)(30 * GUI.Scale), (int)(0 * GUI.Scale)); hoverRect.Inflate((int)(30 * GUI.Scale), (int)(0 * GUI.Scale));
} }
bool toggleOpen = bool toggleOpen =
characterListBox.Content.Rect.Contains(PlayerInput.MousePosition) && characterListBox.Content.Rect.Contains(PlayerInput.MousePosition) &&
hoverRect.Contains(PlayerInput.MousePosition); hoverRect.Contains(PlayerInput.MousePosition);
wrongOrderList.CanBeFocused = toggleOpen; wrongOrderList.CanBeFocused = toggleOpen;
wrongOrderList.Content.CanBeFocused = toggleOpen; wrongOrderList.Content.CanBeFocused = toggleOpen;
@@ -1092,7 +1169,6 @@ namespace Barotrauma
} }
UpdateReports(deltaTime); UpdateReports(deltaTime);
UpdateConversations(deltaTime);
if (orderTargetFrame != null) if (orderTargetFrame != null)
{ {
@@ -1111,16 +1187,16 @@ namespace Barotrauma
} }
} }
#endregion #endregion
/// <summary> /// <summary>
/// Creates a listbox that includes all the characters in the crew, can be used externally (round info menus etc) /// Creates a listbox that includes all the characters in the crew, can be used externally (round info menus etc)
/// </summary> /// </summary>
public void CreateCrewListFrame(IEnumerable<Character> crew, GUIFrame crewFrame) public void CreateCrewListFrame(IEnumerable<Character> crew, GUIFrame crewFrame)
{ {
List<byte> teamIDs = crew.Select(c => c.TeamID).Distinct().ToList(); List<Character.TeamType> teamIDs = crew.Select(c => c.TeamID).Distinct().ToList();
if (!teamIDs.Any()) teamIDs.Add(0); if (!teamIDs.Any()) teamIDs.Add(Character.TeamType.None);
int listBoxHeight = 300 / teamIDs.Count; int listBoxHeight = 300 / teamIDs.Count;
@@ -1151,7 +1227,7 @@ namespace Barotrauma
GUIFrame frame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.15f), crewList.Content.RectTransform), style: "ListBoxElement") GUIFrame frame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.15f), crewList.Content.RectTransform), style: "ListBoxElement")
{ {
UserData = character, UserData = character,
Color = (GameMain.NetworkMember != null && GameMain.NetworkMember.Character == character) ? Color.Gold * 0.2f : Color.Transparent Color = (GameMain.NetworkMember != null && GameMain.Client.Character == character) ? Color.Gold * 0.2f : Color.Transparent
}; };
var paddedFrame = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.9f), frame.RectTransform, Anchor.Center), isHorizontal: true) var paddedFrame = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.9f), frame.RectTransform, Anchor.Center), isHorizontal: true)
@@ -1159,7 +1235,7 @@ namespace Barotrauma
RelativeSpacing = 0.05f, RelativeSpacing = 0.05f,
Stretch = true Stretch = true
}; };
new GUICustomComponent(new RectTransform(new Vector2(0.2f, 1.0f), paddedFrame.RectTransform, Anchor.CenterLeft), new GUICustomComponent(new RectTransform(new Vector2(0.2f, 1.0f), paddedFrame.RectTransform, Anchor.CenterLeft),
onDraw: (sb, component) => character.Info.DrawIcon(sb, component.Rect.Center.ToVector2(), targetAreaSize: component.Rect.Size.ToVector2())) onDraw: (sb, component) => character.Info.DrawIcon(sb, component.Rect.Center.ToVector2(), targetAreaSize: component.Rect.Size.ToVector2()))
{ {
@@ -1169,7 +1245,7 @@ namespace Barotrauma
}; };
GUITextBlock textBlock = new GUITextBlock(new RectTransform(Vector2.One, paddedFrame.RectTransform), GUITextBlock textBlock = new GUITextBlock(new RectTransform(Vector2.One, paddedFrame.RectTransform),
ToolBox.LimitString(character.Info.Name + " (" + character.Info.Job.Name + ")", GUI.Font, paddedFrame.Rect.Width - paddedFrame.Rect.Height), ToolBox.LimitString(character.Info.Name + " (" + character.Info.Job.Name + ")", GUI.Font, paddedFrame.Rect.Width - paddedFrame.Rect.Height),
textColor: character.Info.Job.Prefab.UIColor); textColor: character.Info.Job.Prefab.UIColor);
} }
} }
@@ -1194,12 +1270,12 @@ namespace Barotrauma
character.Info.CreateInfoFrame(previewPlayer); character.Info.CreateInfoFrame(previewPlayer);
if (GameMain.NetworkMember != null) GameMain.NetworkMember.SelectCrewCharacter(character, previewPlayer); if (GameMain.NetworkMember != null) GameMain.Client.SelectCrewCharacter(character, previewPlayer);
return true; return true;
} }
#region Reports #region Reports
/// <summary> /// <summary>
/// Enables/disables report buttons when needed /// Enables/disables report buttons when needed
@@ -1217,7 +1293,7 @@ namespace Barotrauma
{ {
reportButtonFrame.Visible = true; reportButtonFrame.Visible = true;
var reportButtonParent = chatBox ?? GameMain.NetworkMember.ChatBox; var reportButtonParent = chatBox ?? GameMain.Client.ChatBox;
reportButtonFrame.RectTransform.AbsoluteOffset = new Point( reportButtonFrame.RectTransform.AbsoluteOffset = new Point(
Math.Min(reportButtonParent.GUIFrame.Rect.X, reportButtonParent.ToggleButton.Rect.X) - reportButtonFrame.Rect.Width - (int)(10 * GUI.Scale), Math.Min(reportButtonParent.GUIFrame.Rect.X, reportButtonParent.ToggleButton.Rect.X) - reportButtonFrame.Rect.Width - (int)(10 * GUI.Scale),
reportButtonParent.GUIFrame.Rect.Y); reportButtonParent.GUIFrame.Rect.Y);
@@ -1230,7 +1306,7 @@ namespace Barotrauma
bool hasIntruders = Character.CharacterList.Any(c => bool hasIntruders = Character.CharacterList.Any(c =>
c.CurrentHull == Character.Controlled.CurrentHull && !c.IsDead && c.CurrentHull == Character.Controlled.CurrentHull && !c.IsDead &&
(c.AIController is EnemyAIController || c.TeamID != Character.Controlled.TeamID)); (c.AIController is EnemyAIController || (c.TeamID != Character.Controlled.TeamID && c.TeamID != Character.TeamType.FriendlyNPC)));
ToggleReportButton("reportintruders", hasIntruders); ToggleReportButton("reportintruders", hasIntruders);
@@ -1240,7 +1316,7 @@ namespace Barotrauma
if (highlight.Visible) if (highlight.Visible)
{ {
highlight.RectTransform.LocalScale = new Vector2(1.25f + (float)Math.Sin(Timing.TotalTime * 5.0f) * 0.25f); highlight.RectTransform.LocalScale = new Vector2(1.25f + (float)Math.Sin(Timing.TotalTime * 5.0f) * 0.25f);
} }
} }
} }
else else
@@ -1256,7 +1332,7 @@ namespace Barotrauma
{ {
return CharacterHealth.OpenHealthWindow == null; return CharacterHealth.OpenHealthWindow == null;
} }
private bool ReportButtonClicked(GUIButton button, object userData) private bool ReportButtonClicked(GUIButton button, object userData)
{ {
//order targeted to all characters //order targeted to all characters
@@ -1273,7 +1349,7 @@ namespace Barotrauma
private void ToggleReportButton(string orderAiTag, bool enabled) private void ToggleReportButton(string orderAiTag, bool enabled)
{ {
Order order = Order.PrefabList.Find(o => o.AITag == orderAiTag); Order order = Order.PrefabList.Find(o => o.AITag == orderAiTag);
//already reported, disable the button //already reported, disable the button
/*if (GameMain.GameSession.CrewManager.ActiveOrders.Any(o => /*if (GameMain.GameSession.CrewManager.ActiveOrders.Any(o =>
o.First.TargetEntity == Character.Controlled.CurrentHull && o.First.TargetEntity == Character.Controlled.CurrentHull &&
@@ -1286,10 +1362,10 @@ namespace Barotrauma
if (reportButton != null) if (reportButton != null)
{ {
reportButton.GetChildByUserData("highlighted").Visible = enabled; reportButton.GetChildByUserData("highlighted").Visible = enabled;
} }
} }
#endregion #endregion
public void InitSinglePlayerRound() public void InitSinglePlayerRound()
{ {
@@ -1300,13 +1376,13 @@ namespace Barotrauma
for (int i = 0; i < waypoints.Length; i++) for (int i = 0; i < waypoints.Length; i++)
{ {
Character character; Character character;
character = Character.Create(characterInfos[i], waypoints[i].WorldPosition, characterInfos[i].Name); character = Character.Create(characterInfos[i], waypoints[i].WorldPosition, characterInfos[i].Name);
if (character.Info != null && !character.Info.StartItemsGiven) if (character.Info != null && !character.Info.StartItemsGiven)
{ {
character.GiveJobItems(waypoints[i]); character.GiveJobItems(waypoints[i]);
character.Info.StartItemsGiven = true; character.Info.StartItemsGiven = true;
} }
if (character.Info?.InventoryData != null) if (character.Info?.InventoryData != null)
{ {
@@ -3,12 +3,15 @@ using Lidgren.Network;
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
namespace Barotrauma namespace Barotrauma
{ {
partial class MultiPlayerCampaign : CampaignMode partial class MultiPlayerCampaign : CampaignMode
{ {
public static GUIComponent StartCampaignSetup() private UInt16 startWatchmanID, endWatchmanID;
public static GUIComponent StartCampaignSetup(IEnumerable<string> saveFiles)
{ {
GUIFrame background = new GUIFrame(new RectTransform(Vector2.One, GUI.Canvas), style: "GUIBackgroundBlocker"); GUIFrame background = new GUIFrame(new RectTransform(Vector2.One, GUI.Canvas), style: "GUIBackgroundBlocker");
@@ -31,7 +34,7 @@ namespace Barotrauma
var newCampaignContainer = new GUIFrame(new RectTransform(Vector2.One, campaignContainer.RectTransform, Anchor.BottomLeft), style: null); var newCampaignContainer = new GUIFrame(new RectTransform(Vector2.One, campaignContainer.RectTransform, Anchor.BottomLeft), style: null);
var loadCampaignContainer = new GUIFrame(new RectTransform(Vector2.One, campaignContainer.RectTransform, Anchor.BottomLeft), style: null); var loadCampaignContainer = new GUIFrame(new RectTransform(Vector2.One, campaignContainer.RectTransform, Anchor.BottomLeft), style: null);
var campaignSetupUI = new CampaignSetupUI(true, newCampaignContainer, loadCampaignContainer); var campaignSetupUI = new CampaignSetupUI(true, newCampaignContainer, loadCampaignContainer, saveFiles);
var newCampaignButton = new GUIButton(new RectTransform(new Vector2(0.3f, 1.0f), buttonContainer.RectTransform), var newCampaignButton = new GUIButton(new RectTransform(new Vector2(0.3f, 1.0f), buttonContainer.RectTransform),
TextManager.Get("NewCampaign")) TextManager.Get("NewCampaign"))
@@ -56,55 +59,16 @@ namespace Barotrauma
}; };
loadCampaignContainer.Visible = false; loadCampaignContainer.Visible = false;
campaignSetupUI.StartNewGame = (Submarine sub, string saveName, string mapSeed) => campaignSetupUI.StartNewGame = GameMain.Client.SetupNewCampaign;
{ campaignSetupUI.LoadGame = GameMain.Client.SetupLoadCampaign;
GameMain.GameSession = new GameSession(new Submarine(sub.FilePath, ""), saveName,
GameModePreset.List.Find(g => g.Identifier == "multiplayercampaign"));
var campaign = ((MultiPlayerCampaign)GameMain.GameSession.GameMode);
campaign.GenerateMap(mapSeed);
campaign.SetDelegates();
background.Visible = false;
GameMain.NetLobbyScreen.ToggleCampaignMode(true);
campaign.Map.SelectRandomLocation(true);
SaveUtil.SaveGame(GameMain.GameSession.SavePath);
campaign.LastSaveID++;
};
campaignSetupUI.LoadGame = (string fileName) =>
{
SaveUtil.LoadGame(fileName);
if (!(GameMain.GameSession.GameMode is MultiPlayerCampaign))
{
DebugConsole.ThrowError("Failed to load the campaign. The save file appears to be for a single player campaign.");
return;
}
var campaign = ((MultiPlayerCampaign)GameMain.GameSession.GameMode);
campaign.LastSaveID++;
background.Visible = false;
GameMain.NetLobbyScreen.ToggleCampaignMode(true);
campaign.Map.SelectRandomLocation(true);
};
var cancelButton = new GUIButton(new RectTransform(new Vector2(0.2f, 0.05f), paddedFrame.RectTransform, Anchor.BottomLeft), TextManager.Get("Cancel")) var cancelButton = new GUIButton(new RectTransform(new Vector2(0.2f, 0.05f), paddedFrame.RectTransform, Anchor.BottomLeft), TextManager.Get("Cancel"))
{ {
OnClicked = (btn, obj) => OnClicked = (btn, obj) =>
{ {
//find the first mode that's not multiplayer campaign and switch to that
background.Visible = false; background.Visible = false;
int otherModeIndex = 0;
for (otherModeIndex = 0; otherModeIndex < GameMain.NetLobbyScreen.ModeList.Content.CountChildren; otherModeIndex++)
{
if (GameMain.NetLobbyScreen.ModeList.Content.GetChild(otherModeIndex).UserData is MultiPlayerCampaign) continue;
break;
}
GameMain.NetLobbyScreen.SelectMode(otherModeIndex);
return true; return true;
} }
}; };
@@ -112,6 +76,56 @@ namespace Barotrauma
return background; return background;
} }
public override void Update(float deltaTime)
{
base.Update(deltaTime);
if (startWatchmanID > 0 && startWatchman == null)
{
startWatchman = Entity.FindEntityByID(startWatchmanID) as Character;
if (startWatchman != null) { InitializeWatchman(startWatchman); }
}
if (endWatchmanID > 0 && endWatchman == null)
{
endWatchman = Entity.FindEntityByID(endWatchmanID) as Character;
if (endWatchman != null) { InitializeWatchman(endWatchman); }
}
}
protected override void WatchmanInteract(Character watchman, Character interactor)
{
if ((watchman.Submarine == Level.Loaded.StartOutpost && !Submarine.MainSub.AtStartPosition) ||
(watchman.Submarine == Level.Loaded.EndOutpost && !Submarine.MainSub.AtEndPosition))
{
return;
}
if (GUIMessageBox.MessageBoxes.Any(mbox => mbox.UserData as string == "watchmanprompt"))
{
return;
}
if (GameMain.Client != null && interactor == Character.Controlled &&
(GameMain.Client.HasPermission(ClientPermissions.ManageRound) || GameMain.Client.HasPermission(ClientPermissions.ManageCampaign)))
{
var msgBox = new GUIMessageBox("", TextManager.Get("CampaignEnterOutpostPrompt")
.Replace("[locationname]", Submarine.MainSub.AtStartPosition ? Map.CurrentLocation.Name : Map.SelectedLocation.Name),
new string[] { TextManager.Get("Yes"), TextManager.Get("No") })
{
UserData = "watchmanprompt"
};
msgBox.Buttons[0].OnClicked = (btn, userdata) =>
{
GameMain.Client.RequestRoundEnd();
return true;
};
msgBox.Buttons[0].OnClicked += msgBox.Close;
msgBox.Buttons[1].OnClicked += msgBox.Close;
}
}
public void ClientWrite(NetBuffer msg) public void ClientWrite(NetBuffer msg)
{ {
System.Diagnostics.Debug.Assert(map.Locations.Count < UInt16.MaxValue); System.Diagnostics.Debug.Assert(map.Locations.Count < UInt16.MaxValue);
@@ -138,6 +152,9 @@ namespace Barotrauma
UInt16 selectedLocIndex = msg.ReadUInt16(); UInt16 selectedLocIndex = msg.ReadUInt16();
byte selectedMissionIndex = msg.ReadByte(); byte selectedMissionIndex = msg.ReadByte();
UInt16 startWatchmanID = msg.ReadUInt16();
UInt16 endWatchmanID = msg.ReadUInt16();
int money = msg.ReadInt32(); int money = msg.ReadInt32();
UInt16 purchasedItemCount = msg.ReadUInt16(); UInt16 purchasedItemCount = msg.ReadUInt16();
@@ -167,10 +184,9 @@ namespace Barotrauma
campaign = ((MultiPlayerCampaign)GameMain.GameSession.GameMode); campaign = ((MultiPlayerCampaign)GameMain.GameSession.GameMode);
campaign.CampaignID = campaignID; campaign.CampaignID = campaignID;
campaign.GenerateMap(mapSeed); campaign.GenerateMap(mapSeed);
GameMain.NetLobbyScreen.ToggleCampaignMode(true);
} }
GameMain.NetLobbyScreen.ToggleCampaignMode(true);
if (NetIdUtils.IdMoreRecent(campaign.lastUpdateID, updateID)) return;
//server has a newer save file //server has a newer save file
if (NetIdUtils.IdMoreRecent(saveID, campaign.PendingSaveID)) if (NetIdUtils.IdMoreRecent(saveID, campaign.PendingSaveID))
@@ -187,19 +203,22 @@ namespace Barotrauma
GameMain.Client.RequestFile(FileTransferType.CampaignSave, null, null);*/ GameMain.Client.RequestFile(FileTransferType.CampaignSave, null, null);*/
campaign.PendingSaveID = saveID; campaign.PendingSaveID = saveID;
} }
//we've got the latest save file
else if (!NetIdUtils.IdMoreRecent(saveID, campaign.lastSaveID)) if (NetIdUtils.IdMoreRecent(updateID, campaign.lastUpdateID))
{ {
campaign.Map.SetLocation(currentLocIndex == UInt16.MaxValue ? -1 : currentLocIndex); campaign.Map.SetLocation(currentLocIndex == UInt16.MaxValue ? -1 : currentLocIndex);
campaign.Map.SelectLocation(selectedLocIndex == UInt16.MaxValue ? -1 : selectedLocIndex); campaign.Map.SelectLocation(selectedLocIndex == UInt16.MaxValue ? -1 : selectedLocIndex);
campaign.Map.SelectMission(selectedMissionIndex); campaign.Map.SelectMission(selectedMissionIndex);
campaign.startWatchmanID = startWatchmanID;
campaign.endWatchmanID = endWatchmanID;
campaign.Money = money; campaign.Money = money;
campaign.CargoManager.SetPurchasedItems(purchasedItems); campaign.CargoManager.SetPurchasedItems(purchasedItems);
if (myCharacterInfo != null) if (myCharacterInfo != null)
{ {
GameMain.NetworkMember.CharacterInfo = myCharacterInfo; GameMain.Client.CharacterInfo = myCharacterInfo;
GameMain.NetLobbyScreen.SetCampaignCharacterInfo(myCharacterInfo); GameMain.NetLobbyScreen.SetCampaignCharacterInfo(myCharacterInfo);
} }
else else
@@ -38,7 +38,7 @@ namespace Barotrauma
{ {
for (int i = 0; i < jobPrefab.InitialCount; i++) for (int i = 0; i < jobPrefab.InitialCount; i++)
{ {
CrewManager.AddCharacterInfo(new CharacterInfo(Character.HumanConfigFile, "", Gender.None, jobPrefab)); CrewManager.AddCharacterInfo(new CharacterInfo(Character.HumanConfigFile, "", jobPrefab));
} }
} }
@@ -128,7 +128,7 @@ namespace Barotrauma
public override void Draw(SpriteBatch spriteBatch) public override void Draw(SpriteBatch spriteBatch)
{ {
if (!isRunning|| GUI.DisableHUD) return; if (!isRunning|| GUI.DisableHUD || GUI.DisableUpperHUD) return;
if (Submarine.MainSub == null) return; if (Submarine.MainSub == null) return;
@@ -180,7 +180,7 @@ namespace Barotrauma
ContextualTutorial.Update(deltaTime); ContextualTutorial.Update(deltaTime);
} }
if (!GUI.DisableHUD) if (!GUI.DisableHUD && !GUI.DisableUpperHUD)
{ {
endRoundButton.UpdateManually(deltaTime); endRoundButton.UpdateManually(deltaTime);
} }
@@ -206,11 +206,19 @@ namespace Barotrauma
return; return;
} }
CreateDialog(new List<Character> { watchman }, "WatchmanInteract", 1.0f); CreateDialog(new List<Character> { watchman }, "WatchmanInteract", 1.0f);
if (GUIMessageBox.MessageBoxes.Any(mbox => mbox.UserData as string == "watchmanprompt"))
{
return;
}
var msgBox = new GUIMessageBox("", TextManager.Get("CampaignEnterOutpostPrompt") var msgBox = new GUIMessageBox("", TextManager.Get("CampaignEnterOutpostPrompt")
.Replace("[locationname]", leavingSub.AtStartPosition ? Map.CurrentLocation.Name : Map.SelectedLocation.Name), .Replace("[locationname]", leavingSub.AtStartPosition ? Map.CurrentLocation.Name : Map.SelectedLocation.Name),
new string[] { TextManager.Get("Yes"), TextManager.Get("No") }); new string[] { TextManager.Get("Yes"), TextManager.Get("No") })
{
UserData = "watchmanprompt"
};
msgBox.Buttons[0].OnClicked = (btn, userdata) => msgBox.Buttons[0].OnClicked = (btn, userdata) =>
{ {
if (!isRunning) { return true; } if (!isRunning) { return true; }
@@ -584,7 +584,7 @@ namespace Barotrauma.Tutorials
} }
} }
if (brokenBox != null && brokenBox.Condition > 50.0f && pump.Voltage < pump.MinVoltage) if (brokenBox != null && brokenBox.Condition > brokenBox.Prefab.Health / 2.0f && pump.Voltage < pump.MinVoltage)
{ {
yield return new WaitForSeconds(1.0f); yield return new WaitForSeconds(1.0f);
@@ -152,7 +152,6 @@ namespace Barotrauma.Tutorials
if (!Initialized) return; if (!Initialized) return;
PreloadVideoContent(); PreloadVideoContent();
Completed = true; // Trigger completed at start to prevent the contextual tutorial from automatically activating on starting new campaigns after this one
base.Start(); base.Start();
@@ -194,6 +193,7 @@ namespace Barotrauma.Tutorials
} }
crew = GameMain.GameSession.CrewManager.GetCharacters().ToList(); crew = GameMain.GameSession.CrewManager.GetCharacters().ToList();
Completed = true; // Trigger completed at start to prevent the contextual tutorial from automatically activating on starting new campaigns after this one
started = true; started = true;
} }
@@ -325,7 +325,7 @@ namespace Barotrauma.Tutorials
foreach (Item item in Item.ItemList) foreach (Item item in Item.ItemList)
{ {
if (!item.Repairables.Any() || item.Condition > 50.0f) continue; if (!item.Repairables.Any() || item.Condition > item.Prefab.Health / 2.0f) continue;
degradedEquipmentFound = true; degradedEquipmentFound = true;
break; break;
} }
@@ -464,7 +464,7 @@ namespace Barotrauma.Tutorials
spriteSheetPlayer.LoadContent(playableContentPath, activeSegment.Content, activeSegment.Name, true, true, CurrentSegmentStopCallback); spriteSheetPlayer.LoadContent(playableContentPath, activeSegment.Content, activeSegment.Name, true, true, CurrentSegmentStopCallback);
break; break;
case ContentTypes.Text: case ContentTypes.Text:
infoBox = CreateInfoFrame(TextManager.Get(activeSegment.Name), TextManager.Get(activeSegment.Content.GetAttributeString("tag", ""), false, args), infoBox = CreateInfoFrame(TextManager.Get(activeSegment.Name), TextManager.GetFormatted(activeSegment.Content.GetAttributeString("tag", ""), false, args),
activeSegment.Content.GetAttributeInt("width", 300), activeSegment.Content.GetAttributeInt("width", 300),
activeSegment.Content.GetAttributeInt("height", 80), activeSegment.Content.GetAttributeInt("height", 80),
activeSegment.Content.GetAttributeString("anchor", "Center"), true, CurrentSegmentStopCallback); activeSegment.Content.GetAttributeString("anchor", "Center"), true, CurrentSegmentStopCallback);
@@ -36,7 +36,7 @@ namespace Barotrauma.Tutorials
} }
CharacterInfo charInfo = configElement.Element("Character") == null ? CharacterInfo charInfo = configElement.Element("Character") == null ?
new CharacterInfo(Character.HumanConfigFile, "", Gender.None, JobPrefab.List.Find(jp => jp.Identifier == "engineer")) : new CharacterInfo(Character.HumanConfigFile, "", JobPrefab.List.Find(jp => jp.Identifier == "engineer")) :
new CharacterInfo(configElement.Element("Character")); new CharacterInfo(configElement.Element("Character"));
character = Character.Create(charInfo, wayPoint.WorldPosition, "", false, false); character = Character.Create(charInfo, wayPoint.WorldPosition, "", false, false);
@@ -101,7 +101,7 @@ namespace Barotrauma.Tutorials
messageBox.Buttons[0].OnClicked += messageBox.Close; messageBox.Buttons[0].OnClicked += messageBox.Close;
messageBox.Buttons[1].OnClicked = GameMain.MainMenuScreen.SelectTab; messageBox.Buttons[1].OnClicked = GameMain.MainMenuScreen.ReturnToMainMenu;
messageBox.Buttons[1].OnClicked += messageBox.Close; messageBox.Buttons[1].OnClicked += messageBox.Close;
yield return CoroutineStatus.Success; yield return CoroutineStatus.Success;
@@ -31,7 +31,7 @@ namespace Barotrauma.Tutorials
{ {
if (completed == value) return; if (completed == value) return;
completed = value; completed = value;
GameMain.Config.Save(); GameMain.Config.SaveNewPlayerConfig();
} }
} }
@@ -105,7 +105,7 @@ namespace Barotrauma.Tutorials
{ {
configElement = element; configElement = element;
Name = element.GetAttributeString("name", "Unnamed"); Name = element.GetAttributeString("name", "Unnamed");
Completed = GameMain.Config.CompletedTutorialNames.Contains(Name); completed = GameMain.Config.CompletedTutorialNames.Contains(Name);
Enum.TryParse(element.GetAttributeString("tutorialtype", "Scenario"), true, out tutorialType); Enum.TryParse(element.GetAttributeString("tutorialtype", "Scenario"), true, out tutorialType);
} }
@@ -167,7 +167,7 @@ namespace Barotrauma.Tutorials
}; };
} }
GUI.PlayUISound(GUISoundType.Message); GUI.PlayUISound(GUISoundType.UIMessage);
return infoBlock; return infoBlock;
} }
@@ -211,7 +211,7 @@ namespace Barotrauma.Tutorials
}; };
} }
GUI.PlayUISound(GUISoundType.Message); GUI.PlayUISound(GUISoundType.UIMessage);
return infoBlock; return infoBlock;
} }
@@ -6,8 +6,11 @@ namespace Barotrauma
partial class GameSession partial class GameSession
{ {
private InfoFrameTab selectedTab; private InfoFrameTab selectedTab;
private GUIButton infoButton;
private GUIButton infoFrame; private GUIButton infoFrame;
/// <summary>
/// Determines whether the hotkey for the info button was held down in the previous frame.
/// </summary>
private bool prevInfoKey;
private GUIFrame infoFrameContent; private GUIFrame infoFrameContent;
@@ -17,7 +20,12 @@ namespace Barotrauma
get { return roundSummary; } get { return roundSummary; }
} }
private bool ToggleInfoFrame(GUIButton button, object obj) partial void InitProjSpecific()
{
prevInfoKey = false;
}
private bool ToggleInfoFrame()
{ {
if (infoFrame == null) if (infoFrame == null)
{ {
@@ -36,10 +44,7 @@ namespace Barotrauma
{ {
int width = 600, height = 400; int width = 600, height = 400;
infoFrame = new GUIButton(new RectTransform(Vector2.One, GUI.Canvas), style: "GUIBackgroundBlocker") infoFrame = new GUIButton(new RectTransform(Vector2.One, GUI.Canvas), style: "GUIBackgroundBlocker");
{
OnClicked = (btn, userdata) => { if (GUI.MouseOn == btn || GUI.MouseOn == btn.TextBlock) ToggleInfoFrame(btn, userdata); return true; }
};
var innerFrame = new GUIFrame(new RectTransform(new Vector2(0.3f, 0.35f), infoFrame.RectTransform, Anchor.Center) { MinSize = new Point(width,height) }); var innerFrame = new GUIFrame(new RectTransform(new Vector2(0.3f, 0.35f), infoFrame.RectTransform, Anchor.Center) { MinSize = new Point(width,height) });
@@ -63,6 +68,7 @@ namespace Barotrauma
OnClicked = SelectInfoFrameTab OnClicked = SelectInfoFrameTab
}; };
/*TODO: fix
if (GameMain.Server != null) if (GameMain.Server != null)
{ {
var manageButton = new GUIButton(new RectTransform(new Vector2(0.2f, 1.0f), buttonArea.RectTransform), TextManager.Get("ManagePlayers")) var manageButton = new GUIButton(new RectTransform(new Vector2(0.2f, 1.0f), buttonArea.RectTransform), TextManager.Get("ManagePlayers"))
@@ -70,12 +76,7 @@ namespace Barotrauma
UserData = InfoFrameTab.ManagePlayers, UserData = InfoFrameTab.ManagePlayers,
OnClicked = SelectInfoFrameTab OnClicked = SelectInfoFrameTab
}; };
} }*/
var closeButton = new GUIButton(new RectTransform(new Vector2(0.25f, 0.08f), paddedFrame.RectTransform, Anchor.BottomRight), TextManager.Get("Close"))
{
OnClicked = ToggleInfoFrame
};
} }
@@ -94,7 +95,8 @@ namespace Barotrauma
CreateMissionInfo(infoFrameContent); CreateMissionInfo(infoFrameContent);
break; break;
case InfoFrameTab.ManagePlayers: case InfoFrameTab.ManagePlayers:
GameMain.Server.ManagePlayersFrame(infoFrameContent); //TODO: fix
//GameMain.Server.ManagePlayersFrame(infoFrameContent);
break; break;
} }
@@ -125,7 +127,6 @@ namespace Barotrauma
public void AddToGUIUpdateList() public void AddToGUIUpdateList()
{ {
if (GUI.DisableHUD) return; if (GUI.DisableHUD) return;
infoButton.AddToGUIUpdateList();
GameMode?.AddToGUIUpdateList(); GameMode?.AddToGUIUpdateList();
infoFrame?.AddToGUIUpdateList(); infoFrame?.AddToGUIUpdateList();
} }
@@ -133,8 +134,13 @@ namespace Barotrauma
partial void UpdateProjSpecific(float deltaTime) partial void UpdateProjSpecific(float deltaTime)
{ {
if (GUI.DisableHUD) return; if (GUI.DisableHUD) return;
infoButton?.UpdateManually(deltaTime); if (prevInfoKey != (PlayerInput.KeyDown(InputType.InfoTab) && GUI.KeyboardDispatcher.Subscriber == null))
{
ToggleInfoFrame();
prevInfoKey = PlayerInput.KeyDown(InputType.InfoTab);
}
infoFrame?.UpdateManually(deltaTime); infoFrame?.UpdateManually(deltaTime);
} }
@@ -142,8 +148,6 @@ namespace Barotrauma
{ {
if (GUI.DisableHUD) return; if (GUI.DisableHUD) return;
infoButton.DrawManually(spriteBatch);
GameMode?.Draw(spriteBatch); GameMode?.Draw(spriteBatch);
infoFrame?.DrawManually(spriteBatch); infoFrame?.DrawManually(spriteBatch);
} }
@@ -71,21 +71,17 @@ namespace Barotrauma
var missionInfo = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), infoTextBox.Content.RectTransform), var missionInfo = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), infoTextBox.Content.RectTransform),
GameMain.GameSession.Mission.Completed ? GameMain.GameSession.Mission.SuccessMessage : GameMain.GameSession.Mission.FailureMessage, GameMain.GameSession.Mission.Completed ? GameMain.GameSession.Mission.SuccessMessage : GameMain.GameSession.Mission.FailureMessage,
wrap: true); wrap: true);
if (GameMain.GameSession.Mission.Completed)
{
GameMain.Server?.ConnectedClients.ForEach(c => c.Karma += 0.1f);
}
if (GameMain.GameSession.Mission.Completed && singleplayer) if (GameMain.GameSession.Mission.Completed && singleplayer)
{ {
var missionReward = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), infoTextBox.Content.RectTransform), var missionReward = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), infoTextBox.Content.RectTransform),
TextManager.Get("MissionReward").Replace("[reward]", GameMain.GameSession.Mission.Reward.ToString())); TextManager.Get("MissionReward").Replace("[reward]", GameMain.GameSession.Mission.Reward.ToString()));
} }
} }
else
foreach (GUIComponent child in infoTextBox.Content.Children)
{ {
GameMain.Server?.ConnectedClients.ForEach(c => c.Karma += 0.1f); child.CanBeFocused = false;
} }
foreach (GUIComponent child in infoTextBox.Content.Children) foreach (GUIComponent child in infoTextBox.Content.Children)
{ {
@@ -100,7 +96,7 @@ namespace Barotrauma
foreach (CharacterInfo characterInfo in gameSession.CrewManager.GetCharacterInfos()) foreach (CharacterInfo characterInfo in gameSession.CrewManager.GetCharacterInfos())
{ {
if (GameMain.GameSession.Mission is CombatMission && if (GameMain.GameSession.Mission is CombatMission &&
characterInfo.TeamID != GameMain.GameSession.CrewManager.WinningTeam) characterInfo.TeamID != GameMain.GameSession.WinningTeam)
{ {
continue; continue;
} }
+395 -119
View File
@@ -1,6 +1,8 @@
using Microsoft.Xna.Framework; using Barotrauma.Networking;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input; using Microsoft.Xna.Framework.Input;
using OpenTK.Audio.OpenAL;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
@@ -13,8 +15,10 @@ namespace Barotrauma
{ {
General, General,
Graphics, Graphics,
Audio,
Controls,
} }
private GUIFrame settingsFrame; private GUIFrame settingsFrame;
private GUIButton applyButton; private GUIButton applyButton;
@@ -40,9 +44,9 @@ namespace Barotrauma
int index = text.Text.IndexOf("%"); int index = text.Text.IndexOf("%");
string label = text.Text; string label = text.Text;
//if "%" is found //if "%" is found
if(index > 0) if (index > 0)
{ {
while(true) while (true)
{ {
//search for end of label //search for end of label
index -= 1; index -= 1;
@@ -57,6 +61,10 @@ namespace Barotrauma
public void ResetSettingsFrame() public void ResetSettingsFrame()
{ {
if (GameMain.Client == null)
{
VoipCapture.Instance?.Dispose();
}
settingsFrame = null; settingsFrame = null;
} }
@@ -66,12 +74,12 @@ namespace Barotrauma
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.15f), settingsFrame.RectTransform), new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.15f), settingsFrame.RectTransform),
TextManager.Get("Settings"), textAlignment: Alignment.Center, font: GUI.LargeFont); TextManager.Get("Settings"), textAlignment: Alignment.Center, font: GUI.LargeFont);
var paddedFrame = new GUIFrame(new RectTransform(new Vector2(0.9f, 0.8f), settingsFrame.RectTransform, Anchor.Center) var paddedFrame = new GUIFrame(new RectTransform(new Vector2(0.9f, 0.8f), settingsFrame.RectTransform, Anchor.Center)
{ RelativeOffset = new Vector2(0.0f, 0.06f) }, style: null); { RelativeOffset = new Vector2(0.0f, 0.06f) }, style: null);
var tabButtonHolder = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.05f), settingsFrame.RectTransform, Anchor.TopCenter) var tabButtonHolder = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.05f), settingsFrame.RectTransform, Anchor.TopCenter)
{ RelativeOffset = new Vector2(0.0f, 0.1f) }, isHorizontal: true); { RelativeOffset = new Vector2(0.0f, 0.11f) }, isHorizontal: true);
tabs = new GUIFrame[Enum.GetValues(typeof(Tab)).Length]; tabs = new GUIFrame[Enum.GetValues(typeof(Tab)).Length];
tabButtons = new GUIButton[tabs.Length]; tabButtons = new GUIButton[tabs.Length];
@@ -81,7 +89,8 @@ namespace Barotrauma
{ {
UserData = tab UserData = tab
}; };
tabButtons[(int)tab] = new GUIButton(new RectTransform(new Vector2(0.25f, 1.0f), tabButtonHolder.RectTransform), tab.ToString()) tabButtons[(int)tab] = new GUIButton(new RectTransform(new Vector2(0.25f, 1.0f), tabButtonHolder.RectTransform),
TextManager.Get("SettingsTab." + tab.ToString()), style: "GUITabButton")
{ {
UserData = tab, UserData = tab,
OnClicked = (bt, userdata) => { SelectTab((Tab)userdata); return true; } OnClicked = (bt, userdata) => { SelectTab((Tab)userdata); return true; }
@@ -89,27 +98,40 @@ namespace Barotrauma
} }
var buttonArea = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.08f), paddedFrame.RectTransform, Anchor.BottomCenter), style: null); var buttonArea = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.08f), paddedFrame.RectTransform, Anchor.BottomCenter), style: null);
/// Graphics tab -------------------------------------------------------------- /// Graphics tab --------------------------------------------------------------
var leftColumn = new GUILayoutGroup(new RectTransform(new Vector2(0.46f, 0.95f), tabs[(int)Tab.Graphics].RectTransform, Anchor.CenterLeft) var leftColumn = new GUILayoutGroup(new RectTransform(new Vector2(0.46f, 0.95f), tabs[(int)Tab.Graphics].RectTransform, Anchor.CenterLeft)
{ RelativeOffset = new Vector2(0.02f, 0.0f) }) { RelativeSpacing = 0.01f, Stretch = true }; { RelativeOffset = new Vector2(0.02f, 0.0f) })
{ RelativeSpacing = 0.01f, Stretch = true };
var rightColumn = new GUILayoutGroup(new RectTransform(new Vector2(0.46f, 0.95f), tabs[(int)Tab.Graphics].RectTransform, Anchor.CenterRight) var rightColumn = new GUILayoutGroup(new RectTransform(new Vector2(0.46f, 0.95f), tabs[(int)Tab.Graphics].RectTransform, Anchor.CenterRight)
{ RelativeOffset = new Vector2(0.02f, 0.0f) }) { RelativeSpacing = 0.01f, Stretch = true }; { RelativeOffset = new Vector2(0.02f, 0.0f) })
{ RelativeSpacing = 0.01f, Stretch = true };
var supportedDisplayModes = new List<DisplayMode>(); var supportedDisplayModes = new List<DisplayMode>();
foreach (DisplayMode mode in GraphicsAdapter.DefaultAdapter.SupportedDisplayModes) foreach (DisplayMode mode in GraphicsAdapter.DefaultAdapter.SupportedDisplayModes)
{ {
if (supportedDisplayModes.Any(m => m.Width == mode.Width && m.Height == mode.Height)) continue; if (supportedDisplayModes.Any(m => m.Width == mode.Width && m.Height == mode.Height)) { continue; }
#if OSX
// Monogame currently doesn't support retina displays
// so we need to disable resolutions above the viewport size.
// In a bundled .app you just disable HiDPI in the info.plist
// but that's probably not gonna happen.
if (mode.Width > GameMain.Instance.GraphicsDevice.DisplayMode.Width || mode.Height > GameMain.Instance.GraphicsDevice.DisplayMode.Height) { continue; }
#endif
supportedDisplayModes.Add(mode); supportedDisplayModes.Add(mode);
} }
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), leftColumn.RectTransform), TextManager.Get("Resolution")); new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), leftColumn.RectTransform), TextManager.Get("Resolution"));
var resolutionDD = new GUIDropDown(new RectTransform(new Vector2(1.0f, 0.05f), leftColumn.RectTransform), elementCount: supportedDisplayModes.Count) var resolutionDD = new GUIDropDown(new RectTransform(new Vector2(1.0f, 0.05f), leftColumn.RectTransform), elementCount: supportedDisplayModes.Count)
{ {
OnSelected = SelectResolution OnSelected = SelectResolution,
}; #if OSX
ButtonEnabled = GameMain.Config.WindowMode == WindowMode.Windowed
#endif
};
foreach (DisplayMode mode in supportedDisplayModes) foreach (DisplayMode mode in supportedDisplayModes)
{ {
resolutionDD.AddItem(mode.Width + "x" + mode.Height, mode); resolutionDD.AddItem(mode.Width + "x" + mode.Height, mode);
@@ -120,17 +142,33 @@ namespace Barotrauma
{ {
resolutionDD.SelectItem(GraphicsAdapter.DefaultAdapter.SupportedDisplayModes.Last()); resolutionDD.SelectItem(GraphicsAdapter.DefaultAdapter.SupportedDisplayModes.Last());
} }
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), leftColumn.RectTransform), TextManager.Get("DisplayMode")); new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), leftColumn.RectTransform), TextManager.Get("DisplayMode"));
var displayModeDD = new GUIDropDown(new RectTransform(new Vector2(1.0f, 0.05f), leftColumn.RectTransform)); var displayModeDD = new GUIDropDown(new RectTransform(new Vector2(1.0f, 0.05f), leftColumn.RectTransform));
displayModeDD.AddItem(TextManager.Get("Fullscreen"), WindowMode.Fullscreen); displayModeDD.AddItem(TextManager.Get("Fullscreen"), WindowMode.Fullscreen);
displayModeDD.AddItem(TextManager.Get("Windowed"), WindowMode.Windowed); displayModeDD.AddItem(TextManager.Get("Windowed"), WindowMode.Windowed);
#if (!OSX)
displayModeDD.AddItem(TextManager.Get("BorderlessWindowed"), WindowMode.BorderlessWindowed); displayModeDD.AddItem(TextManager.Get("BorderlessWindowed"), WindowMode.BorderlessWindowed);
displayModeDD.SelectItem(GameMain.Config.WindowMode); displayModeDD.SelectItem(GameMain.Config.WindowMode);
displayModeDD.OnSelected = (guiComponent, obj) => #else
// Fullscreen option will just set itself to borderless on macOS.
if (GameMain.Config.WindowMode == WindowMode.BorderlessWindowed)
{
displayModeDD.SelectItem(WindowMode.Fullscreen);
}
else
{
displayModeDD.SelectItem(GameMain.Config.WindowMode);
}
#endif
displayModeDD.OnSelected = (guiComponent, obj) =>
{ {
UnsavedSettings = true; UnsavedSettings = true;
GameMain.Config.WindowMode = (WindowMode)guiComponent.UserData; GameMain.Config.WindowMode = (WindowMode)guiComponent.UserData;
#if OSX
resolutionDD.ButtonEnabled = GameMain.Config.WindowMode == WindowMode.Windowed;
#endif
return true; return true;
}; };
@@ -139,6 +177,7 @@ namespace Barotrauma
GUITickBox vsyncTickBox = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.05f), leftColumn.RectTransform), TextManager.Get("EnableVSync")) GUITickBox vsyncTickBox = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.05f), leftColumn.RectTransform), TextManager.Get("EnableVSync"))
{ {
ToolTip = TextManager.Get("EnableVSyncToolTip"),
OnSelected = (GUITickBox box) => OnSelected = (GUITickBox box) =>
{ {
VSyncEnabled = box.Selected; VSyncEnabled = box.Selected;
@@ -150,7 +189,7 @@ namespace Barotrauma
}, },
Selected = VSyncEnabled Selected = VSyncEnabled
}; };
//spacing //spacing
new GUIFrame(new RectTransform(new Vector2(1.0f, 0.5f), leftColumn.RectTransform), style: null); new GUIFrame(new RectTransform(new Vector2(1.0f, 0.5f), leftColumn.RectTransform), style: null);
GUITextBlock particleLimitText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), rightColumn.RectTransform), TextManager.Get("ParticleLimit")); GUITextBlock particleLimitText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), rightColumn.RectTransform), TextManager.Get("ParticleLimit"));
@@ -188,7 +227,7 @@ namespace Barotrauma
} }
return true; return true;
}; };
//spacing //spacing
new GUIFrame(new RectTransform(new Vector2(1.0f, 0.05f), rightColumn.RectTransform), style: null); new GUIFrame(new RectTransform(new Vector2(1.0f, 0.05f), rightColumn.RectTransform), style: null);
GUITextBlock LightText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), rightColumn.RectTransform), TextManager.Get("LightMapScale")) GUITextBlock LightText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), rightColumn.RectTransform), TextManager.Get("LightMapScale"))
@@ -201,7 +240,7 @@ namespace Barotrauma
UserData = LightText, UserData = LightText,
ToolTip = TextManager.Get("LightMapScaleToolTip"), ToolTip = TextManager.Get("LightMapScaleToolTip"),
BarScroll = MathUtils.InverseLerp(0.2f, 1.0f, LightMapScale), BarScroll = MathUtils.InverseLerp(0.2f, 1.0f, LightMapScale),
OnMoved = (scrollBar, barScroll) => OnMoved = (scrollBar, barScroll) =>
{ {
ChangeSliderText(scrollBar, barScroll); ChangeSliderText(scrollBar, barScroll);
LightMapScale = MathHelper.Lerp(0.2f, 1.0f, barScroll); LightMapScale = MathHelper.Lerp(0.2f, 1.0f, barScroll);
@@ -238,7 +277,7 @@ namespace Barotrauma
return true; return true;
} }
}; };
//spacing //spacing
new GUIFrame(new RectTransform(new Vector2(1.0f, 0.05f), rightColumn.RectTransform), style: null); new GUIFrame(new RectTransform(new Vector2(1.0f, 0.05f), rightColumn.RectTransform), style: null);
@@ -282,19 +321,258 @@ namespace Barotrauma
//spacing //spacing
new GUIFrame(new RectTransform(new Vector2(1.0f, 0.2f), rightColumn.RectTransform), style: null); new GUIFrame(new RectTransform(new Vector2(1.0f, 0.2f), rightColumn.RectTransform), style: null);
/// Audio tab ----------------------------------------------------------------
var audioSliders = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.4f), tabs[(int)Tab.Audio].RectTransform, Anchor.TopCenter)
{ RelativeOffset = new Vector2(0.0f, 0.02f) })
{ RelativeSpacing = 0.01f, Stretch = true };
GUITextBlock soundVolumeText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.2f), audioSliders.RectTransform), TextManager.Get("SoundVolume"));
GUIScrollBar soundScrollBar = new GUIScrollBar(new RectTransform(new Vector2(1.0f, 0.2f), audioSliders.RectTransform),
barSize: 0.1f)
{
UserData = soundVolumeText,
BarScroll = SoundVolume,
OnMoved = (scrollBar, scroll) =>
{
ChangeSliderText(scrollBar, scroll);
SoundVolume = scroll;
return true;
},
Step = 0.05f
};
soundScrollBar.OnMoved(soundScrollBar, soundScrollBar.BarScroll);
GUITextBlock musicVolumeText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.18f), audioSliders.RectTransform), TextManager.Get("MusicVolume"));
GUIScrollBar musicScrollBar = new GUIScrollBar(new RectTransform(new Vector2(1.0f, 0.18f), audioSliders.RectTransform),
barSize: 0.1f)
{
UserData = musicVolumeText,
BarScroll = MusicVolume,
OnMoved = (scrollBar, scroll) =>
{
ChangeSliderText(scrollBar, scroll);
MusicVolume = scroll;
return true;
},
Step = 0.05f
};
musicScrollBar.OnMoved(musicScrollBar, musicScrollBar.BarScroll);
GUITextBlock voiceChatVolumeText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.18f), audioSliders.RectTransform), TextManager.Get("VoiceChatVolume"));
GUIScrollBar voiceChatScrollBar = new GUIScrollBar(new RectTransform(new Vector2(1.0f, 0.18f), audioSliders.RectTransform),
barSize: 0.1f)
{
UserData = voiceChatVolumeText,
BarScroll = VoiceChatVolume,
OnMoved = (scrollBar, scroll) =>
{
ChangeSliderText(scrollBar, scroll);
VoiceChatVolume = scroll;
return true;
},
Step = 0.05f
};
voiceChatScrollBar.OnMoved(voiceChatScrollBar, voiceChatScrollBar.BarScroll);
GUITickBox muteOnFocusLostBox = new GUITickBox(new RectTransform(new Vector2(0.95f, 0.15f), audioSliders.RectTransform), TextManager.Get("MuteOnFocusLost"));
muteOnFocusLostBox.Selected = MuteOnFocusLost;
muteOnFocusLostBox.ToolTip = TextManager.Get("MuteOnFocusLostToolTip");
muteOnFocusLostBox.OnSelected = (tickBox) =>
{
MuteOnFocusLost = tickBox.Selected;
return true;
};
var voiceSettings = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.5f), tabs[(int)Tab.Audio].RectTransform, Anchor.BottomCenter)
{ RelativeOffset = new Vector2(0.0f, 0.04f) })
{ RelativeSpacing = 0.01f, Stretch = true };
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.1f), voiceSettings.RectTransform), TextManager.Get("VoiceChat"));
//spacing
new GUIFrame(new RectTransform(new Vector2(1.0f, 0.2f), rightColumn.RectTransform), style: null);
IList<string> deviceNames = Alc.GetString((IntPtr)null, AlcGetStringList.CaptureDeviceSpecifier);
foreach (string name in deviceNames)
{
DebugConsole.NewMessage(name + " " + name.Length.ToString(), Color.Lime);
}
if (string.IsNullOrWhiteSpace(VoiceCaptureDevice)) VoiceCaptureDevice = deviceNames[0];
#if (!OSX)
var deviceList = new GUIDropDown(new RectTransform(new Vector2(1.0f, 0.2f), voiceSettings.RectTransform), VoiceCaptureDevice, deviceNames.Count);
foreach (string name in deviceNames)
{
deviceList.AddItem(name, name);
}
deviceList.OnSelected = (GUIComponent selected, object obj) =>
{
string name = obj as string;
if (VoiceCaptureDevice == name) return true;
VoipCapture.ChangeCaptureDevice(name);
return true;
};
#else
var suavemente = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.2f), voiceSettings.RectTransform), TextManager.Get("CurrentDevice") + ": " + VoiceCaptureDevice)
{
ToolTip = TextManager.Get("CurrentDeviceToolTip.OSX"),
TextAlignment = Alignment.CenterX
};
new GUIButton(new RectTransform(new Vector2(1.0f, 0.25f), voiceSettings.RectTransform), TextManager.Get("RefreshDefaultDevice"))
{
ToolTip = TextManager.Get("RefreshDefaultDeviceToolTip"),
OnClicked = (bt, userdata) =>
{
deviceNames = Alc.GetString((IntPtr)null, AlcGetStringList.CaptureDeviceSpecifier);
if (VoiceCaptureDevice == deviceNames[0]) return true;
VoipCapture.ChangeCaptureDevice(deviceNames[0]);
suavemente.Text = TextManager.Get("CurrentDevice") + ": " + VoiceCaptureDevice;
suavemente.Flash(Color.Blue);
return true;
}
};
#endif
var radioButtonFrame = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.6f), voiceSettings.RectTransform))
{
Stretch = true,
RelativeSpacing = 0.05f
};
GUIRadioButtonGroup voiceMode = new GUIRadioButtonGroup();
for (int i = 0; i < 3; i++)
{
string langStr = "VoiceMode." + ((VoiceMode)i).ToString();
var tick = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.33f), radioButtonFrame.RectTransform), TextManager.Get(langStr))
{
ToolTip = TextManager.Get(langStr + "ToolTip")
};
voiceMode.AddRadioButton((VoiceMode)i, tick);
}
var voiceInputContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.5f, 0.2f), voiceSettings.RectTransform, Anchor.BottomCenter));
new GUITextBlock(new RectTransform(new Vector2(0.6f, 1.0f), voiceInputContainer.RectTransform), TextManager.Get("InputType.Voice") + ": ");
var voiceKeyBox = new GUITextBox(new RectTransform(new Vector2(0.4f, 1.0f), voiceInputContainer.RectTransform, Anchor.TopRight),
text: keyMapping[(int)InputType.Voice].ToString())
{
UserData = InputType.Voice
};
voiceKeyBox.OnSelected += KeyBoxSelected;
voiceKeyBox.SelectedColor = Color.Gold * 0.3f;
var voiceActivityGroup = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.3f), voiceSettings.RectTransform));
GUITextBlock noiseGateText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), voiceActivityGroup.RectTransform), TextManager.Get("NoiseGateThreshold"))
{
TextGetter = () =>
{
return TextManager.Get("NoiseGateThreshold") + " " + ((int)NoiseGateThreshold).ToString() + " dB";
}
};
var dbMeter = new GUIProgressBar(new RectTransform(new Vector2(1.0f, 0.5f), voiceActivityGroup.RectTransform), 0.0f, Color.Lime);
dbMeter.ProgressGetter = () =>
{
if (VoipCapture.Instance == null) return 0.0f;
dbMeter.Color = VoipCapture.Instance.LastdB > NoiseGateThreshold ? Color.Lime : Color.Orange; //TODO: i'm a filthy hack
return ((float)VoipCapture.Instance.LastdB + 100.0f) / 100.0f;
};
var noiseGateSlider = new GUIScrollBar(new RectTransform(new Vector2(1.0f, 1.0f), dbMeter.RectTransform, Anchor.Center), color: Color.White, barSize: 0.03f);
noiseGateSlider.Frame.Visible = false;
noiseGateSlider.Step = 0.01f;
noiseGateSlider.Range = new Vector2(-100.0f, 0.0f);
noiseGateSlider.BarScrollValue = NoiseGateThreshold;
noiseGateSlider.OnMoved = (GUIScrollBar scrollBar, float barScroll) =>
{
NoiseGateThreshold = scrollBar.BarScrollValue;
UnsavedSettings = true;
return true;
};
voiceMode.OnSelect = (GUIRadioButtonGroup rbg, Enum value) =>
{
if (rbg.Selected != null && rbg.Selected.Equals(value)) return;
VoiceMode vMode = (VoiceMode)value;
VoiceSetting = vMode;
if (vMode == VoiceMode.Activity)
{
voiceActivityGroup.Visible = true;
if (GameMain.Client == null && VoipCapture.Instance == null)
{
VoipCapture.Create(GameMain.Config.VoiceCaptureDevice);
}
}
else
{
voiceActivityGroup.Visible = false;
if (GameMain.Client == null)
{
VoipCapture.Instance?.Dispose();
}
}
voiceInputContainer.Visible = (vMode == VoiceMode.PushToTalk);
UnsavedSettings = true;
};
voiceMode.Selected = VoiceSetting;
/// Controls tab -------------------------------------------------------------
var controlsLayoutGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.95f), tabs[(int)Tab.Controls].RectTransform, Anchor.Center)
{ RelativeOffset = new Vector2(0.0f, 0.0f) })
{ RelativeSpacing = 0.01f, Stretch = true };
var inputFrame = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.8f), controlsLayoutGroup.RectTransform))
{
Stretch = true
};
var inputNames = Enum.GetValues(typeof(InputType));
for (int i = 0; i < inputNames.Length; i++)
{
var inputContainer = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.06f), inputFrame.RectTransform), style: null);
new GUITextBlock(new RectTransform(new Vector2(0.6f, 1.0f), inputContainer.RectTransform), TextManager.Get("InputType." + ((InputType)i)) + ": ", font: GUI.SmallFont);
var keyBox = new GUITextBox(new RectTransform(new Vector2(0.4f, 1.0f), inputContainer.RectTransform, Anchor.TopRight),
text: keyMapping[i].ToString(), font: GUI.SmallFont)
{
UserData = i
};
keyBox.OnSelected += KeyBoxSelected;
keyBox.SelectedColor = Color.Gold * 0.3f;
}
GUITextBlock aimAssistText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), controlsLayoutGroup.RectTransform), TextManager.Get("AimAssist"));
GUIScrollBar aimAssistSlider = new GUIScrollBar(new RectTransform(new Vector2(1.0f, 0.05f), controlsLayoutGroup.RectTransform),
barSize: 0.1f)
{
UserData = aimAssistText,
BarScroll = MathUtils.InverseLerp(0.0f, 5.0f, AimAssistAmount),
OnMoved = (scrollBar, scroll) =>
{
ChangeSliderText(scrollBar, scroll);
AimAssistAmount = MathHelper.Lerp(0.0f, 5.0f, scroll);
return true;
},
Step = 0.1f
};
aimAssistSlider.OnMoved(aimAssistSlider, aimAssistSlider.BarScroll);
/// General tab -------------------------------------------------------------- /// General tab --------------------------------------------------------------
leftColumn = new GUILayoutGroup(new RectTransform(new Vector2(0.46f, 0.95f), tabs[(int)Tab.General].RectTransform, Anchor.CenterLeft) var generalLayoutGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.95f), tabs[(int)Tab.General].RectTransform, Anchor.Center)
{ RelativeOffset = new Vector2(0.02f, 0.0f) }) { RelativeSpacing = 0.01f, Stretch = true }; { RelativeOffset = new Vector2(0.0f, 0.0f) }) { RelativeSpacing = 0.01f, Stretch = true };
rightColumn = new GUILayoutGroup(new RectTransform(new Vector2(0.46f, 0.95f), tabs[(int)Tab.General].RectTransform, Anchor.CenterRight)
{ RelativeOffset = new Vector2(0.02f, 0.0f) }) { RelativeSpacing = 0.01f, Stretch = true };
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), leftColumn.RectTransform), TextManager.Get("ContentPackages")); new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), generalLayoutGroup.RectTransform), TextManager.Get("ContentPackages"));
var contentPackageList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.4f), leftColumn.RectTransform)) var contentPackageList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.4f), generalLayoutGroup.RectTransform))
{ {
CanBeFocused = false CanBeFocused = false
}; };
foreach (ContentPackage contentPackage in ContentPackage.List) foreach (ContentPackage contentPackage in ContentPackage.List)
{ {
var tickBox = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.1f), contentPackageList.Content.RectTransform, minSize: new Point(0, 15)), contentPackage.Name) var tickBox = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.1f), contentPackageList.Content.RectTransform, minSize: new Point(0, 15)), contentPackage.Name)
@@ -321,84 +599,6 @@ namespace Barotrauma
.Replace("[missingfiletypes]", string.Join(", ", missingContentTypes)); .Replace("[missingfiletypes]", string.Join(", ", missingContentTypes));
} }
} }
//spacing
new GUIFrame(new RectTransform(new Vector2(1.0f, 0.02f), leftColumn.RectTransform), style: null);
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), leftColumn.RectTransform), TextManager.Get("Language"));
var languageDD = new GUIDropDown(new RectTransform(new Vector2(1.0f, 0.05f), leftColumn.RectTransform));
foreach (string language in TextManager.AvailableLanguages)
{
languageDD.AddItem(language, language);
}
languageDD.SelectItem(TextManager.Language);
languageDD.OnSelected = (guiComponent, obj) =>
{
string newLanguage = obj as string;
if (newLanguage == Language) return true;
UnsavedSettings = true;
Language = newLanguage;
new GUIMessageBox(TextManager.Get("RestartRequiredLabel"), TextManager.Get("RestartRequiredLanguage"));
return true;
};
//spacing
new GUIFrame(new RectTransform(new Vector2(1.0f, 0.02f), leftColumn.RectTransform), style: null);
GUITextBlock soundVolumeText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), leftColumn.RectTransform), TextManager.Get("SoundVolume"));
GUIScrollBar soundScrollBar = new GUIScrollBar(new RectTransform(new Vector2(1.0f, 0.05f), leftColumn.RectTransform),
barSize: 0.1f)
{
UserData = soundVolumeText,
BarScroll = SoundVolume,
OnMoved = (scrollBar, scroll) =>
{
ChangeSliderText(scrollBar, scroll);
SoundVolume = scroll;
return true;
},
Step = 0.05f
};
soundScrollBar.OnMoved(soundScrollBar, soundScrollBar.BarScroll);
GUITextBlock musicVolumeText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), leftColumn.RectTransform), TextManager.Get("MusicVolume"));
GUIScrollBar musicScrollBar = new GUIScrollBar(new RectTransform(new Vector2(1.0f, 0.05f), leftColumn.RectTransform),
barSize: 0.1f)
{
UserData = musicVolumeText,
BarScroll = MusicVolume,
OnMoved = (scrollBar, scroll) =>
{
ChangeSliderText(scrollBar, scroll);
MusicVolume = scroll;
return true;
},
Step = 0.05f
};
musicScrollBar.OnMoved(musicScrollBar, musicScrollBar.BarScroll);
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), rightColumn.RectTransform), TextManager.Get("Controls"));
var inputFrame = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.8f), rightColumn.RectTransform))
{
Stretch = true
};
var inputNames = Enum.GetValues(typeof(InputType));
for (int i = 0; i < inputNames.Length; i++)
{
var inputContainer = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.06f), inputFrame.RectTransform), style: null);
new GUITextBlock(new RectTransform(new Vector2(0.6f, 1.0f), inputContainer.RectTransform), TextManager.Get("InputType." + ((InputType)i)) + ": ", font: GUI.SmallFont);
var keyBox = new GUITextBox(new RectTransform(new Vector2(0.4f, 1.0f), inputContainer.RectTransform, Anchor.TopRight),
text: keyMapping[i].ToString(), font: GUI.SmallFont)
{
UserData = i
};
keyBox.OnSelected += KeyBoxSelected;
keyBox.SelectedColor = Color.Gold * 0.3f;
}
GUITextBlock aimAssistText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), rightColumn.RectTransform), TextManager.Get("AimAssist")); GUITextBlock aimAssistText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), rightColumn.RectTransform), TextManager.Get("AimAssist"));
GUIScrollBar aimAssistSlider = new GUIScrollBar(new RectTransform(new Vector2(1.0f, 0.05f), rightColumn.RectTransform), GUIScrollBar aimAssistSlider = new GUIScrollBar(new RectTransform(new Vector2(1.0f, 0.05f), rightColumn.RectTransform),
barSize: 0.1f) barSize: 0.1f)
@@ -415,14 +615,43 @@ namespace Barotrauma
}; };
aimAssistSlider.OnMoved(aimAssistSlider, aimAssistSlider.BarScroll); aimAssistSlider.OnMoved(aimAssistSlider, aimAssistSlider.BarScroll);
//spacing
new GUIFrame(new RectTransform(new Vector2(1.0f, 0.02f), generalLayoutGroup.RectTransform), style: null);
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), generalLayoutGroup.RectTransform), TextManager.Get("Language"));
var languageDD = new GUIDropDown(new RectTransform(new Vector2(1.0f, 0.05f), generalLayoutGroup.RectTransform));
foreach (string language in TextManager.AvailableLanguages)
{
languageDD.AddItem(TextManager.Get("Language." + language), language);
}
languageDD.SelectItem(TextManager.Language);
languageDD.OnSelected = (guiComponent, obj) =>
{
string newLanguage = obj as string;
if (newLanguage == Language) return true;
UnsavedSettings = true;
Language = newLanguage;
new GUIMessageBox(TextManager.Get("RestartRequiredLabel"), TextManager.Get("RestartRequiredLanguage"));
return true;
};
//spacing
new GUIFrame(new RectTransform(new Vector2(1.0f, 0.02f), generalLayoutGroup.RectTransform), style: null);
new GUIButton(new RectTransform(new Vector2(0.4f, 1.0f), buttonArea.RectTransform, Anchor.BottomLeft), new GUIButton(new RectTransform(new Vector2(0.4f, 1.0f), buttonArea.RectTransform, Anchor.BottomLeft),
TextManager.Get("Cancel")) TextManager.Get("Cancel"))
{ {
IgnoreLayoutGroups = true, IgnoreLayoutGroups = true,
OnClicked = (x, y) => OnClicked = (x, y) =>
{ {
if (GameMain.Config.UnsavedSettings) GameMain.Config.Load("config.xml"); if (UnsavedSettings)
if (Screen.Selected == GameMain.MainMenuScreen) GameMain.MainMenuScreen.SelectTab(0); {
LoadPlayerConfig();
}
if (Screen.Selected == GameMain.MainMenuScreen) GameMain.MainMenuScreen.ReturnToMainMenu(null, null);
GUI.SettingsMenuOpen = false; GUI.SettingsMenuOpen = false;
return true; return true;
} }
@@ -436,11 +665,30 @@ namespace Barotrauma
}; };
applyButton.OnClicked = ApplyClicked; applyButton.OnClicked = ApplyClicked;
UnsavedSettings = false; // Reset unsaved settings to false once the UI has been created
SelectTab(Tab.General); SelectTab(Tab.General);
} }
private void SelectTab(Tab tab) private void SelectTab(Tab tab)
{ {
switch (tab)
{
case Tab.Audio:
if (VoiceSetting == VoiceMode.Activity)
{
if (GameMain.Client == null && VoipCapture.Instance == null)
{
VoipCapture.Create(GameMain.Config.VoiceCaptureDevice);
}
}
break;
default:
if (GameMain.Client == null)
{
VoipCapture.Instance?.Dispose();
}
break;
}
for (int i = 0; i < tabs.Length; i++) for (int i = 0; i < tabs.Length; i++)
{ {
tabs[i].Visible = (Tab)tabs[i].UserData == tab; tabs[i].Visible = (Tab)tabs[i].UserData == tab;
@@ -453,7 +701,7 @@ namespace Barotrauma
textBox.Text = ""; textBox.Text = "";
CoroutineManager.StartCoroutine(WaitForKeyPress(textBox)); CoroutineManager.StartCoroutine(WaitForKeyPress(textBox));
} }
private bool SelectResolution(GUIComponent selected, object userData) private bool SelectResolution(GUIComponent selected, object userData)
{ {
DisplayMode mode = selected.UserData as DisplayMode; DisplayMode mode = selected.UserData as DisplayMode;
@@ -512,14 +760,15 @@ namespace Barotrauma
private IEnumerable<object> WaitForKeyPress(GUITextBox keyBox) private IEnumerable<object> WaitForKeyPress(GUITextBox keyBox)
{ {
yield return CoroutineStatus.Running; yield return CoroutineStatus.Running;
while (PlayerInput.LeftButtonHeld() || PlayerInput.LeftButtonClicked()) while (PlayerInput.LeftButtonHeld() || PlayerInput.LeftButtonClicked())
{ {
//wait for the mouse to be released, so that we don't interpret clicking on the textbox as the keybinding //wait for the mouse to be released, so that we don't interpret clicking on the textbox as the keybinding
yield return CoroutineStatus.Running; yield return CoroutineStatus.Running;
} }
while (keyBox.Selected && PlayerInput.GetKeyboardState.GetPressedKeys().Length == 0 && while (keyBox.Selected && PlayerInput.GetKeyboardState.GetPressedKeys().Length == 0 &&
!PlayerInput.LeftButtonClicked() && !PlayerInput.RightButtonClicked() && !PlayerInput.MidButtonClicked()) !PlayerInput.LeftButtonClicked() && !PlayerInput.RightButtonClicked() && !PlayerInput.MidButtonClicked() &&
!PlayerInput.Mouse4ButtonClicked() && !PlayerInput.Mouse5ButtonClicked() && !PlayerInput.MouseWheelUpClicked() && !PlayerInput.MouseWheelDownClicked())
{ {
if (Screen.Selected != GameMain.MainMenuScreen && !GUI.SettingsMenuOpen) yield return CoroutineStatus.Success; if (Screen.Selected != GameMain.MainMenuScreen && !GUI.SettingsMenuOpen) yield return CoroutineStatus.Success;
@@ -545,6 +794,26 @@ namespace Barotrauma
keyMapping[keyIndex] = new KeyOrMouse(2); keyMapping[keyIndex] = new KeyOrMouse(2);
keyBox.Text = "Mouse3"; keyBox.Text = "Mouse3";
} }
else if (PlayerInput.Mouse4ButtonClicked())
{
keyMapping[keyIndex] = new KeyOrMouse(3);
keyBox.Text = "Mouse4";
}
else if (PlayerInput.Mouse5ButtonClicked())
{
keyMapping[keyIndex] = new KeyOrMouse(4);
keyBox.Text = "Mouse5";
}
else if (PlayerInput.MouseWheelUpClicked())
{
keyMapping[keyIndex] = new KeyOrMouse(5);
keyBox.Text = "MouseWheelUp";
}
else if (PlayerInput.MouseWheelDownClicked())
{
keyMapping[keyIndex] = new KeyOrMouse(6);
keyBox.Text = "MouseWheelDown";
}
else if (PlayerInput.GetKeyboardState.GetPressedKeys().Length > 0) else if (PlayerInput.GetKeyboardState.GetPressedKeys().Length > 0)
{ {
Keys key = PlayerInput.GetKeyboardState.GetPressedKeys()[0]; Keys key = PlayerInput.GetKeyboardState.GetPressedKeys()[0];
@@ -560,21 +829,28 @@ namespace Barotrauma
yield return CoroutineStatus.Success; yield return CoroutineStatus.Success;
} }
private bool ApplyClicked(GUIButton button, object userData) private bool ApplyClicked(GUIButton button, object userData)
{ {
Save(); SaveNewPlayerConfig();
settingsFrame.Flash(Color.Green); settingsFrame.Flash(Color.Green);
if (GameMain.WindowMode != GameMain.Config.WindowMode) if (GameMain.WindowMode != GameMain.Config.WindowMode)
{ {
GameMain.Instance.SetWindowMode(GameMain.Config.WindowMode); GameMain.Instance.ApplyGraphicsSettings();
} }
if (GameMain.GraphicsWidth != GameMain.Config.GraphicsWidth || GameMain.GraphicsHeight != GameMain.Config.GraphicsHeight) if (GameMain.GraphicsWidth != GameMain.Config.GraphicsWidth || GameMain.GraphicsHeight != GameMain.Config.GraphicsHeight)
{ {
new GUIMessageBox(TextManager.Get("RestartRequiredLabel"), TextManager.Get("RestartRequiredResolution")); #if OSX
if (GameMain.Config.WindowMode != WindowMode.BorderlessWindowed)
{
#endif
new GUIMessageBox(TextManager.Get("RestartRequiredLabel"), TextManager.Get("RestartRequiredResolution"));
#if OSX
}
#endif
} }
if (Screen.Selected != GameMain.MainMenuScreen) GUI.SettingsMenuOpen = false; if (Screen.Selected != GameMain.MainMenuScreen) GUI.SettingsMenuOpen = false;
@@ -458,8 +458,8 @@ namespace Barotrauma
slots[i].QuickUseTimer = Math.Max(0.1f, slots[i].QuickUseTimer + deltaTime); slots[i].QuickUseTimer = Math.Max(0.1f, slots[i].QuickUseTimer + deltaTime);
if (slots[i].QuickUseTimer >= 1.0f) if (slots[i].QuickUseTimer >= 1.0f)
{ {
CreateNetworkEvent();
Items[i].Drop(Character.Controlled); Items[i].Drop(Character.Controlled);
GUI.PlayUISound(GUISoundType.DropItem);
} }
} }
else else
@@ -4,7 +4,6 @@ using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Graphics;
using System; using System;
namespace Barotrauma.Items.Components namespace Barotrauma.Items.Components
{ {
partial class Door : Pickable, IDrawableComponent, IServerSerializable partial class Door : Pickable, IDrawableComponent, IServerSerializable
@@ -12,6 +11,15 @@ namespace Barotrauma.Items.Components
private ConvexHull convexHull; private ConvexHull convexHull;
private ConvexHull convexHull2; private ConvexHull convexHull2;
//openState when the vertices of the convex hull were last calculated
private float lastConvexHullState;
public Vector2 DrawSize
{
//use the extents of the item as the draw size
get { return Vector2.Zero; }
}
private Vector2[] GetConvexHullCorners(Rectangle rect) private Vector2[] GetConvexHullCorners(Rectangle rect)
{ {
Vector2[] corners = new Vector2[4]; Vector2[] corners = new Vector2[4];
@@ -32,7 +40,7 @@ namespace Barotrauma.Items.Components
(int)(doorSprite.size.Y * item.Scale)); (int)(doorSprite.size.Y * item.Scale));
Rectangle rect = doorRect; Rectangle rect = doorRect;
if (isHorizontal) if (IsHorizontal)
{ {
rect.Width = (int)(rect.Width * (1.0f - openState)); rect.Width = (int)(rect.Width * (1.0f - openState));
} }
@@ -41,9 +49,9 @@ namespace Barotrauma.Items.Components
rect.Height = (int)(rect.Height * (1.0f - openState)); rect.Height = (int)(rect.Height * (1.0f - openState));
} }
if (window.Height > 0 && window.Width > 0) if (Window.Height > 0 && Window.Width > 0)
{ {
rect.Height = -(int)(window.Y * item.Scale); rect.Height = -(int)(Window.Y * item.Scale);
rect.Y += (int)(doorRect.Height * openState); rect.Y += (int)(doorRect.Height * openState);
rect.Height = Math.Max(rect.Height - (rect.Y - doorRect.Y), 0); rect.Height = Math.Max(rect.Height - (rect.Y - doorRect.Y), 0);
@@ -52,7 +60,7 @@ namespace Barotrauma.Items.Components
if (convexHull2 != null) if (convexHull2 != null)
{ {
Rectangle rect2 = doorRect; Rectangle rect2 = doorRect;
rect2.Y = rect2.Y + (int)((window.Y * item.Scale - window.Height * item.Scale)); rect2.Y = rect2.Y + (int)((Window.Y * item.Scale - Window.Height * item.Scale));
rect2.Y += (int)(doorRect.Height * openState); rect2.Y += (int)(doorRect.Height * openState);
rect2.Y = Math.Min(doorRect.Y, rect2.Y); rect2.Y = Math.Min(doorRect.Y, rect2.Y);
@@ -105,11 +113,11 @@ namespace Barotrauma.Items.Components
if (openState == 1.0f) if (openState == 1.0f)
{ {
body.Enabled = false; Body.Enabled = false;
return; return;
} }
if (isHorizontal) if (IsHorizontal)
{ {
Vector2 pos = new Vector2(item.Rect.X, item.Rect.Y - item.Rect.Height / 2); Vector2 pos = new Vector2(item.Rect.X, item.Rect.Y - item.Rect.Height / 2);
if (item.Submarine != null) pos += item.Submarine.DrawPosition; if (item.Submarine != null) pos += item.Submarine.DrawPosition;
@@ -159,9 +167,49 @@ namespace Barotrauma.Items.Components
(int)brokenSprite.size.X, (int)(brokenSprite.size.Y * (1.0f - openState))), (int)brokenSprite.size.X, (int)(brokenSprite.size.Y * (1.0f - openState))),
color * alpha, 0.0f, brokenSprite.Origin, scale * item.Scale, SpriteEffects.None, brokenSprite.Depth); color * alpha, 0.0f, brokenSprite.Origin, scale * item.Scale, SpriteEffects.None, brokenSprite.Depth);
} }
}
}
partial void SetState(bool open, bool isNetworkMessage, bool sendNetworkMessage)
{
if (isStuck ||
(PredictedState == null && isOpen == open) ||
(PredictedState != null && isOpen == PredictedState.Value && isOpen == open))
{
return;
} }
if (GameMain.Client != null && !isNetworkMessage)
{
bool stateChanged = open != PredictedState;
//clients can "predict" that the door opens/closes when a signal is received
//the prediction will be reset after 1 second, setting the door to a state
//sent by the server, or reverting it back to its old state if no msg from server was received
PredictedState = open;
resetPredictionTimer = CorrectionDelay;
if (stateChanged) PlaySound(ActionType.OnUse, item.WorldPosition);
}
else
{
isOpen = open;
if (!isNetworkMessage || open != PredictedState) PlaySound(ActionType.OnUse, item.WorldPosition);
}
//opening a partially stuck door makes it less stuck
if (isOpen) stuck = MathHelper.Clamp(stuck - 30.0f, 0.0f, 100.0f);
}
public override void ClientRead(ServerNetObject type, Lidgren.Network.NetBuffer msg, float sendingTime)
{
base.ClientRead(type, msg, sendingTime);
SetState(msg.ReadBoolean(), isNetworkMessage: true, sendNetworkMessage: false);
Stuck = msg.ReadRangedSingle(0.0f, 100.0f, 8);
PredictedState = null;
} }
} }
} }
@@ -35,7 +35,15 @@ namespace Barotrauma.Items.Components
get { return RoundSound.Range; } get { return RoundSound.Range; }
} }
public float VolumeMultiplier
{
get { return RoundSound.Volume; }
}
public float Range
{
get { return RoundSound.Range; }
}
public readonly bool Loop; public readonly bool Loop;
@@ -309,15 +317,15 @@ namespace Barotrauma.Items.Components
private float GetSoundVolume(ItemSound sound) private float GetSoundVolume(ItemSound sound)
{ {
if (sound == null) return 0.0f; if (sound == null) { return 0.0f; }
if (sound.VolumeProperty == "") return 1.0f; if (sound.VolumeProperty == "") { return sound.VolumeMultiplier; }
if (properties.TryGetValue(sound.VolumeProperty.ToLowerInvariant(), out SerializableProperty property)) if (properties.TryGetValue(sound.VolumeProperty, out SerializableProperty property))
{ {
float newVolume = 0.0f; float newVolume = 0.0f;
try try
{ {
newVolume = (float)property.GetValue(); newVolume = (float)property.GetValue(this);
} }
catch catch
{ {
@@ -353,7 +361,7 @@ namespace Barotrauma.Items.Components
{ {
return null; return null;
} }
foreach (ItemComponent component in item.components) foreach (ItemComponent component in item.Components)
{ {
if (component.name.ToLower() == LinkUIToComponent.ToLower()) if (component.name.ToLower() == LinkUIToComponent.ToLower())
{ {
@@ -427,9 +435,10 @@ namespace Barotrauma.Items.Components
} }
RoundSound sound = Submarine.LoadRoundSound(subElement); RoundSound sound = Submarine.LoadRoundSound(subElement);
if (sound == null) { break; }
ItemSound itemSound = new ItemSound(sound, type, subElement.GetAttributeBool("loop", false)) ItemSound itemSound = new ItemSound(sound, type, subElement.GetAttributeBool("loop", false))
{ {
VolumeProperty = subElement.GetAttributeString("volumeproperty", "") VolumeProperty = subElement.GetAttributeString("volumeproperty", "").ToLowerInvariant()
}; };
if (soundSelectionModes == null) soundSelectionModes = new Dictionary<ActionType, SoundSelectionMode>(); if (soundSelectionModes == null) soundSelectionModes = new Dictionary<ActionType, SoundSelectionMode>();
@@ -72,7 +72,13 @@ namespace Barotrauma.Items.Components
get; get;
set; set;
} }
public Vector2 DrawSize
{
//use the extents of the item as the draw size
get { return Vector2.Zero; }
}
partial void InitProjSpecific(XElement element) partial void InitProjSpecific(XElement element)
{ {
foreach (XElement subElement in element.Elements()) foreach (XElement subElement in element.Elements())
@@ -169,9 +175,10 @@ namespace Barotrauma.Items.Components
item.IsHighlighted = false; item.IsHighlighted = false;
} }
if (containedItem.body != null) if (containedItem.body != null &&
Math.Abs(containedItem.body.FarseerBody.Rotation - currentRotation) > 0.001f)
{ {
containedItem.body.FarseerBody.Rotation = currentRotation; containedItem.body.SetTransformIgnoreContacts(containedItem.body.SimPosition, currentRotation);
} }
containedItem.Sprite.Draw( containedItem.Sprite.Draw(
@@ -209,6 +209,7 @@ namespace Barotrauma.Items.Components
return; return;
} }
textBlock.TextDepth = item.SpriteDepth - 0.0001f;
textBlock.TextOffset = drawPos - textBlock.Rect.Location.ToVector2() + new Vector2(scrollAmount + scrollPadding, 0.0f); textBlock.TextOffset = drawPos - textBlock.Rect.Location.ToVector2() + new Vector2(scrollAmount + scrollPadding, 0.0f);
textBlock.DrawManually(spriteBatch); textBlock.DrawManually(spriteBatch);
} }
@@ -8,6 +8,11 @@ namespace Barotrauma.Items.Components
{ {
partial class LightComponent : Powered, IServerSerializable, IDrawableComponent partial class LightComponent : Powered, IServerSerializable, IDrawableComponent
{ {
public Vector2 DrawSize
{
get { return new Vector2(light.Range * 2, light.Range * 2); }
}
private LightSource light; private LightSource light;
public LightSource Light public LightSource Light
{ {
@@ -8,7 +8,7 @@ namespace Barotrauma.Items.Components
{ {
if (focusTarget != null && character.ViewTarget == focusTarget) if (focusTarget != null && character.ViewTarget == focusTarget)
{ {
foreach (ItemComponent ic in focusTarget.components) foreach (ItemComponent ic in focusTarget.Components)
{ {
ic.DrawHUD(spriteBatch, character); ic.DrawHUD(spriteBatch, character);
} }
@@ -79,12 +79,8 @@ namespace Barotrauma.Items.Components
SetActive(!IsActive, Character.Controlled); SetActive(!IsActive, Character.Controlled);
currPowerConsumption = IsActive ? powerConsumption : 0.0f; currPowerConsumption = IsActive ? powerConsumption : 0.0f;
if (GameMain.Server != null) if (GameMain.Client != null)
{
item.CreateServerEvent(this);
}
else if (GameMain.Client != null)
{ {
item.CreateClientEvent(this); item.CreateClientEvent(this);
} }
@@ -22,6 +22,12 @@ namespace Barotrauma.Items.Components
private set; private set;
} }
public Vector2 DrawSize
{
//use the extents of the item as the draw size
get { return Vector2.Zero; }
}
partial void InitProjSpecific(XElement element) partial void InitProjSpecific(XElement element)
{ {
powerIndicator = new GUITickBox(new RectTransform(new Point(30, 30), GuiFrame.RectTransform) { RelativeOffset = new Vector2(0.05f, 0.15f) }, powerIndicator = new GUITickBox(new RectTransform(new Point(30, 30), GuiFrame.RectTransform) { RelativeOffset = new Vector2(0.05f, 0.15f) },
@@ -51,12 +57,8 @@ namespace Barotrauma.Items.Components
if (Math.Abs(newTargetForce - targetForce) < 0.01) return false; if (Math.Abs(newTargetForce - targetForce) < 0.01) return false;
targetForce = newTargetForce; targetForce = newTargetForce;
if (GameMain.Server != null)
{ if (GameMain.Client != null)
item.CreateServerEvent(this);
GameServer.Log(Character.Controlled.LogName + " set the force speed of " + item.Name + " to " + (int)(targetForce) + " %", ServerLog.MessageType.ItemInteraction);
}
else if (GameMain.Client != null)
{ {
correctionTimer = CorrectionDelay; correctionTimer = CorrectionDelay;
item.CreateClientEvent(this); item.CreateClientEvent(this);
@@ -306,13 +306,6 @@ namespace Barotrauma.Items.Components
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedFrame.RectTransform), text, new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedFrame.RectTransform), text,
textColor: inadequateSkills.Any() ? Color.Red : Color.LightGreen, font: GUI.SmallFont); textColor: inadequateSkills.Any() ? Color.Red : Color.LightGreen, font: GUI.SmallFont);
} }
if (tooltip != null)
{
GUIComponent.DrawToolTip(spriteBatch, tooltip.Second, tooltip.First);
tooltip = null;
}
}
float degreeOfSuccess = user == null ? 0.0f : DegreeOfSuccess(user, selectedItem.RequiredSkills); float degreeOfSuccess = user == null ? 0.0f : DegreeOfSuccess(user, selectedItem.RequiredSkills);
if (degreeOfSuccess > 0.5f) { degreeOfSuccess = 1.0f; } if (degreeOfSuccess > 0.5f) { degreeOfSuccess = 1.0f; }
@@ -343,11 +336,7 @@ namespace Barotrauma.Items.Components
CancelFabricating(Character.Controlled); CancelFabricating(Character.Controlled);
} }
if (GameMain.Server != null) if (GameMain.Client != null)
{
item.CreateServerEvent(this);
}
else if (GameMain.Client != null)
{ {
item.CreateClientEvent(this); item.CreateClientEvent(this);
} }
@@ -79,7 +79,7 @@ namespace Barotrauma.Items.Components
CreateHUD(); CreateHUD();
} }
float distort = 1.0f - item.Condition / 100.0f; float distort = 1.0f - item.Condition / item.Prefab.Health;
foreach (HullData hullData in hullDatas.Values) foreach (HullData hullData in hullDatas.Values)
{ {
hullData.DistortionTimer -= deltaTime; hullData.DistortionTimer -= deltaTime;
@@ -59,12 +59,7 @@ namespace Barotrauma.Items.Components
IsActive = active; IsActive = active;
if (!IsActive) currPowerConsumption = 0.0f; if (!IsActive) currPowerConsumption = 0.0f;
if (GameMain.Server != null) if (GameMain.Client != null)
{
item.CreateServerEvent(this);
GameServer.Log(Character.Controlled.LogName + (IsActive ? " turned on " : " turned off ") + item.Name, ServerLog.MessageType.ItemInteraction);
}
else if (GameMain.Client != null)
{ {
correctionTimer = CorrectionDelay; correctionTimer = CorrectionDelay;
item.CreateClientEvent(this); item.CreateClientEvent(this);
@@ -102,12 +97,8 @@ namespace Barotrauma.Items.Components
if (Math.Abs(newValue - FlowPercentage) < 0.1f) return false; if (Math.Abs(newValue - FlowPercentage) < 0.1f) return false;
FlowPercentage = newValue; FlowPercentage = newValue;
if (GameMain.Server != null)
{ if (GameMain.Client != null)
item.CreateServerEvent(this);
GameServer.Log(Character.Controlled.LogName + " set the pumping speed of " + item.Name + " to " + (int)(flowPercentage) + " %", ServerLog.MessageType.ItemInteraction);
}
else if (GameMain.Client != null)
{ {
correctionTimer = CorrectionDelay; correctionTimer = CorrectionDelay;
item.CreateClientEvent(this); item.CreateClientEvent(this);
@@ -162,10 +162,6 @@ namespace Barotrauma.Items.Components
OnMoved = (GUIScrollBar bar, float scrollAmount) => OnMoved = (GUIScrollBar bar, float scrollAmount) =>
{ {
LastUser = Character.Controlled; LastUser = Character.Controlled;
if (nextServerLogWriteTime == null)
{
nextServerLogWriteTime = Math.Max(lastServerLogWriteTime + 1.0f, (float)Timing.TotalTime);
}
unsentChanges = true; unsentChanges = true;
targetFissionRate = scrollAmount * 100.0f; targetFissionRate = scrollAmount * 100.0f;
@@ -181,10 +177,6 @@ namespace Barotrauma.Items.Components
OnMoved = (GUIScrollBar bar, float scrollAmount) => OnMoved = (GUIScrollBar bar, float scrollAmount) =>
{ {
LastUser = Character.Controlled; LastUser = Character.Controlled;
if (nextServerLogWriteTime == null)
{
nextServerLogWriteTime = Math.Max(lastServerLogWriteTime + 1.0f, (float)Timing.TotalTime);
}
unsentChanges = true; unsentChanges = true;
targetTurbineOutput = scrollAmount * 100.0f; targetTurbineOutput = scrollAmount * 100.0f;
@@ -209,10 +201,6 @@ namespace Barotrauma.Items.Components
OnMoved = (scrollBar, scrollAmount) => OnMoved = (scrollBar, scrollAmount) =>
{ {
LastUser = Character.Controlled; LastUser = Character.Controlled;
if (nextServerLogWriteTime == null)
{
nextServerLogWriteTime = Math.Max(lastServerLogWriteTime + 1.0f, (float)Timing.TotalTime);
}
unsentChanges = true; unsentChanges = true;
return true; return true;
} }
@@ -227,10 +215,6 @@ namespace Barotrauma.Items.Components
OnMoved = (scrollBar, scrollAmount) => OnMoved = (scrollBar, scrollAmount) =>
{ {
LastUser = Character.Controlled; LastUser = Character.Controlled;
if (nextServerLogWriteTime == null)
{
nextServerLogWriteTime = Math.Max(lastServerLogWriteTime + 1.0f, (float)Timing.TotalTime);
}
unsentChanges = true; unsentChanges = true;
return true; return true;
} }
@@ -11,6 +11,12 @@ namespace Barotrauma.Items.Components
{ {
partial class Sonar : Powered, IServerSerializable, IClientSerializable partial class Sonar : Powered, IServerSerializable, IClientSerializable
{ {
enum Mode
{
Active,
Passive
};
private bool unsentChanges; private bool unsentChanges;
private float networkUpdateTimer; private float networkUpdateTimer;
@@ -86,17 +92,12 @@ namespace Barotrauma.Items.Components
ToolTip = TextManager.Get("SonarTipActive"), ToolTip = TextManager.Get("SonarTipActive"),
OnSelected = (GUITickBox box) => OnSelected = (GUITickBox box) =>
{ {
if (GameMain.Server != null) IsActive = box.Selected;
{ if (GameMain.Client != null)
unsentChanges = true;
}
else if (GameMain.Client != null)
{ {
unsentChanges = true; unsentChanges = true;
correctionTimer = CorrectionDelay; correctionTimer = CorrectionDelay;
} }
IsActive = box.Selected;
return true; return true;
} }
}; };
@@ -111,11 +112,7 @@ namespace Barotrauma.Items.Components
OnMoved = (scrollbar, scroll) => OnMoved = (scrollbar, scroll) =>
{ {
zoom = MathHelper.Lerp(MinZoom, MaxZoom, scroll); zoom = MathHelper.Lerp(MinZoom, MaxZoom, scroll);
if (GameMain.Server != null) if (GameMain.Client != null)
{
unsentChanges = true;
}
else if (GameMain.Client != null)
{ {
unsentChanges = true; unsentChanges = true;
correctionTimer = CorrectionDelay; correctionTimer = CorrectionDelay;
@@ -136,11 +133,7 @@ namespace Barotrauma.Items.Components
OnSelected = (tickBox) => OnSelected = (tickBox) =>
{ {
useDirectionalPing = tickBox.Selected; useDirectionalPing = tickBox.Selected;
if (GameMain.Server != null) if (GameMain.Client != null)
{
unsentChanges = true;
}
else if (GameMain.Client != null)
{ {
unsentChanges = true; unsentChanges = true;
correctionTimer = CorrectionDelay; correctionTimer = CorrectionDelay;
@@ -154,11 +147,7 @@ namespace Barotrauma.Items.Components
{ {
float pingAngle = MathHelper.Lerp(0.0f, MathHelper.TwoPi, scroll); float pingAngle = MathHelper.Lerp(0.0f, MathHelper.TwoPi, scroll);
pingDirection = new Vector2((float)Math.Cos(pingAngle), (float)Math.Sin(pingAngle)); pingDirection = new Vector2((float)Math.Cos(pingAngle), (float)Math.Sin(pingAngle));
if (GameMain.Server != null) if (GameMain.Client != null)
{
unsentChanges = true;
}
else if (GameMain.Client != null)
{ {
unsentChanges = true; unsentChanges = true;
correctionTimer = CorrectionDelay; correctionTimer = CorrectionDelay;
@@ -168,9 +157,12 @@ namespace Barotrauma.Items.Components
}; };
signalWarningText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.15f), paddedControlContainer.RectTransform), "", Color.Orange, textAlignment: Alignment.Center); signalWarningText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.15f), paddedControlContainer.RectTransform), "", Color.Orange, textAlignment: Alignment.Center);
GUITickBox.CreateRadioButtonGroup(new List<GUITickBox>() { activeTickBox, passiveTickBox });
GUIRadioButtonGroup sonarMode = new GUIRadioButtonGroup();
sonarMode.AddRadioButton(Mode.Active, activeTickBox);
sonarMode.AddRadioButton(Mode.Passive, passiveTickBox);
sonarMode.Selected = Mode.Passive;
GuiFrame.CanBeFocused = false; GuiFrame.CanBeFocused = false;
} }
@@ -183,27 +175,20 @@ namespace Barotrauma.Items.Components
public override void UpdateHUD(Character character, float deltaTime, Camera cam) public override void UpdateHUD(Character character, float deltaTime, Camera cam)
{ {
if (unsentChanges) if (GameMain.Client != null)
{ {
if (networkUpdateTimer <= 0.0f) if (unsentChanges)
{ {
#if CLIENT if (networkUpdateTimer <= 0.0f)
if (GameMain.Client != null)
{ {
item.CreateClientEvent(this); item.CreateClientEvent(this);
correctionTimer = CorrectionDelay; correctionTimer = CorrectionDelay;
networkUpdateTimer = 0.1f;
unsentChanges = false;
} }
#endif
if (GameMain.Server != null)
{
item.CreateServerEvent(this);
}
networkUpdateTimer = 0.1f;
unsentChanges = false;
} }
networkUpdateTimer -= deltaTime;
} }
networkUpdateTimer -= deltaTime;
if (sonarView.Rect.Contains(PlayerInput.MousePosition)) if (sonarView.Rect.Contains(PlayerInput.MousePosition))
{ {
@@ -215,7 +200,7 @@ namespace Barotrauma.Items.Components
} }
} }
float distort = 1.0f - item.Condition / 100.0f; float distort = 1.0f - item.Condition / item.Prefab.Health;
for (int i = sonarBlips.Count - 1; i >= 0; i--) for (int i = sonarBlips.Count - 1; i >= 0; i--)
{ {
sonarBlips[i].FadeTimer -= deltaTime * MathHelper.Lerp(0.5f, 2.0f, distort); sonarBlips[i].FadeTimer -= deltaTime * MathHelper.Lerp(0.5f, 2.0f, distort);
@@ -304,18 +289,22 @@ namespace Barotrauma.Items.Components
return; return;
} }
float passivePingRadius = (float)Math.Sin(Timing.TotalTime * 10); float passivePingRadius = (float)(Timing.TotalTime % 1.0f);
if (passivePingRadius > 0.0f) if (passivePingRadius > 0.0f)
{ {
disruptedDirections.Clear(); disruptedDirections.Clear();
foreach (AITarget t in AITarget.List) foreach (AITarget t in AITarget.List)
{ {
if (t.SoundRange <= 0.0f || !t.Enabled) continue; if (t.SoundRange <= 0.0f || !t.Enabled) { continue; }
float distSqr = Vector2.DistanceSquared(t.WorldPosition, transducerCenter);
if (distSqr > t.SoundRange * t.SoundRange * 2) { continue; }
if (Vector2.DistanceSquared(t.WorldPosition, transducerCenter) < t.SoundRange * t.SoundRange) float dist = (float)Math.Sqrt(distSqr);
if (dist > prevPassivePingRadius * Range && dist <= passivePingRadius * Range)
{ {
Ping(t.WorldPosition, transducerCenter, Ping(t.WorldPosition, transducerCenter,
t.SoundRange * passivePingRadius * 0.2f, t.SoundRange * prevPassivePingRadius * 0.2f, displayScale, t.SoundRange, Math.Min(t.SoundRange, range * 0.5f) * displayScale, 0, displayScale, Math.Min(t.SoundRange, range * 0.5f),
passive: true, pingStrength: 0.5f); passive: true, pingStrength: 0.5f);
sonarBlips.Add(new SonarBlip(t.WorldPosition, 1.0f, 1.0f)); sonarBlips.Add(new SonarBlip(t.WorldPosition, 1.0f, 1.0f));
} }
@@ -653,25 +642,25 @@ namespace Barotrauma.Items.Components
CreateBlipsForLine( CreateBlipsForLine(
new Vector2(item.CurrentHull.WorldRect.X, item.CurrentHull.WorldRect.Y), new Vector2(item.CurrentHull.WorldRect.X, item.CurrentHull.WorldRect.Y),
new Vector2(item.CurrentHull.WorldRect.Right, item.CurrentHull.WorldRect.Y), new Vector2(item.CurrentHull.WorldRect.Right, item.CurrentHull.WorldRect.Y),
transducerPos, pingSource, transducerPos,
pingRadius, prevPingRadius, 50.0f, 5.0f, range, 2.0f, passive); pingRadius, prevPingRadius, 50.0f, 5.0f, range, 2.0f, passive);
CreateBlipsForLine( CreateBlipsForLine(
new Vector2(item.CurrentHull.WorldRect.X, item.CurrentHull.WorldRect.Y - item.CurrentHull.Rect.Height), new Vector2(item.CurrentHull.WorldRect.X, item.CurrentHull.WorldRect.Y - item.CurrentHull.Rect.Height),
new Vector2(item.CurrentHull.WorldRect.Right, item.CurrentHull.WorldRect.Y - item.CurrentHull.Rect.Height), new Vector2(item.CurrentHull.WorldRect.Right, item.CurrentHull.WorldRect.Y - item.CurrentHull.Rect.Height),
transducerPos, pingSource, transducerPos,
pingRadius, prevPingRadius, 50.0f, 5.0f, range, 2.0f, passive); pingRadius, prevPingRadius, 50.0f, 5.0f, range, 2.0f, passive);
CreateBlipsForLine( CreateBlipsForLine(
new Vector2(item.CurrentHull.WorldRect.X, item.CurrentHull.WorldRect.Y), new Vector2(item.CurrentHull.WorldRect.X, item.CurrentHull.WorldRect.Y),
new Vector2(item.CurrentHull.WorldRect.X, item.CurrentHull.WorldRect.Y - item.CurrentHull.Rect.Height), new Vector2(item.CurrentHull.WorldRect.X, item.CurrentHull.WorldRect.Y - item.CurrentHull.Rect.Height),
transducerPos, pingSource, transducerPos,
pingRadius, prevPingRadius, 50.0f, 5.0f, range, 2.0f, passive); pingRadius, prevPingRadius, 50.0f, 5.0f, range, 2.0f, passive);
CreateBlipsForLine( CreateBlipsForLine(
new Vector2(item.CurrentHull.WorldRect.Right, item.CurrentHull.WorldRect.Y), new Vector2(item.CurrentHull.WorldRect.Right, item.CurrentHull.WorldRect.Y),
new Vector2(item.CurrentHull.WorldRect.Right, item.CurrentHull.WorldRect.Y - item.CurrentHull.Rect.Height), new Vector2(item.CurrentHull.WorldRect.Right, item.CurrentHull.WorldRect.Y - item.CurrentHull.Rect.Height),
transducerPos, pingSource, transducerPos,
pingRadius, prevPingRadius, 50.0f, 5.0f, range, 2.0f, passive); pingRadius, prevPingRadius, 50.0f, 5.0f, range, 2.0f, passive);
return; return;
@@ -708,7 +697,7 @@ namespace Barotrauma.Items.Components
CreateBlipsForLine( CreateBlipsForLine(
start + submarine.WorldPosition, start + submarine.WorldPosition,
end + submarine.WorldPosition, end + submarine.WorldPosition,
transducerPos, pingSource, transducerPos,
pingRadius, prevPingRadius, pingRadius, prevPingRadius,
200.0f, 2.0f, range, 1.0f, passive); 200.0f, 2.0f, range, 1.0f, passive);
} }
@@ -721,7 +710,7 @@ namespace Barotrauma.Items.Components
CreateBlipsForLine( CreateBlipsForLine(
new Vector2(pingSource.X - range, Level.Loaded.Size.Y), new Vector2(pingSource.X - range, Level.Loaded.Size.Y),
new Vector2(pingSource.X + range, Level.Loaded.Size.Y), new Vector2(pingSource.X + range, Level.Loaded.Size.Y),
transducerPos, pingSource, transducerPos,
pingRadius, prevPingRadius, pingRadius, prevPingRadius,
250.0f, 150.0f, range, pingStrength, passive); 250.0f, 150.0f, range, pingStrength, passive);
} }
@@ -742,7 +731,7 @@ namespace Barotrauma.Items.Components
CreateBlipsForLine( CreateBlipsForLine(
edge.Point1 + cell.Translation, edge.Point1 + cell.Translation,
edge.Point2 + cell.Translation, edge.Point2 + cell.Translation,
transducerPos, pingSource, transducerPos,
pingRadius, prevPingRadius, pingRadius, prevPingRadius,
350.0f, 3.0f * (Math.Abs(facingDot) + 1.0f), range, pingStrength, passive); 350.0f, 3.0f * (Math.Abs(facingDot) + 1.0f), range, pingStrength, passive);
} }
@@ -763,7 +752,7 @@ namespace Barotrauma.Items.Components
CreateBlipsForLine( CreateBlipsForLine(
wall.A, wall.B, wall.A, wall.B,
transducerPos, pingSource, transducerPos,
pingRadius, prevPingRadius, pingRadius, prevPingRadius,
100.0f, 1000.0f, range, pingStrength, passive); 100.0f, 1000.0f, range, pingStrength, passive);
} }
@@ -813,7 +802,7 @@ namespace Barotrauma.Items.Components
} }
} }
private void CreateBlipsForLine(Vector2 point1, Vector2 point2, Vector2 transducerPos, float pingRadius, float prevPingRadius, private void CreateBlipsForLine(Vector2 point1, Vector2 point2, Vector2 pingSource, Vector2 transducerPos, float pingRadius, float prevPingRadius,
float lineStep, float zStep, float range, float pingStrength, bool passive) float lineStep, float zStep, float range, float pingStrength, bool passive)
{ {
lineStep /= zoom; lineStep /= zoom;
@@ -824,19 +813,25 @@ namespace Barotrauma.Items.Components
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; Vector2 point = point1 + lineDir * x;
//point += cell.Translation;
Vector2 pointDiff = point - transducerPos; //ignore if outside the display
float pointDist = pointDiff.Length(); Vector2 transducerDiff = point - transducerPos;
float displayPointDist = pointDist * displayScale; Vector2 transducerDisplayDiff = transducerDiff * displayScale;
if (transducerDisplayDiff.LengthSquared() > DisplayRadius * DisplayRadius) continue;
if (displayPointDist > DisplayRadius) continue; //ignore if the point is not within the ping
if (displayPointDist < prevPingRadius || displayPointDist > pingRadius) continue; Vector2 pointDiff = point - pingSource;
Vector2 displayPointDiff = pointDiff * displayScale;
float displayPointDistSqr = displayPointDiff.LengthSquared();
if (displayPointDistSqr < prevPingRadius * prevPingRadius || displayPointDistSqr > pingRadius * pingRadius) continue;
//ignore if direction is disrupted
float transducerDist = transducerDiff.Length();
Vector2 pingDirection = transducerDiff / transducerDist;
bool disrupted = false; bool disrupted = false;
foreach (Pair<Vector2, float> disruptDir in disruptedDirections) foreach (Pair<Vector2, float> disruptDir in disruptedDirections)
{ {
float dot = Vector2.Dot(pointDiff / pointDist, disruptDir.First); float dot = Vector2.Dot(pingDirection, disruptDir.First);
if (dot > 1.0f - disruptDir.Second) if (dot > 1.0f - disruptDir.Second)
{ {
disrupted = true; disrupted = true;
@@ -845,10 +840,11 @@ namespace Barotrauma.Items.Components
} }
if (disrupted) continue; if (disrupted) continue;
float displayPointDist = (float)Math.Sqrt(displayPointDistSqr);
float alpha = pingStrength * Rand.Range(1.5f, 2.0f); float alpha = pingStrength * Rand.Range(1.5f, 2.0f);
for (float z = 0; z < DisplayRadius - displayPointDist; z += zStep) for (float z = 0; z < DisplayRadius - transducerDist * displayScale; z += zStep)
{ {
Vector2 pos = point + Rand.Vector(150.0f / zoom) + Vector2.Normalize(point - item.WorldPosition) * z / displayScale; Vector2 pos = point + Rand.Vector(150.0f / zoom) + pingDirection * z / displayScale;
float fadeTimer = alpha * (1.0f - displayPointDist / range); float fadeTimer = alpha * (1.0f - displayPointDist / range);
int minDist = (int)(200 / zoom); int minDist = (int)(200 / zoom);
@@ -902,7 +898,7 @@ namespace Barotrauma.Items.Components
{ {
strength = MathHelper.Clamp(strength, 0.0f, 1.0f); strength = MathHelper.Clamp(strength, 0.0f, 1.0f);
float distort = 1.0f - item.Condition / 100.0f; float distort = 1.0f - item.Condition / item.Prefab.Health;
Vector2 pos = (blip.Position - transducerPos) * displayScale * zoom; Vector2 pos = (blip.Position - transducerPos) * displayScale * zoom;
pos.Y = -pos.Y; pos.Y = -pos.Y;
@@ -10,7 +10,19 @@ namespace Barotrauma.Items.Components
{ {
partial class Steering : Powered, IServerSerializable, IClientSerializable partial class Steering : Powered, IServerSerializable, IClientSerializable
{ {
enum Mode
{
AutoPilot,
Manual
};
private GUITickBox autopilotTickBox, manualTickBox; private GUITickBox autopilotTickBox, manualTickBox;
enum Destination
{
MaintainPos,
LevelEnd,
LevelStart
};
private GUITickBox maintainPosTickBox, levelEndTickBox, levelStartTickBox; private GUITickBox maintainPosTickBox, levelEndTickBox, levelStartTickBox;
private GUIFrame autoPilotControlsDisabler; private GUIFrame autoPilotControlsDisabler;
@@ -104,8 +116,11 @@ namespace Barotrauma.Items.Components
} }
}; };
GUITickBox.CreateRadioButtonGroup(new List<GUITickBox> { manualTickBox, autopilotTickBox }); GUIRadioButtonGroup modes = new GUIRadioButtonGroup();
modes.AddRadioButton(Mode.AutoPilot, autopilotTickBox);
modes.AddRadioButton(Mode.Manual, manualTickBox);
modes.Selected = Mode.Manual;
var autoPilotControls = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.6f), paddedControlContainer.RectTransform), "InnerFrame"); var autoPilotControls = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.6f), paddedControlContainer.RectTransform), "InnerFrame");
var paddedAutoPilotControls = new GUILayoutGroup(new RectTransform(new Vector2(0.8f), autoPilotControls.RectTransform, Anchor.Center)) var paddedAutoPilotControls = new GUILayoutGroup(new RectTransform(new Vector2(0.8f), autoPilotControls.RectTransform, Anchor.Center))
{ {
@@ -205,7 +220,12 @@ namespace Barotrauma.Items.Components
autoPilotControlsDisabler = new GUIFrame(new RectTransform(Vector2.One, autoPilotControls.RectTransform), "InnerFrame"); autoPilotControlsDisabler = new GUIFrame(new RectTransform(Vector2.One, autoPilotControls.RectTransform), "InnerFrame");
GUITickBox.CreateRadioButtonGroup(new List<GUITickBox> { maintainPosTickBox, levelStartTickBox, levelEndTickBox }); GUIRadioButtonGroup destinations = new GUIRadioButtonGroup();
destinations.AddRadioButton(Destination.MaintainPos, maintainPosTickBox);
destinations.AddRadioButton(Destination.LevelStart, levelStartTickBox);
destinations.AddRadioButton(Destination.LevelEnd, levelEndTickBox);
destinations.Selected = maintainPos ? Destination.MaintainPos :
levelStartSelected ? Destination.LevelStart : Destination.LevelEnd;
string steeringVelX = TextManager.Get("SteeringVelocityX"); string steeringVelX = TextManager.Get("SteeringVelocityX");
string steeringVelY = TextManager.Get("SteeringVelocityY"); string steeringVelY = TextManager.Get("SteeringVelocityY");
@@ -11,6 +11,12 @@ namespace Barotrauma.Items.Components
private GUIProgressBar chargeIndicator; private GUIProgressBar chargeIndicator;
private GUIScrollBar rechargeSpeedSlider; private GUIScrollBar rechargeSpeedSlider;
public Vector2 DrawSize
{
//use the extents of the item as the draw size
get { return Vector2.Zero; }
}
partial void InitProjSpecific() partial void InitProjSpecific()
{ {
if (GuiFrame == null) return; if (GuiFrame == null) return;
@@ -44,12 +50,7 @@ namespace Barotrauma.Items.Components
if (Math.Abs(newRechargeSpeed - rechargeSpeed) < 0.1f) return false; if (Math.Abs(newRechargeSpeed - rechargeSpeed) < 0.1f) return false;
RechargeSpeed = newRechargeSpeed; RechargeSpeed = newRechargeSpeed;
if (GameMain.Server != null) if (GameMain.Client != null)
{
item.CreateServerEvent(this);
GameServer.Log(Character.Controlled.LogName + " set the recharge speed of " + item.Name + " to " + (int)((rechargeSpeed / maxRechargeSpeed) * 100.0f) + " %", ServerLog.MessageType.ItemInteraction);
}
else if (GameMain.Client != null)
{ {
item.CreateClientEvent(this); item.CreateClientEvent(this);
correctionTimer = CorrectionDelay; correctionTimer = CorrectionDelay;
@@ -22,7 +22,8 @@ namespace Barotrauma.Items.Components
powerOnSound = Submarine.LoadRoundSound(subElement, false); powerOnSound = Submarine.LoadRoundSound(subElement, false);
break; break;
case "sparksound": case "sparksound":
sparkSounds.Add(Submarine.LoadRoundSound(subElement, false)); var sparkSound = Submarine.LoadRoundSound(subElement, false);
if (sparkSound != null) { sparkSounds.Add(sparkSound); }
break; break;
} }
} }
@@ -73,7 +73,7 @@ namespace Barotrauma.Items.Components
} }
var progressBar = user.UpdateHUDProgressBar( var progressBar = user.UpdateHUDProgressBar(
targetStructure, targetStructure.ID * 1000 + sectionIndex, //unique "identifier" for each wall section
progressBarPos, progressBarPos,
1.0f - targetStructure.SectionDamage(sectionIndex) / targetStructure.Health, 1.0f - targetStructure.SectionDamage(sectionIndex) / targetStructure.Health,
Color.Red, Color.Green); Color.Red, Color.Green);
@@ -108,7 +108,7 @@ namespace Barotrauma.Items.Components
var progressBar = user.UpdateHUDProgressBar( var progressBar = user.UpdateHUDProgressBar(
targetItem, targetItem,
progressBarPos, progressBarPos,
targetItem.Condition / 100.0f, targetItem.Prefab.Health <= 0.0f ? 0.0f : targetItem.Condition / targetItem.Prefab.Health,
Color.Red, Color.Green); Color.Red, Color.Green);
if (progressBar != null) { progressBar.Size = new Vector2(60.0f, 20.0f); } if (progressBar != null) { progressBar.Size = new Vector2(60.0f, 20.0f); }
} }
@@ -26,7 +26,7 @@ namespace Barotrauma.Items.Components
public override bool ShouldDrawHUD(Character character) public override bool ShouldDrawHUD(Character character)
{ {
if (!HasRequiredItems(character, false)) return false; if (!HasRequiredItems(character, false) || character.SelectedConstruction != item) return false;
return (item.Condition < ShowRepairUIThreshold || (currentFixer == character && item.Condition < item.Prefab.Health)); return (item.Condition < ShowRepairUIThreshold || (currentFixer == character && item.Condition < item.Prefab.Health));
} }
@@ -108,10 +108,6 @@ namespace Barotrauma.Items.Components
{ {
panel.Item.CreateClientEvent(panel); panel.Item.CreateClientEvent(panel);
} }
else if (GameMain.Server != null)
{
panel.Item.CreateServerEvent(panel);
}
draggingConnected = null; draggingConnected = null;
} }
@@ -173,6 +169,8 @@ namespace Barotrauma.Items.Components
if (draggingConnected.Connect(this, !alreadyConnected, true)) if (draggingConnected.Connect(this, !alreadyConnected, true))
{ {
var otherConnection = draggingConnected.OtherConnection(this); var otherConnection = draggingConnected.OtherConnection(this);
#if SERVER
//TODO: ffs
if (otherConnection == null) if (otherConnection == null)
{ {
GameServer.Log(Character.Controlled.LogName + " connected a wire to " + GameServer.Log(Character.Controlled.LogName + " connected a wire to " +
@@ -183,6 +181,7 @@ namespace Barotrauma.Items.Components
GameServer.Log(Character.Controlled.LogName + " connected a wire from " + GameServer.Log(Character.Controlled.LogName + " connected a wire from " +
Item.Name + " (" + Name + ") to " + otherConnection.item.Name + " (" + otherConnection.Name + ")", ServerLog.MessageType.ItemInteraction); Item.Name + " (" + Name + ") to " + otherConnection.item.Name + " (" + otherConnection.Name + ")", ServerLog.MessageType.ItemInteraction);
} }
#endif
SetWire(index, draggingConnected); SetWire(index, draggingConnected);
} }
@@ -54,7 +54,7 @@ namespace Barotrauma.Items.Components
} }
else else
{ {
GameMain.Client.CreateEntityEvent(item, new object[] { NetEntityEvent.Type.ComponentState, item.components.IndexOf(this), userdata as CustomInterfaceElement }); GameMain.Client.CreateEntityEvent(item, new object[] { NetEntityEvent.Type.ComponentState, item.GetComponentIndex(this), userdata as CustomInterfaceElement });
} }
return true; return true;
}; };
@@ -5,6 +5,11 @@ namespace Barotrauma.Items.Components
{ {
partial class MotionSensor : IDrawableComponent partial class MotionSensor : IDrawableComponent
{ {
public Vector2 DrawSize
{
get { return new Vector2(rangeX, rangeY) * 2.0f; }
}
public void Draw(SpriteBatch spriteBatch, bool editing) public void Draw(SpriteBatch spriteBatch, bool editing)
{ {
if (!editing || !MapEntity.SelectedList.Contains(item)) return; if (!editing || !MapEntity.SelectedList.Contains(item)) return;
@@ -5,6 +5,11 @@ namespace Barotrauma.Items.Components
{ {
partial class WifiComponent : IDrawableComponent partial class WifiComponent : IDrawableComponent
{ {
public Vector2 DrawSize
{
get { return new Vector2(range * 2); }
}
public void Draw(SpriteBatch spriteBatch, bool editing) public void Draw(SpriteBatch spriteBatch, bool editing)
{ {
if (!editing || !MapEntity.SelectedList.Contains(item)) return; if (!editing || !MapEntity.SelectedList.Contains(item)) return;
@@ -41,7 +41,12 @@ namespace Barotrauma.Items.Components
private static Wire draggingWire; private static Wire draggingWire;
private static int? selectedNodeIndex; private static int? selectedNodeIndex;
private static int? highlightedNodeIndex; private static int? highlightedNodeIndex;
public Vector2 DrawSize
{
get { return sectionExtents; }
}
public void Draw(SpriteBatch spriteBatch, bool editing) public void Draw(SpriteBatch spriteBatch, bool editing)
{ {
if (sections.Count == 0 && !IsActive || Hidden) if (sections.Count == 0 && !IsActive || Hidden)
@@ -73,7 +73,7 @@ namespace Barotrauma.Items.Components
visibleCharacters.Clear(); visibleCharacters.Clear();
foreach (Character c in Character.CharacterList) foreach (Character c in Character.CharacterList)
{ {
if (c == equipper) continue; if (c == equipper || !c.Enabled || c.Removed) { continue; }
float dist = Vector2.DistanceSquared(equipper.WorldPosition, c.WorldPosition); float dist = Vector2.DistanceSquared(equipper.WorldPosition, c.WorldPosition);
if (dist < Range * Range) if (dist < Range * Range)
@@ -111,10 +111,9 @@ namespace Barotrauma.Items.Components
Character closestCharacter = null; Character closestCharacter = null;
float closestDist = float.PositiveInfinity; float closestDist = float.PositiveInfinity;
foreach (Character c in visibleCharacters) foreach (Character c in visibleCharacters)
{ {
if (c == character) continue; if (c == character || !c.Enabled || c.Removed) { continue; }
float dist = Vector2.DistanceSquared(GameMain.GameScreen.Cam.ScreenToWorld(PlayerInput.MousePosition), c.WorldPosition); float dist = Vector2.DistanceSquared(GameMain.GameScreen.Cam.ScreenToWorld(PlayerInput.MousePosition), c.WorldPosition);
if (dist < closestDist) if (dist < closestDist)
@@ -175,14 +174,14 @@ namespace Barotrauma.Items.Components
{ {
int bleedingTextIndex = MathHelper.Clamp((int)Math.Floor(target.Bleeding / 100.0f) * BleedingTexts.Length, 0, BleedingTexts.Length - 1); int bleedingTextIndex = MathHelper.Clamp((int)Math.Floor(target.Bleeding / 100.0f) * BleedingTexts.Length, 0, BleedingTexts.Length - 1);
texts.Add(BleedingTexts[bleedingTextIndex]); texts.Add(BleedingTexts[bleedingTextIndex]);
textColors.Add(Color.Lerp(Color.Red, Color.Green, target.Bleeding / 100.0f)); textColors.Add(Color.Lerp(Color.Orange, Color.Red, target.Bleeding / 100.0f));
} }
var allAfflictions = target.CharacterHealth.GetAllAfflictions(); var allAfflictions = target.CharacterHealth.GetAllAfflictions();
Dictionary<AfflictionPrefab, float> combinedAfflictionStrengths = new Dictionary<AfflictionPrefab, float>(); Dictionary<AfflictionPrefab, float> combinedAfflictionStrengths = new Dictionary<AfflictionPrefab, float>();
foreach (Affliction affliction in allAfflictions) foreach (Affliction affliction in allAfflictions)
{ {
if (affliction.Strength < affliction.Prefab.ActivationThreshold || affliction.Strength < affliction.Prefab.ShowIconThreshold) continue; if (affliction.Strength < affliction.Prefab.ActivationThreshold || affliction.Strength <= 0.0f) continue;
if (combinedAfflictionStrengths.ContainsKey(affliction.Prefab)) if (combinedAfflictionStrengths.ContainsKey(affliction.Prefab))
{ {
combinedAfflictionStrengths[affliction.Prefab] += affliction.Strength; combinedAfflictionStrengths[affliction.Prefab] += affliction.Strength;
@@ -196,7 +195,7 @@ namespace Barotrauma.Items.Components
foreach (AfflictionPrefab affliction in combinedAfflictionStrengths.Keys) foreach (AfflictionPrefab affliction in combinedAfflictionStrengths.Keys)
{ {
texts.Add(affliction.Name + ": " + ((int)combinedAfflictionStrengths[affliction]).ToString() + " %"); texts.Add(affliction.Name + ": " + ((int)combinedAfflictionStrengths[affliction]).ToString() + " %");
textColors.Add(Color.Lerp(Color.Red, Color.Green, combinedAfflictionStrengths[affliction] / affliction.MaxStrength)); textColors.Add(Color.Lerp(Color.Orange, Color.Red, combinedAfflictionStrengths[affliction] / affliction.MaxStrength));
} }
} }
@@ -204,6 +203,9 @@ namespace Barotrauma.Items.Components
hudPos.X += 5.0f; hudPos.X += 5.0f;
hudPos.Y += 24.0f; hudPos.Y += 24.0f;
hudPos.X = (int)hudPos.X;
hudPos.Y = (int)hudPos.Y;
for (int i = 1; i < texts.Count; i++) for (int i = 1; i < texts.Count; i++)
{ {
GUI.DrawString(spriteBatch, hudPos, texts[i], textColors[i] * alpha, Color.Black * 0.7f * alpha, 2, GUI.SmallFont); GUI.DrawString(spriteBatch, hudPos, texts[i], textColors[i] * alpha, Color.Black * 0.7f * alpha, 2, GUI.SmallFont);
@@ -61,6 +61,26 @@ namespace Barotrauma.Items.Components
private set; private set;
} }
public Vector2 DrawSize
{
get
{
float size = Math.Max(transformedBarrelPos.X, transformedBarrelPos.Y);
if (barrelSprite != null)
{
if (railSprite != null)
{
size += Math.Max(Math.Max(barrelSprite.size.X, barrelSprite.size.Y), Math.Max(railSprite.size.X, railSprite.size.Y)) * item.Scale;
}
else
{
size += Math.Max(barrelSprite.size.X, barrelSprite.size.Y) * item.Scale;
}
}
return Vector2.One * size * 2;
}
}
partial void InitProjSpecific(XElement element) partial void InitProjSpecific(XElement element)
{ {
foreach (XElement subElement in element.Elements()) foreach (XElement subElement in element.Elements())
@@ -1,7 +1,6 @@
using Barotrauma.Networking; using Barotrauma.Networking;
using FarseerPhysics; using FarseerPhysics;
using FarseerPhysics.Collision; using FarseerPhysics.Collision;
using FarseerPhysics.Dynamics;
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Graphics;
@@ -9,6 +8,12 @@ namespace Barotrauma.Items.Components
{ {
partial class DockingPort : ItemComponent, IDrawableComponent, IServerSerializable partial class DockingPort : ItemComponent, IDrawableComponent, IServerSerializable
{ {
public Vector2 DrawSize
{
//use the extents of the item as the draw size
get { return Vector2.Zero; }
}
public void Draw(SpriteBatch spriteBatch, bool editing) public void Draw(SpriteBatch spriteBatch, bool editing)
{ {
if (dockingState == 0.0f) return; if (dockingState == 0.0f) return;
@@ -128,12 +128,14 @@ namespace Barotrauma
protected float prevUIScale = UIScale; protected float prevUIScale = UIScale;
protected float prevHUDScale = GUI.Scale; protected float prevHUDScale = GUI.Scale;
protected static Sprite slotSpriteSmall, slotSpriteHorizontal, slotSpriteVertical, slotSpriteRound; protected static Sprite slotSpriteSmall, slotSpriteHorizontal, slotSpriteVertical, slotSpriteRound;
public static Sprite EquipIndicator, EquipIndicatorHighlight; public static Sprite EquipIndicator, EquipIndicatorHighlight;
public static Sprite DropIndicator, DropIndicatorHighlight; public static Sprite DropIndicator, DropIndicatorHighlight;
public Rectangle BackgroundFrame { get; protected set; } public Rectangle BackgroundFrame { get; protected set; }
private ushort[] receivedItemIDs;
private CoroutineHandle syncItemsCoroutine;
public float HideTimer; public float HideTimer;
@@ -504,7 +506,7 @@ namespace Barotrauma
if (Character.Controlled.SelectedConstruction != null) if (Character.Controlled.SelectedConstruction != null)
{ {
foreach (ItemComponent ic in Character.Controlled.SelectedConstruction.components) foreach (ItemComponent ic in Character.Controlled.SelectedConstruction.Components)
{ {
var itemContainer = ic as ItemContainer; var itemContainer = ic as ItemContainer;
if (itemContainer?.Inventory?.slots == null) continue; if (itemContainer?.Inventory?.slots == null) continue;
@@ -596,7 +598,6 @@ namespace Barotrauma
if (selectedSlot == null) if (selectedSlot == null)
{ {
draggingItem.ParentInventory?.CreateNetworkEvent();
draggingItem.Drop(); draggingItem.Drop();
GUI.PlayUISound(GUISoundType.DropItem); GUI.PlayUISound(GUISoundType.DropItem);
} }
@@ -675,7 +676,7 @@ namespace Barotrauma
foreach (var slot in highlightedSubInventorySlots) foreach (var slot in highlightedSubInventorySlots)
{ {
int slotIndex = Array.IndexOf(slot.ParentInventory.slots, slot.Slot); int slotIndex = Array.IndexOf(slot.ParentInventory.slots, slot.Slot);
if (slotIndex > 0 && slotIndex < slot.ParentInventory.slots.Length) if (slotIndex > -1 && slotIndex < slot.ParentInventory.slots.Length)
{ {
slot.ParentInventory.DrawSubInventory(spriteBatch, slotIndex); slot.ParentInventory.DrawSubInventory(spriteBatch, slotIndex);
} }
@@ -788,7 +789,7 @@ namespace Barotrauma
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, rect.Width, 8), Color.Black * 0.8f, true);
GUI.DrawRectangle(spriteBatch, GUI.DrawRectangle(spriteBatch,
new Rectangle(rect.X, rect.Bottom - 8, (int)(rect.Width * item.Condition / item.Prefab.Health), 8), new Rectangle(rect.X, rect.Bottom - 8, (int)(rect.Width * item.Condition / item.Prefab.Health), 8),
Color.Lerp(Color.Red, Color.Green, item.Condition / 100.0f) * 0.8f, true); Color.Lerp(Color.Red, Color.Green, item.Condition / item.Prefab.Health) * 0.8f, true);
} }
if (itemContainer != null) if (itemContainer != null)
@@ -796,12 +797,12 @@ namespace Barotrauma
float containedState = 0.0f; float containedState = 0.0f;
if (itemContainer.ShowConditionInContainedStateIndicator) if (itemContainer.ShowConditionInContainedStateIndicator)
{ {
containedState = item.Condition / 100.0f; containedState = item.Condition / item.Prefab.Health;
} }
else else
{ {
containedState = itemContainer.Inventory.Capacity == 1 ? containedState = itemContainer.Inventory.Capacity == 1 ?
(itemContainer.Inventory.Items[0] == null ? 0.0f : itemContainer.Inventory.Items[0].Condition / 100.0f) : (itemContainer.Inventory.Items[0] == null ? 0.0f : itemContainer.Inventory.Items[0].Condition / item.Prefab.Health) :
itemContainer.Inventory.Items.Count(i => i != null) / (float)itemContainer.Inventory.capacity; itemContainer.Inventory.Items.Count(i => i != null) / (float)itemContainer.Inventory.capacity;
} }
@@ -962,8 +963,7 @@ namespace Barotrauma
{ {
if (receivedItemIDs[i] > 0) if (receivedItemIDs[i] > 0)
{ {
var item = Entity.FindEntityByID(receivedItemIDs[i]) as Item; if (!(Entity.FindEntityByID(receivedItemIDs[i]) is Item item) || Items[i] == item) continue;
if (item == null || Items[i] == item) continue;
TryPutItem(item, i, true, true, null, false); TryPutItem(item, i, true, true, null, false);
for (int j = 0; j < capacity; j++) for (int j = 0; j < capacity; j++)
@@ -978,5 +978,11 @@ namespace Barotrauma
receivedItemIDs = null; receivedItemIDs = null;
} }
public void ClientWrite(NetBuffer msg, object[] extraData = null)
{
SharedWrite(msg, extraData);
syncItemsDelay = 1.0f;
}
} }
} }
+170 -30
View File
@@ -15,6 +15,8 @@ namespace Barotrauma
partial class Item : MapEntity, IDamageable, ISerializableEntity, IServerSerializable, IClientSerializable partial class Item : MapEntity, IDamageable, ISerializableEntity, IServerSerializable, IClientSerializable
{ {
public static bool ShowItems = true; public static bool ShowItems = true;
private readonly List<PosInfo> positionBuffer = new List<PosInfo>();
private List<ItemComponent> activeHUDs = new List<ItemComponent>(); private List<ItemComponent> activeHUDs = new List<ItemComponent>();
@@ -34,6 +36,8 @@ namespace Barotrauma
{ {
get { return activeSprite; } get { return activeSprite; }
} }
public float SpriteRotation;
private GUITextBlock itemInUseWarning; private GUITextBlock itemInUseWarning;
private GUITextBlock ItemInUseWarning private GUITextBlock ItemInUseWarning
@@ -127,12 +131,36 @@ namespace Barotrauma
} }
} }
public override bool IsVisible(Rectangle worldView)
{
//no drawable components and the body has been disabled = nothing to draw
if (drawableComponents.Count == 0 && body != null && !body.Enabled)
{
return false;
}
float padding = 100.0f;
Vector2 size = new Vector2(rect.Width + padding, rect.Height + padding);
foreach (IDrawableComponent drawable in drawableComponents)
{
size.X = Math.Max(drawable.DrawSize.X, size.X);
size.Y = Math.Max(drawable.DrawSize.Y, size.Y);
}
size *= 0.5f;
Vector2 worldPosition = WorldPosition;
if (worldPosition.X - size.X > worldView.Right || worldPosition.X + size.X < worldView.X) return false;
if (worldPosition.Y + size.Y < worldView.Y - worldView.Height || worldPosition.Y - size.Y > worldView.Y) return false;
return true;
}
public override void Draw(SpriteBatch spriteBatch, bool editing, bool back = true) public override void Draw(SpriteBatch spriteBatch, bool editing, bool back = true)
{ {
if (!Visible || (!editing && hiddenInGame)) return; // TODO: Prevent drawing hiddenInGame objects via cheating with server-side checks if (!Visible || (!editing && hiddenInGame)) return;
if (editing && !ShowItems) return; if (editing && !ShowItems) return;
Color color = isHighlighted ? Color.Orange : GetSpriteColor(); Color color = isHighlighted && !GUI.DisableItemHighlights ? Color.Orange : GetSpriteColor();
//if (IsSelected && editing) color = Color.Lerp(color, Color.Gold, 0.5f); //if (IsSelected && editing) color = Color.Lerp(color, Color.Gold, 0.5f);
Sprite activeSprite = prefab.sprite; Sprite activeSprite = prefab.sprite;
@@ -816,41 +844,53 @@ namespace Barotrauma
} }
msg.WritePadBits(); msg.WritePadBits();
} }
partial void UpdateNetPosition()
{
if (GameMain.Client == null) { return; }
Vector2 newVelocity = body.LinearVelocity;
Vector2 newPosition = body.SimPosition;
float newAngularVelocity = body.AngularVelocity;
float newRotation = body.Rotation;
body.CorrectPosition(positionBuffer, out newPosition, out newVelocity, out newRotation, out newAngularVelocity);
body.LinearVelocity = newVelocity;
body.AngularVelocity = newAngularVelocity;
if (Vector2.DistanceSquared(newPosition, body.SimPosition) > 0.0001f ||
Math.Abs(newRotation - body.Rotation) > 0.01f)
{
body.TargetPosition = newPosition;
body.TargetRotation = newRotation;
body.MoveToTargetPosition(lerp: true);
}
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 ClientReadPosition(ServerNetObject type, NetBuffer msg, float sendingTime) 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 (!MathUtils.IsValid(newPosition) || !MathUtils.IsValid(newRotation) || !MathUtils.IsValid(newVelocity))
{
string errorMsg = "Received invalid position data for the item \"" + Name
+ "\" (position: " + newPosition + ", rotation: " + newRotation + ", velocity: " + newVelocity + ")";
#if DEBUG
DebugConsole.ThrowError(errorMsg);
#endif
GameAnalyticsManager.AddErrorEventOnce("Item.ClientReadPosition:InvalidData" + ID,
GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
errorMsg);
return;
}
if (body == null) if (body == null)
{ {
DebugConsole.ThrowError("Received a position update for an item with no physics body (" + Name + ")"); DebugConsole.ThrowError("Received a position update for an item with no physics body (" + Name + ")");
return; return;
} }
body.FarseerBody.Awake = awake; var posInfo = body.ClientRead(type, msg, sendingTime, parentDebugName: Name);
msg.ReadPadBits();
if (posInfo != null)
{
int index = 0;
while (index < positionBuffer.Count && sendingTime > positionBuffer[index].Timestamp)
{
index++;
}
positionBuffer.Insert(index, posInfo);
}
/*body.FarseerBody.Awake = awake;
if (body.FarseerBody.Awake) if (body.FarseerBody.Awake)
{ {
if ((newVelocity - body.LinearVelocity).LengthSquared() > 8.0f * 8.0f) body.LinearVelocity = newVelocity; if ((newVelocity - body.LinearVelocity).LengthSquared() > 8.0f * 8.0f) body.LinearVelocity = newVelocity;
@@ -879,7 +919,7 @@ namespace Barotrauma
rect.X = (int)(displayPos.X - rect.Width / 2.0f); rect.X = (int)(displayPos.X - rect.Width / 2.0f);
rect.Y = (int)(displayPos.Y + rect.Height / 2.0f); rect.Y = (int)(displayPos.Y + rect.Height / 2.0f);
} }
} }*/
} }
public void CreateClientEvent<T>(T ic) where T : ItemComponent, IClientSerializable public void CreateClientEvent<T>(T ic) where T : ItemComponent, IClientSerializable
@@ -891,6 +931,106 @@ namespace Barotrauma
GameMain.Client.CreateEntityEvent(this, new object[] { NetEntityEvent.Type.ComponentState, index }); GameMain.Client.CreateEntityEvent(this, new object[] { NetEntityEvent.Type.ComponentState, index });
} }
public static Item ReadSpawnData(NetBuffer msg, bool spawn = true)
{
string itemName = msg.ReadString();
string itemIdentifier = msg.ReadString();
bool descriptionChanged = msg.ReadBoolean();
string itemDesc = "";
if (descriptionChanged)
{
itemDesc = msg.ReadString();
}
ushort itemId = msg.ReadUInt16();
ushort inventoryId = msg.ReadUInt16();
DebugConsole.Log("Received entity spawn message for item " + itemName + ".");
Vector2 pos = Vector2.Zero;
Submarine sub = null;
int itemContainerIndex = -1;
int inventorySlotIndex = -1;
if (inventoryId > 0)
{
itemContainerIndex = msg.ReadByte();
inventorySlotIndex = msg.ReadByte();
}
else
{
pos = new Vector2(msg.ReadSingle(), msg.ReadSingle());
ushort subID = msg.ReadUInt16();
if (subID > 0)
{
sub = Submarine.Loaded.Find(s => s.ID == subID);
}
}
byte teamID = msg.ReadByte();
bool tagsChanged = msg.ReadBoolean();
string tags = "";
if (tagsChanged)
{
tags = msg.ReadString();
}
if (!spawn) return null;
//----------------------------------------
var itemPrefab = MapEntityPrefab.Find(itemName, itemIdentifier) as ItemPrefab;
if (itemPrefab == null) return null;
Inventory inventory = null;
var inventoryOwner = FindEntityByID(inventoryId);
if (inventoryOwner != null)
{
if (inventoryOwner is Character)
{
inventory = (inventoryOwner as Character).Inventory;
}
else if (inventoryOwner is Item)
{
if ((inventoryOwner as Item).components[itemContainerIndex] is ItemContainer container)
{
inventory = container.Inventory;
}
}
}
var item = new Item(itemPrefab, pos, sub)
{
ID = itemId
};
foreach (WifiComponent wifiComponent in item.GetComponents<WifiComponent>())
{
wifiComponent.TeamID = (Character.TeamType)teamID;
}
if (descriptionChanged) item.Description = itemDesc;
if (tagsChanged) item.Tags = tags;
if (sub != null)
{
item.CurrentHull = Hull.FindHull(pos + sub.Position, null, true);
item.Submarine = item.CurrentHull?.Submarine;
}
if (inventory != null)
{
if (inventorySlotIndex >= 0 && inventorySlotIndex < 255 &&
inventory.TryPutItem(item, inventorySlotIndex, false, false, null, false))
{
return null;
}
inventory.TryPutItem(item, null, item.AllowedSlots, false);
}
return item;
}
partial void RemoveProjSpecific() partial void RemoveProjSpecific()
{ {
@@ -6,6 +6,8 @@ namespace Barotrauma
{ {
partial class ItemInventory : Inventory partial class ItemInventory : Inventory
{ {
private string uiLabel;
protected override void ControlInput(Camera cam) protected override void ControlInput(Camera cam)
{ {
if (draggingItem == null && HUD.CloseHUD(BackgroundFrame)) if (draggingItem == null && HUD.CloseHUD(BackgroundFrame))
@@ -84,13 +86,24 @@ namespace Barotrauma
if (container.InventoryTopSprite == null) if (container.InventoryTopSprite == null)
{ {
Item item = Owner as Item; if (uiLabel == null || uiLabel == string.Empty)
string label = container.UILabel ?? item?.Name; {
if (!string.IsNullOrEmpty(label) && !subInventory) if (container.UILabel != null && container.UILabel.Length > 0)
{
uiLabel = TextManager.Get("UILabel." + container.UILabel);
}
else
{
Item item = Owner as Item;
uiLabel = item?.Name;
}
}
if (!string.IsNullOrEmpty(uiLabel) && !subInventory)
{ {
GUI.DrawString(spriteBatch, GUI.DrawString(spriteBatch,
new Vector2((int)(BackgroundFrame.Center.X - GUI.Font.MeasureString(label).X / 2), (int)BackgroundFrame.Y + 5), new Vector2((int)(BackgroundFrame.Center.X - GUI.Font.MeasureString(uiLabel).X / 2), (int)BackgroundFrame.Y + 5),
label, Color.White * 0.9f); uiLabel, Color.White * 0.9f);
} }
} }
else if (!subInventory) else if (!subInventory)
@@ -7,6 +7,12 @@ namespace Barotrauma.Items.Components
{ {
partial class Rope : ItemComponent, IDrawableComponent partial class Rope : ItemComponent, IDrawableComponent
{ {
public Vector2 DrawSize
{
//use the extents of the item as the draw size
get { return Vector2.Zero; }
}
public void Draw(SpriteBatch spriteBatch, bool editing = false) public void Draw(SpriteBatch spriteBatch, bool editing = false)
{ {
if (!IsActive) return; if (!IsActive) return;
@@ -16,14 +16,17 @@ namespace Barotrauma
} }
} }
public override bool IsVisible(Rectangle worldView)
{
return Screen.Selected == GameMain.SubEditorScreen || GameMain.DebugDraw;
}
public override void Draw(SpriteBatch sb, bool editing, bool back = true) public override void Draw(SpriteBatch sb, bool editing, bool back = true)
{ {
if (GameMain.DebugDraw) if (GameMain.DebugDraw)
{ {
Vector2 center = new Vector2(WorldRect.X + rect.Width / 2.0f, -(WorldRect.Y - rect.Height / 2.0f)); 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, 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); GUI.DrawLine(sb, center + Vector2.One * 5.0f, center + new Vector2(lerpedFlowForce.X, -lerpedFlowForce.Y) / 10.0f + Vector2.One * 5.0f, Color.Orange);
} }
+122 -7
View File
@@ -7,15 +7,21 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using Microsoft.Xna.Framework.Input; using Microsoft.Xna.Framework.Input;
using System.Linq; using System.Linq;
using Lidgren.Network;
namespace Barotrauma namespace Barotrauma
{ {
partial class Hull : MapEntity, ISerializableEntity, IServerSerializable partial class Hull : MapEntity, ISerializableEntity, IServerSerializable, IClientSerializable
{ {
public const int MaxDecalsPerHull = 10; public const int MaxDecalsPerHull = 10;
private List<Decal> decals = new List<Decal>(); private List<Decal> decals = new List<Decal>();
private float serverUpdateDelay;
private bool networkUpdatePending;
private float networkUpdateTimer;
public override bool SelectableInEditor public override bool SelectableInEditor
{ {
get get
@@ -39,7 +45,20 @@ namespace Barotrauma
return true; return true;
} }
} }
public override bool IsVisible(Rectangle worldView)
{
if (Screen.Selected != GameMain.SubEditorScreen && !GameMain.DebugDraw)
{
if (decals.Count == 0) { return false; }
Rectangle worldRect = WorldRect;
if (worldRect.X > worldView.Right || worldRect.Right < worldView.X) { return false; }
if (worldRect.Y < worldView.Y - worldView.Height || worldRect.Y - worldRect.Height > worldView.Y) { return false; }
}
return true;
}
public override bool IsMouseOn(Vector2 position) public override bool IsMouseOn(Vector2 position)
{ {
if (!GameMain.DebugDraw && !ShowHulls) return false; if (!GameMain.DebugDraw && !ShowHulls) return false;
@@ -118,6 +137,19 @@ namespace Barotrauma
partial void UpdateProjSpecific(float deltaTime, Camera cam) partial void UpdateProjSpecific(float deltaTime, Camera cam)
{ {
serverUpdateDelay -= deltaTime;
if (networkUpdatePending)
{
networkUpdateTimer += deltaTime;
if (networkUpdateTimer > 0.2f)
{
GameMain.NetworkMember?.CreateEntityEvent(this);
networkUpdatePending = false;
networkUpdateTimer = 0.0f;
}
}
if (EditWater) if (EditWater)
{ {
Vector2 position = cam.ScreenToWorld(PlayerInput.MousePosition); Vector2 position = cam.ScreenToWorld(PlayerInput.MousePosition);
@@ -126,10 +158,14 @@ namespace Barotrauma
if (PlayerInput.LeftButtonHeld()) if (PlayerInput.LeftButtonHeld())
{ {
WaterVolume += 1500.0f; WaterVolume += 1500.0f;
networkUpdatePending = true;
serverUpdateDelay = 0.5f;
} }
else if (PlayerInput.RightButtonHeld()) else if (PlayerInput.RightButtonHeld())
{ {
WaterVolume -= 1500.0f; WaterVolume -= 1500.0f;
networkUpdatePending = true;
serverUpdateDelay = 0.5f;
} }
} }
} }
@@ -140,7 +176,9 @@ namespace Barotrauma
{ {
if (PlayerInput.LeftButtonClicked()) if (PlayerInput.LeftButtonClicked())
{ {
new FireSource(position, this); new FireSource(position, this, isNetworkMessage: true);
networkUpdatePending = true;
serverUpdateDelay = 0.5f;
} }
} }
} }
@@ -189,8 +227,7 @@ namespace Barotrauma
return; return;
} }
Rectangle drawRect; /*if (!Visible)
if (!Visible)
{ {
drawRect = drawRect =
Submarine == null ? rect : new Rectangle((int)(Submarine.DrawPosition.X + rect.X), (int)(Submarine.DrawPosition.Y + rect.Y), rect.Width, rect.Height); Submarine == null ? rect : new Rectangle((int)(Submarine.DrawPosition.X + rect.X), (int)(Submarine.DrawPosition.Y + rect.Y), rect.Width, rect.Height);
@@ -200,7 +237,7 @@ namespace Barotrauma
new Vector2(rect.Width, rect.Height), new Vector2(rect.Width, rect.Height),
Color.Black, true, Color.Black, true,
0, (int)Math.Max((1.5f / GameScreen.Selected.Cam.Zoom), 1.0f)); 0, (int)Math.Max((1.5f / GameScreen.Selected.Cam.Zoom), 1.0f));
} }*/
if (!ShowHulls && !GameMain.DebugDraw) return; if (!ShowHulls && !GameMain.DebugDraw) return;
@@ -208,7 +245,7 @@ namespace Barotrauma
if (aiTarget != null) aiTarget.Draw(spriteBatch); if (aiTarget != null) aiTarget.Draw(spriteBatch);
drawRect = Rectangle drawRect =
Submarine == null ? rect : new Rectangle((int)(Submarine.DrawPosition.X + rect.X), (int)(Submarine.DrawPosition.Y + rect.Y), rect.Width, rect.Height); Submarine == null ? rect : new Rectangle((int)(Submarine.DrawPosition.X + rect.X), (int)(Submarine.DrawPosition.Y + rect.Y), rect.Width, rect.Height);
GUI.DrawRectangle(spriteBatch, GUI.DrawRectangle(spriteBatch,
@@ -483,6 +520,84 @@ namespace Barotrauma
width -= (int)Math.Max((x + WaveWidth) - (Submarine == null ? rect.Right : (rect.Right + Submarine.DrawPosition.X)), 0); width -= (int)Math.Max((x + WaveWidth) - (Submarine == null ? rect.Right : (rect.Right + Submarine.DrawPosition.X)), 0);
} }
} }
}
public void ClientWrite(NetBuffer msg, object[] extraData = null)
{
msg.WriteRangedSingle(MathHelper.Clamp(waterVolume / Volume, 0.0f, 1.5f), 0.0f, 1.5f, 8);
msg.Write(FireSources.Count > 0);
if (FireSources.Count > 0)
{
msg.WriteRangedInteger(0, 16, Math.Min(FireSources.Count, 16));
for (int i = 0; i < Math.Min(FireSources.Count, 16); i++)
{
var fireSource = FireSources[i];
Vector2 normalizedPos = new Vector2(
(fireSource.Position.X - rect.X) / rect.Width,
(fireSource.Position.Y - (rect.Y - rect.Height)) / rect.Height);
msg.WriteRangedSingle(MathHelper.Clamp(normalizedPos.X, 0.0f, 1.0f), 0.0f, 1.0f, 8);
msg.WriteRangedSingle(MathHelper.Clamp(normalizedPos.Y, 0.0f, 1.0f), 0.0f, 1.0f, 8);
msg.WriteRangedSingle(MathHelper.Clamp(fireSource.Size.X / rect.Width, 0.0f, 1.0f), 0, 1.0f, 8);
}
}
}
public void ClientRead(ServerNetObject type, NetBuffer message, float sendingTime)
{
float newWaterVolume = message.ReadRangedSingle(0.0f, 1.5f, 8) * Volume;
float newOxygenPercentage = message.ReadRangedSingle(0.0f, 100.0f, 8);
bool hasFireSources = message.ReadBoolean();
int fireSourceCount = 0;
List<Vector3> newFireSources = new List<Vector3>();
if (hasFireSources)
{
fireSourceCount = message.ReadRangedInteger(0, 16);
for (int i = 0; i < fireSourceCount; i++)
{
newFireSources.Add(new Vector3(
MathHelper.Clamp(message.ReadRangedSingle(0.0f, 1.0f, 8), 0.05f, 0.95f),
MathHelper.Clamp(message.ReadRangedSingle(0.0f, 1.0f, 8), 0.05f, 0.95f),
message.ReadRangedSingle(0.0f, 1.0f, 8)));
}
}
if (serverUpdateDelay > 0.0f) { return; }
WaterVolume = newWaterVolume;
OxygenPercentage = newOxygenPercentage;
for (int i = 0; i < fireSourceCount; i++)
{
Vector2 pos = new Vector2(
rect.X + rect.Width * newFireSources[i].X,
rect.Y - rect.Height + (rect.Height * newFireSources[i].Y));
float size = newFireSources[i].Z * rect.Width;
var newFire = i < FireSources.Count ?
FireSources[i] :
new FireSource(Submarine == null ? pos : pos + Submarine.Position, null, true);
newFire.Position = pos;
newFire.Size = new Vector2(size, newFire.Size.Y);
//ignore if the fire wasn't added to this room (invalid position)?
if (!FireSources.Contains(newFire))
{
newFire.Remove();
continue;
}
}
for (int i = FireSources.Count - 1; i >= fireSourceCount; i--)
{
FireSources[i].Remove();
if (i < FireSources.Count)
{
FireSources.RemoveAt(i);
}
}
} }
} }
} }
@@ -93,8 +93,6 @@ namespace Barotrauma
public void ClientRead(ServerNetObject type, NetBuffer msg, float sendingTime) public void ClientRead(ServerNetObject type, NetBuffer msg, float sendingTime)
{ {
if (GameMain.Server != null) return;
foreach (LevelWall levelWall in extraWalls) foreach (LevelWall levelWall in extraWalls)
{ {
if (levelWall.Body.BodyType == BodyType.Static) continue; if (levelWall.Body.BodyType == BodyType.Static) continue;
@@ -194,6 +194,7 @@ namespace Barotrauma
for (int i = 0; i < Sounds.Length; i++) for (int i = 0; i < Sounds.Length; i++)
{ {
if (Sounds[i] == null) { continue; }
if (SoundTriggers[i] == null || SoundTriggers[i].IsTriggered) if (SoundTriggers[i] == null || SoundTriggers[i].IsTriggered)
{ {
RoundSound roundSound = Sounds[i]; RoundSound roundSound = Sounds[i];
@@ -322,8 +322,14 @@ namespace Barotrauma
Matrix transformMatrix = cam.ShaderTransform Matrix transformMatrix = cam.ShaderTransform
* Matrix.CreateOrthographic(GameMain.GraphicsWidth, GameMain.GraphicsHeight, -1, 100) * 0.5f; * Matrix.CreateOrthographic(GameMain.GraphicsWidth, GameMain.GraphicsHeight, -1, 100) * 0.5f;
wallEdgeEffect.Texture = specular && level.GenerationParams.WallEdgeSpriteSpecular != null ?
level.GenerationParams.WallEdgeSpriteSpecular.Texture :
level.GenerationParams.WallEdgeSprite.Texture;
wallEdgeEffect.World = transformMatrix; wallEdgeEffect.World = transformMatrix;
wallCenterEffect.Texture = specular && level.GenerationParams.WallSpriteSpecular != null ?
level.GenerationParams.WallSpriteSpecular.Texture :
level.GenerationParams.WallSprite.Texture;
wallCenterEffect.World = transformMatrix; wallCenterEffect.World = transformMatrix;
graphicsDevice.SamplerStates[0] = SamplerState.LinearWrap; graphicsDevice.SamplerStates[0] = SamplerState.LinearWrap;
@@ -34,8 +34,8 @@ namespace Barotrauma
public const int DefaultBufferSize = 2000; public const int DefaultBufferSize = 2000;
public const int DefaultIndoorsBufferSize = 3000; public const int DefaultIndoorsBufferSize = 3000;
public static Vector2 DistortionScale = new Vector2(0.5f, 0.5f); public static Vector2 DistortionScale = new Vector2(2f, 2f);
public static Vector2 DistortionStrength = new Vector2(0.5f, 0.5f); public static Vector2 DistortionStrength = new Vector2(0.25f, 0.25f);
public static float BlurAmount = 0.0f; public static float BlurAmount = 0.0f;
public Vector2 WavePos public Vector2 WavePos
@@ -103,7 +103,6 @@ namespace Barotrauma
} }
else else
{ WaterEffect.CurrentTechnique = WaterEffect.Techniques["WaterShader"]; { WaterEffect.CurrentTechnique = WaterEffect.Techniques["WaterShader"];
WaterEffect.Parameters["xBlurDistance"].SetValue(BlurAmount / 100.0f);
} }
Vector2 offset = WavePos; Vector2 offset = WavePos;
@@ -20,18 +20,11 @@ namespace Barotrauma.Lights
/// the time being because it makes the lighting behave unpredictably and may cause rooms to appear /// the time being because it makes the lighting behave unpredictably and may cause rooms to appear
/// excessively bright if different lighting conditions aren't tested and accounted for. /// excessively bright if different lighting conditions aren't tested and accounted for.
/// </summary> /// </summary>
private static bool UseHullSpecificAmbientLight = false; private static readonly bool UseHullSpecificAmbientLight = false;
private static Entity viewTarget; public static Entity ViewTarget { get; set; }
public static Entity ViewTarget private float currLightMapScale;
{
get { return viewTarget; }
set {
if (viewTarget == value) return;
viewTarget = value;
}
}
private float currLightMapScale; private float currLightMapScale;
@@ -55,10 +48,7 @@ namespace Barotrauma.Lights
private BasicEffect lightEffect; private BasicEffect lightEffect;
public Effect LosEffect public Effect LosEffect { get; private set; }
{
get; private set;
}
private List<LightSource> lights; private List<LightSource> lights;
@@ -99,11 +89,12 @@ namespace Barotrauma.Lights
if (lightEffect == null) if (lightEffect == null)
{ {
lightEffect = new BasicEffect(GameMain.Instance.GraphicsDevice); lightEffect = new BasicEffect(GameMain.Instance.GraphicsDevice)
lightEffect.VertexColorEnabled = true; {
VertexColorEnabled = true,
lightEffect.TextureEnabled = true; TextureEnabled = true,
lightEffect.Texture = LightSource.LightTexture; Texture = LightSource.LightTexture
};
} }
hullAmbientLights = new Dictionary<Hull, Color>(); hullAmbientLights = new Dictionary<Hull, Color>();
@@ -284,11 +275,14 @@ namespace Barotrauma.Lights
Character.Controlled.FocusedCharacter.Draw(spriteBatch, cam); Character.Controlled.FocusedCharacter.Draw(spriteBatch, cam);
} }
foreach (Item item in Item.ItemList) if (!GUI.DisableItemHighlights)
{ {
if (item.IsHighlighted) foreach (Item item in Item.ItemList)
{ {
item.Draw(spriteBatch, false, true); if (item.IsHighlighted)
{
item.Draw(spriteBatch, false, true);
}
} }
} }
} }
@@ -391,7 +385,7 @@ namespace Barotrauma.Lights
graphics.SetRenderTarget(SpecularMap); graphics.SetRenderTarget(SpecularMap);
//clear the lightmap //clear the lightmap
graphics.Clear(Color.Gray); graphics.Clear(Color.Black);
graphics.BlendState = BlendState.AlphaBlend; graphics.BlendState = BlendState.AlphaBlend;
spriteBatch.Begin(sortMode: SpriteSortMode.Deferred, blendState: BlendState.AlphaBlend, transformMatrix: spriteBatchTransform); spriteBatch.Begin(sortMode: SpriteSortMode.Deferred, blendState: BlendState.AlphaBlend, transformMatrix: spriteBatchTransform);
@@ -400,41 +394,22 @@ namespace Barotrauma.Lights
{ {
Level.Loaded.LevelObjectManager.DrawObjects(spriteBatch, cam, drawFront: false, specular: true); Level.Loaded.LevelObjectManager.DrawObjects(spriteBatch, cam, drawFront: false, specular: true);
} }
Dictionary<Hull, Rectangle> visibleHulls = new Dictionary<Hull, Rectangle>();
foreach (Hull hull in Hull.hullList)
{
var drawRect =
hull.Submarine == null ?
hull.Rect :
new Rectangle((int)(hull.Submarine.DrawPosition.X + hull.Rect.X), (int)(hull.Submarine.DrawPosition.Y + hull.Rect.Y), hull.Rect.Width, hull.Rect.Height);
if (drawRect.Right < cam.WorldView.X || drawRect.X > cam.WorldView.Right ||
drawRect.Y - drawRect.Height > cam.WorldView.Y || drawRect.Y < cam.WorldView.Y - cam.WorldView.Height)
{
continue;
}
visibleHulls.Add(hull, drawRect);
}
foreach (Rectangle drawRect in visibleHulls.Values)
{
GUI.DrawRectangle(spriteBatch,
new Vector2(drawRect.X, -drawRect.Y),
new Vector2(drawRect.Width, drawRect.Height),
Color.Gray, true);
}
spriteBatch.End(); spriteBatch.End();
//TODO: use renderTargetFront to obstruct the things behind the sub (has to be drawn with a solid gray color)
/*spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend);
spriteBatch.Draw(renderTargetFront, new Rectangle(0, 0,
(int)(GameMain.GraphicsWidth * currLightMapScale), (int)(GameMain.GraphicsHeight * currLightMapScale)), Color.White);
spriteBatch.End();*/
//TODO: specular maps for level walls //TODO: specular maps for level walls
Level.Loaded?.Renderer?.RenderWalls(graphics, cam, specular: true); Level.Loaded?.Renderer?.RenderWalls(graphics, cam, specular: true);
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend);
if (backgroundObstructor != null)
{
spriteBatch.Draw(backgroundObstructor, new Rectangle(0, 0,
(int)(GameMain.GraphicsWidth * currLightMapScale), (int)(GameMain.GraphicsHeight * currLightMapScale)), Color.Black);
}
GUI.DrawRectangle(spriteBatch, new Rectangle(0, 0,
(int)(GameMain.GraphicsWidth * currLightMapScale), (int)(GameMain.GraphicsHeight * currLightMapScale)),
Color.White * 0.4f, isFilled: true);
spriteBatch.End();
graphics.SetRenderTarget(null); graphics.SetRenderTarget(null);
graphics.BlendState = BlendState.AlphaBlend; graphics.BlendState = BlendState.AlphaBlend;
} }
@@ -491,14 +466,14 @@ namespace Barotrauma.Lights
if (LosEnabled && LosMode != LosMode.None && ViewTarget != null) if (LosEnabled && LosMode != LosMode.None && ViewTarget != null)
{ {
Vector2 pos = ViewTarget.WorldPosition; Vector2 pos = ViewTarget.DrawPosition;
Rectangle camView = new Rectangle(cam.WorldView.X, cam.WorldView.Y - cam.WorldView.Height, cam.WorldView.Width, cam.WorldView.Height); Rectangle camView = new Rectangle(cam.WorldView.X, cam.WorldView.Y - cam.WorldView.Height, cam.WorldView.Width, cam.WorldView.Height);
Matrix shadowTransform = cam.ShaderTransform Matrix shadowTransform = cam.ShaderTransform
* Matrix.CreateOrthographic(GameMain.GraphicsWidth, GameMain.GraphicsHeight, -1, 1) * 0.5f; * Matrix.CreateOrthographic(GameMain.GraphicsWidth, GameMain.GraphicsHeight, -1, 1) * 0.5f;
var convexHulls = ConvexHull.GetHullsInRange(viewTarget.Position, cam.WorldView.Width*0.75f, viewTarget.Submarine); var convexHulls = ConvexHull.GetHullsInRange(ViewTarget.Position, cam.WorldView.Width*0.75f, ViewTarget.Submarine);
if (convexHulls != null) if (convexHulls != null)
{ {
List<VertexPositionColor> shadowVerts = new List<VertexPositionColor>(); List<VertexPositionColor> shadowVerts = new List<VertexPositionColor>();
@@ -718,7 +718,11 @@ namespace Barotrauma.Lights
if (OverrideLightTexture != null) if (OverrideLightTexture != null)
{ {
overrideTextureDims = new Vector2(OverrideLightTexture.SourceRect.Width, OverrideLightTexture.SourceRect.Height); overrideTextureDims = new Vector2(OverrideLightTexture.SourceRect.Width, OverrideLightTexture.SourceRect.Height);
uvOffset = (OverrideLightTexture.Origin / overrideTextureDims) - new Vector2(0.5f, 0.5f);
Vector2 origin = OverrideLightTexture.Origin;
if (LightSpriteEffect == SpriteEffects.FlipHorizontally) origin.X = OverrideLightTexture.SourceRect.Width - origin.X;
if (LightSpriteEffect == SpriteEffects.FlipVertically) origin.Y = (OverrideLightTexture.SourceRect.Height - origin.Y);
uvOffset = (origin / overrideTextureDims) - new Vector2(0.5f, 0.5f);
} }
// Add a vertex for the center of the mesh // Add a vertex for the center of the mesh
@@ -258,7 +258,7 @@ namespace Barotrauma
if (change.Messages.Count > 0) if (change.Messages.Count > 0)
{ {
mapAnim.EndMessage = change.Messages[Rand.Range(0,change.Messages.Count)] mapAnim.EndMessage = change.Messages[Rand.Range(0,change.Messages.Count)]
.Replace("[prevname]", prevName) .Replace("[previousname]", prevName)
.Replace("[name]", location.Name); .Replace("[name]", location.Name);
} }
mapAnimQueue.Enqueue(mapAnim); mapAnimQueue.Enqueue(mapAnim);
@@ -634,7 +634,7 @@ namespace Barotrauma
GUI.DrawString(spriteBatch, pos, GUI.DrawString(spriteBatch, pos,
location.Name, Color.White * hudOpenState * 1.5f, font: GUI.LargeFont); location.Name, Color.White * hudOpenState * 1.5f, font: GUI.LargeFont);
GUI.DrawString(spriteBatch, pos + Vector2.UnitY * 25, GUI.DrawString(spriteBatch, pos + Vector2.UnitY * 25,
location.Type.DisplayName, Color.White * hudOpenState * 1.5f); location.Type.Name, Color.White * hudOpenState * 1.5f);
} }
GameMain.Instance.GraphicsDevice.ScissorRectangle = prevScissorRect; GameMain.Instance.GraphicsDevice.ScissorRectangle = prevScissorRect;
@@ -85,6 +85,11 @@ namespace Barotrauma
get { return selectedList.Contains(this); } get { return selectedList.Contains(this); }
} }
public virtual bool IsVisible(Rectangle worldView)
{
return true;
}
public virtual void Draw(SpriteBatch spriteBatch, bool editing, bool back = true) { } public virtual void Draw(SpriteBatch spriteBatch, bool editing, bool back = true) { }
public virtual void DrawDamage(SpriteBatch spriteBatch, Effect damageEffect) { } public virtual void DrawDamage(SpriteBatch spriteBatch, Effect damageEffect) { }
@@ -1,10 +1,10 @@
using Barotrauma.Lights; using Barotrauma.Lights;
using Barotrauma.Networking; using Barotrauma.Networking;
using Lidgren.Network;
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Graphics;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
namespace Barotrauma namespace Barotrauma
{ {
@@ -105,7 +105,17 @@ namespace Barotrauma
return editingHUD; return editingHUD;
} }
public override bool IsVisible(Rectangle worldView)
{
Rectangle worldRect = WorldRect;
if (worldRect.X > worldView.Right || worldRect.Right < worldView.X) return false;
if (worldRect.Y < worldView.Y - worldView.Height || worldRect.Y - worldRect.Height > worldView.Y) return false;
return true;
}
public override void Draw(SpriteBatch spriteBatch, bool editing, bool back = true) public override void Draw(SpriteBatch spriteBatch, bool editing, bool back = true)
{ {
if (prefab.sprite == null) return; if (prefab.sprite == null) return;
@@ -159,13 +169,13 @@ namespace Barotrauma
if (back && damageEffect == null) if (back && damageEffect == null)
{ {
if (prefab.BackgroundSprite != null) if (Prefab.BackgroundSprite != null)
{ {
bool drawDropShadow = Submarine != null && HasBody; bool drawDropShadow = Submarine != null && HasBody;
Vector2 dropShadowOffset = Vector2.Zero; Vector2 dropShadowOffset = Vector2.Zero;
if (drawDropShadow) if (drawDropShadow)
{ {
dropShadowOffset = Submarine.WorldPosition - WorldPosition; dropShadowOffset = Submarine.HiddenSubPosition - Position;
if (dropShadowOffset != Vector2.Zero) if (dropShadowOffset != Vector2.Zero)
{ {
if (IsHorizontal) if (IsHorizontal)
@@ -182,14 +192,14 @@ namespace Barotrauma
if (DrawTiled) if (DrawTiled)
{ {
SpriteEffects oldEffects = prefab.BackgroundSprite.effects; SpriteEffects oldEffects = Prefab.BackgroundSprite.effects;
prefab.BackgroundSprite.effects ^= SpriteEffects; Prefab.BackgroundSprite.effects ^= SpriteEffects;
Point backGroundOffset = new Point( Point backGroundOffset = new Point(
MathUtils.PositiveModulo((int)-textureOffset.X, prefab.BackgroundSprite.SourceRect.Width), MathUtils.PositiveModulo((int)-textureOffset.X, Prefab.BackgroundSprite.SourceRect.Width),
MathUtils.PositiveModulo((int)-textureOffset.Y, prefab.BackgroundSprite.SourceRect.Height)); MathUtils.PositiveModulo((int)-textureOffset.Y, Prefab.BackgroundSprite.SourceRect.Height));
prefab.BackgroundSprite.DrawTiled( Prefab.BackgroundSprite.DrawTiled(
spriteBatch, spriteBatch,
new Vector2(rect.X + drawOffset.X, -(rect.Y + drawOffset.Y)), new Vector2(rect.X + drawOffset.X, -(rect.Y + drawOffset.Y)),
new Vector2(rect.Width, rect.Height), new Vector2(rect.Width, rect.Height),
@@ -199,21 +209,21 @@ namespace Barotrauma
if (drawDropShadow) if (drawDropShadow)
{ {
prefab.BackgroundSprite.DrawTiled( Prefab.BackgroundSprite.DrawTiled(
spriteBatch, spriteBatch,
new Vector2(rect.X + drawOffset.X, -(rect.Y + drawOffset.Y)) + dropShadowOffset, new Vector2(rect.X + drawOffset.X, -(rect.Y + drawOffset.Y)) + dropShadowOffset,
new Vector2(rect.Width, rect.Height), new Vector2(rect.Width, rect.Height),
color: Color.Black * 0.5f, color: Color.Black * 0.5f,
textureScale: TextureScale * Scale, textureScale: TextureScale * Scale,
startOffset: backGroundOffset, startOffset: backGroundOffset,
depth: (depth + prefab.BackgroundSprite.Depth) / 2.0f); depth: (depth + Prefab.BackgroundSprite.Depth) / 2.0f);
} }
prefab.BackgroundSprite.effects = oldEffects; Prefab.BackgroundSprite.effects = oldEffects;
} }
else else
{ {
prefab.BackgroundSprite.Draw( Prefab.BackgroundSprite.Draw(
spriteBatch, spriteBatch,
new Vector2(rect.X + drawOffset.X, -(rect.Y + drawOffset.Y)), new Vector2(rect.X + drawOffset.X, -(rect.Y + drawOffset.Y)),
color, color,
@@ -224,7 +234,7 @@ namespace Barotrauma
if (drawDropShadow) if (drawDropShadow)
{ {
prefab.BackgroundSprite.Draw( Prefab.BackgroundSprite.Draw(
spriteBatch, spriteBatch,
new Vector2(rect.X + drawOffset.X, -(rect.Y + drawOffset.Y)) + dropShadowOffset, new Vector2(rect.X + drawOffset.X, -(rect.Y + drawOffset.Y)) + dropShadowOffset,
Color.Black * 0.5f, Color.Black * 0.5f,
@@ -232,7 +242,7 @@ namespace Barotrauma
scale: Scale, scale: Scale,
rotate: 0, rotate: 0,
spriteEffect: SpriteEffects, spriteEffect: SpriteEffects,
depth: (depth + prefab.BackgroundSprite.Depth) / 2.0f); depth: (depth + Prefab.BackgroundSprite.Depth) / 2.0f);
} }
} }
} }
@@ -248,7 +258,7 @@ namespace Barotrauma
if (damageEffect != null) if (damageEffect != null)
{ {
float newCutoff = Sections[i].damage > 0 ? float newCutoff = Sections[i].damage > 0 ?
MathHelper.Lerp(0.2f, 0.65f, Sections[i].damage / prefab.Health) : 0.0f; MathHelper.Lerp(0.2f, 0.65f, Sections[i].damage / Prefab.Health) : 0.0f;
if (Math.Abs(newCutoff - Submarine.DamageEffectCutoff) > 0.01f || color != Submarine.DamageEffectColor) if (Math.Abs(newCutoff - Submarine.DamageEffectCutoff) > 0.01f || color != Submarine.DamageEffectColor)
{ {
@@ -317,5 +327,14 @@ namespace Barotrauma
} }
} }
} }
public void ClientRead(ServerNetObject type, NetBuffer msg, float sendingTime)
{
for (int i = 0; i < Sections.Length; i++)
{
float damage = msg.ReadRangedSingle(0.0f, 1.0f, 8) * Health;
SetDamage(i, damage);
}
}
} }
} }
@@ -1,4 +1,5 @@
using Barotrauma.Networking; using Barotrauma.Networking;
using Barotrauma.RuinGeneration;
using Barotrauma.Sounds; using Barotrauma.Sounds;
using FarseerPhysics; using FarseerPhysics;
using Lidgren.Network; using Lidgren.Network;
@@ -62,7 +63,15 @@ namespace Barotrauma
if (existingSound == null) if (existingSound == null)
{ {
existingSound = GameMain.SoundManager.LoadSound(filename, stream); try
{
existingSound = GameMain.SoundManager.LoadSound(filename, stream);
}
catch (FileNotFoundException e)
{
DebugConsole.ThrowError("Failed to load sound file \"" + filename + "\".", e);
return null;
}
} }
RoundSound newSound = new RoundSound(element, existingSound); RoundSound newSound = new RoundSound(element, existingSound);
@@ -91,6 +100,71 @@ namespace Barotrauma
RemoveRoundSound(roundSounds[i]); RemoveRoundSound(roundSounds[i]);
} }
} }
//drawing ----------------------------------------------------
public static void CullEntities(Camera cam)
{
HashSet<Submarine> visibleSubs = new HashSet<Submarine>();
foreach (Submarine sub in Loaded)
{
if (sub.WorldPosition.Y < Level.MaxEntityDepth) continue;
Rectangle worldBorders = new Rectangle(
sub.Borders.X + (int)sub.WorldPosition.X - 500,
sub.Borders.Y + (int)sub.WorldPosition.Y + 500,
sub.Borders.Width + 1000,
sub.Borders.Height + 1000);
if (RectsOverlap(worldBorders, cam.WorldView))
{
visibleSubs.Add(sub);
}
}
HashSet<Ruin> visibleRuins = new HashSet<Ruin>();
if (Level.Loaded != null)
{
foreach (Ruin ruin in Level.Loaded.Ruins)
{
Rectangle worldBorders = new Rectangle(
ruin.Area.X - 500,
ruin.Area.Y + ruin.Area.Height + 500,
ruin.Area.Width + 1000,
ruin.Area.Height + 1000);
if (RectsOverlap(worldBorders, cam.WorldView))
{
visibleRuins.Add(ruin);
}
}
}
if (visibleEntities == null)
{
visibleEntities = new List<MapEntity>(MapEntity.mapEntityList.Count);
}
else
{
visibleEntities.Clear();
}
Rectangle worldView = cam.WorldView;
foreach (MapEntity entity in MapEntity.mapEntityList)
{
if (entity.Submarine != null)
{
if (!visibleSubs.Contains(entity.Submarine)) { continue; }
}
else if (entity.ParentRuin != null)
{
if (!visibleRuins.Contains(entity.ParentRuin)) { continue; }
}
if (entity.IsVisible(worldView)) { visibleEntities.Add(entity); }
}
}
public static void Draw(SpriteBatch spriteBatch, bool editing = false) public static void Draw(SpriteBatch spriteBatch, bool editing = false)
{ {
@@ -128,14 +202,14 @@ namespace Barotrauma
GUI.DrawRectangle(spriteBatch, worldBorders, Color.White, false, 0, 5); GUI.DrawRectangle(spriteBatch, worldBorders, Color.White, false, 0, 5);
if (sub.subBody.MemPos.Count < 2) continue; if (sub.subBody.PositionBuffer.Count < 2) continue;
Vector2 prevPos = ConvertUnits.ToDisplayUnits(sub.subBody.MemPos[0].Position); Vector2 prevPos = ConvertUnits.ToDisplayUnits(sub.subBody.PositionBuffer[0].Position);
prevPos.Y = -prevPos.Y; prevPos.Y = -prevPos.Y;
for (int i = 1; i < sub.subBody.MemPos.Count; i++) for (int i = 1; i < sub.subBody.PositionBuffer.Count; i++)
{ {
Vector2 currPos = ConvertUnits.ToDisplayUnits(sub.subBody.MemPos[i].Position); Vector2 currPos = ConvertUnits.ToDisplayUnits(sub.subBody.PositionBuffer[i].Position);
currPos.Y = -currPos.Y; currPos.Y = -currPos.Y;
GUI.DrawRectangle(spriteBatch, new Rectangle((int)currPos.X - 10, (int)currPos.Y - 10, 20, 20), Color.Blue * 0.6f, true, 0.01f); GUI.DrawRectangle(spriteBatch, new Rectangle((int)currPos.X - 10, (int)currPos.Y - 10, 20, 20), Color.Blue * 0.6f, true, 0.01f);
@@ -372,30 +446,19 @@ namespace Barotrauma
public void ClientRead(ServerNetObject type, NetBuffer msg, float sendingTime) public void ClientRead(ServerNetObject type, NetBuffer msg, float sendingTime)
{ {
var newTargetPosition = new Vector2( var posInfo = PhysicsBody.ClientRead(type, msg, sendingTime, parentDebugName: Name);
msg.ReadFloat(), msg.ReadPadBits();
msg.ReadFloat());
//already interpolating with more up-to-date data -> ignore
if (subBody.MemPos.Count > 1 && subBody.MemPos[0].Timestamp > sendingTime)
{
return;
}
int index = 0; if (posInfo != null)
while (index < subBody.MemPos.Count && sendingTime > subBody.MemPos[index].Timestamp)
{ {
index++; int index = 0;
} while (index < subBody.PositionBuffer.Count && sendingTime > subBody.PositionBuffer[index].Timestamp)
{
index++;
}
//position with the same timestamp already in the buffer (duplicate packet?) subBody.PositionBuffer.Insert(index, posInfo);
// -> no need to add again
if (index < subBody.MemPos.Count && sendingTime == subBody.MemPos[index].Timestamp)
{
return;
} }
subBody.MemPos.Insert(index, new PosInfo(newTargetPosition, 0.0f, sendingTime));
} }
} }
} }
@@ -0,0 +1,61 @@
using FarseerPhysics;
using Microsoft.Xna.Framework;
using System.Collections.Generic;
namespace Barotrauma
{
partial class SubmarineBody
{
partial void ClientUpdatePosition(float deltaTime)
{
if (GameMain.Client == null) { return; }
Vector2 newVelocity = Body.LinearVelocity;
Vector2 newPosition = Body.SimPosition;
Body.CorrectPosition(positionBuffer, out newPosition, out newVelocity, out _, out _);
Vector2 moveAmount = ConvertUnits.ToDisplayUnits(newPosition - Body.SimPosition);
newVelocity = newVelocity.ClampLength(100.0f);
if (!MathUtils.IsValid(newVelocity) || moveAmount.LengthSquared() < 0.0001f)
{
return;
}
List<Submarine> subsToMove = submarine.GetConnectedSubs();
foreach (Submarine dockedSub in subsToMove)
{
if (dockedSub == submarine) continue;
//clear the position buffer of the docked subs to prevent unnecessary position corrections
dockedSub.SubBody.positionBuffer.Clear();
}
Submarine closestSub = null;
if (Character.Controlled == null)
{
closestSub = Submarine.FindClosest(GameMain.GameScreen.Cam.Position);
}
else
{
closestSub = Character.Controlled.Submarine;
}
bool displace = moveAmount.LengthSquared() > 100.0f * 100.0f;
foreach (Submarine sub in subsToMove)
{
sub.PhysicsBody.SetTransform(sub.PhysicsBody.SimPosition + ConvertUnits.ToSimUnits(moveAmount), 0.0f);
sub.PhysicsBody.LinearVelocity = newVelocity;
if (displace) sub.SubBody.DisplaceCharacters(moveAmount);
}
if (closestSub != null && subsToMove.Contains(closestSub))
{
GameMain.GameScreen.Cam.Position += moveAmount;
if (GameMain.GameScreen.Cam.TargetPos != Vector2.Zero) GameMain.GameScreen.Cam.TargetPos += moveAmount;
if (Character.Controlled != null) Character.Controlled.CursorPosition += moveAmount;
}
}
}
}
@@ -10,6 +10,11 @@ namespace Barotrauma
private const int IconSize = 32; private const int IconSize = 32;
private static int[] iconIndices = { 3, 0, 1, 2 }; private static int[] iconIndices = { 3, 0, 1, 2 };
public override bool IsVisible(Rectangle worldView)
{
return Screen.Selected == GameMain.SubEditorScreen || GameMain.DebugDraw;
}
public override void Draw(SpriteBatch spriteBatch, bool editing, bool back = true) public override void Draw(SpriteBatch spriteBatch, bool editing, bool back = true)
{ {
if (!editing && !GameMain.DebugDraw) return; if (!editing && !GameMain.DebugDraw) return;
@@ -0,0 +1,298 @@
using System;
using System.IO;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Linq;
using System.Runtime.InteropServices;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Barotrauma.Sounds;
namespace Barotrauma.Media
{
public class Video : IDisposable
{
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate IntPtr LibVLCVideoLockCb(IntPtr opaque, IntPtr planes);
private static LibVLCVideoLockCb VideoLockDelegate;
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void LibVLCVideoUnlockCb(IntPtr opaque, IntPtr picture, IntPtr planes);
private static LibVLCVideoUnlockCb VideoUnlockDelegate;
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void LibVLCVideoDisplayCb(IntPtr opaque, IntPtr picture);
private static LibVLCVideoDisplayCb VideoDisplayDelegate;
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void LibVLCAudioPlayCb(IntPtr data, IntPtr samples, uint count, long pts);
private static LibVLCAudioPlayCb AudioPlayDelegate;
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void LibVLCAudioPauseCb(IntPtr data, long pts);
private static LibVLCAudioPauseCb AudioPauseDelegate;
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void LibVLCAudioResumeCb(IntPtr data, long pts);
private static LibVLCAudioResumeCb AudioResumeDelegate;
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void LibVLCAudioFlushCb(IntPtr data, long pts);
private static LibVLCAudioFlushCb AudioFlushDelegate;
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void LibVLCAudioDrainCb(IntPtr data);
private static LibVLCAudioDrainCb AudioDrainDelegate;
private static IntPtr lib = IntPtr.Zero;
private static Dictionary<int, Video> videos;
private static int latestVideoId;
public static void Init()
{
if (lib == IntPtr.Zero)
{
string[] parameters = {
//"--no-xlib"
};
lib = LibVlcWrapper.LibVlcMethods.libvlc_new(parameters.Length, parameters);
videos = new Dictionary<int, Video>();
latestVideoId = 0;
VideoLockDelegate = VideoLockCallback;
VideoUnlockDelegate = VideoUnlockCallback;
VideoDisplayDelegate = VideoDisplayCallback;
AudioPlayDelegate = AudioPlayCallback;
AudioPauseDelegate = AudioPauseCallback;
AudioResumeDelegate = AudioResumeCallback;
AudioFlushDelegate = AudioFlushCallback;
AudioDrainDelegate = AudioDrainCallback;
}
}
public static void Close()
{
if (lib != IntPtr.Zero)
{
List<int> keys = videos.Keys.ToList();
foreach (int key in keys)
{
videos[key].Dispose();
}
LibVlcWrapper.LibVlcMethods.libvlc_free(lib);
lib = IntPtr.Zero;
}
}
private int videoId;
private IntPtr unmanagedData;
private IntPtr media;
private IntPtr mediaPlayer;
private Texture2D texture;
private byte[] textureData;
private object mutex;
private VideoSound sound;
/*private IntPtr videoLockDelegate;
private IntPtr videoUnlockDelegate;
private IntPtr videoDisplayDelegate;*/
public uint Width { get; private set; }
public uint Height { get; private set; }
public Video(GraphicsDevice graphicsDevice,SoundManager soundManager,string filename,uint width,uint height)
{
Init();
mutex = new object();
sound = new VideoSound(soundManager, filename, 44100, this);
videos.Add(latestVideoId, this);
videoId = latestVideoId; latestVideoId++;
/*using (var stream = File.OpenRead(filename))
{*/
byte[] filenameBytes = Encoding.UTF8.GetBytes(filename);
byte[] filenameBytesNullTerminated = new byte[filenameBytes.Length + 1];
filenameBytesNullTerminated[filenameBytes.Length] = 0;
Array.Copy(filenameBytes, filenameBytesNullTerminated, filenameBytes.Length);
media = LibVlcWrapper.LibVlcMethods.libvlc_media_new_path(lib, filenameBytesNullTerminated);
LibVlcWrapper.LibVlcMethods.libvlc_media_parse(media);
mediaPlayer = LibVlcWrapper.LibVlcMethods.libvlc_media_player_new(lib);
LibVlcWrapper.LibVlcMethods.libvlc_media_player_set_media(mediaPlayer, media);
//LibVlcWrapper.LibVlcMethods.libvlc_media_release(media);
//LibVlcWrapper.LibVlcMethods.libvlc_video_get_size(mediaPlayer, 0, out width, out height);
texture = new Texture2D(graphicsDevice, (int)width, (int)height);
Width = width; Height = height;
unmanagedData = Marshal.AllocHGlobal(sizeof(int)*2+(int)(width*height*3));
int[] arr = { videoId, 1 };
Marshal.Copy(arr, 0, unmanagedData, 2);
textureData = new byte[width * height * 3];
for (int i = 0; i < width*height*3; i++)
{
textureData[i] = 0;
}
IntPtr videoLockDelegatePtr = Marshal.GetFunctionPointerForDelegate(VideoLockDelegate);
IntPtr videoUnlockDelegatePtr = Marshal.GetFunctionPointerForDelegate(VideoUnlockDelegate);
IntPtr videoDisplayDelegatePtr = Marshal.GetFunctionPointerForDelegate(VideoDisplayDelegate);
LibVlcWrapper.LibVlcMethods.libvlc_video_set_callbacks(mediaPlayer, videoLockDelegatePtr, videoUnlockDelegatePtr, videoDisplayDelegatePtr, unmanagedData);
LibVlcWrapper.LibVlcMethods.libvlc_video_set_format(mediaPlayer, Encoding.UTF8.GetBytes("RV24"), (int)width, (int)height, (int)width * 3);
IntPtr audioPlayDelegatePtr = Marshal.GetFunctionPointerForDelegate(AudioPlayDelegate);
IntPtr audioPauseDelegatePtr = Marshal.GetFunctionPointerForDelegate(AudioPauseDelegate);
IntPtr audioResumeDelegatePtr = Marshal.GetFunctionPointerForDelegate(AudioResumeDelegate);
IntPtr audioFlushDelegatePtr = Marshal.GetFunctionPointerForDelegate(AudioFlushDelegate);
IntPtr audioDrainDelegatePtr = Marshal.GetFunctionPointerForDelegate(AudioDrainDelegate);
LibVlcWrapper.LibVlcMethods.libvlc_audio_set_callbacks(mediaPlayer, audioPlayDelegatePtr, audioPauseDelegatePtr, audioResumeDelegatePtr, audioFlushDelegatePtr, audioDrainDelegatePtr, unmanagedData);
LibVlcWrapper.LibVlcMethods.libvlc_audio_set_format(mediaPlayer, Encoding.UTF8.GetBytes("S16N"), 44100, 2);
LibVlcWrapper.LibVlcMethods.libvlc_audio_set_delay(mediaPlayer, 0);
LibVlcWrapper.LibVlcMethods.libvlc_media_player_play(mediaPlayer);
//}
}
public void Dispose()
{
LibVlcWrapper.LibVlcMethods.libvlc_media_player_stop(mediaPlayer);
Monitor.Enter(mutex);
//just waiting for callbacks to be done
Monitor.Exit(mutex);
Marshal.FreeHGlobal(unmanagedData);
sound.Dispose();
LibVlcWrapper.LibVlcMethods.libvlc_media_release(media);
LibVlcWrapper.LibVlcMethods.libvlc_media_player_release(mediaPlayer);
texture.Dispose();
videos.Remove(videoId);
}
public bool IsPlaying
{
get
{
return LibVlcWrapper.LibVlcMethods.libvlc_media_player_is_playing(mediaPlayer)!=0;
}
}
public Texture2D GetTexture()
{
Monitor.Enter(mutex);
int[] arr = { -1 };
IntPtr changedPtr = (IntPtr)(unmanagedData.ToInt64() + sizeof(int));
Marshal.Copy(changedPtr, arr, 0, 1);
if (arr[0]!=0)
{
IntPtr colorLocation = (IntPtr)(unmanagedData.ToInt64() + sizeof(int) * 2);
Marshal.Copy(colorLocation, textureData, 0, (int)(Width * Height * 3));
Color[] colors = new Color[Width * Height];
for (int y = 0; y < Height;y++)
{
for (int x = 0; x < Width;x++)
{
colors[x + y * Width] = new Color(textureData[3 * (x + y * Width) + 0],
textureData[3 * (x + y * Width) + 1],
textureData[3 * (x + y * Width) + 2],
(byte)255);
}
}
texture.SetData(colors);
arr[0] = 0;
Marshal.Copy(arr, 0, changedPtr, 1);
}
if (!sound.IsPlaying()) videos[videoId].sound.Play();
Monitor.Exit(mutex);
return texture;
}
static IntPtr VideoLockCallback(IntPtr opaque, IntPtr planes)
{
int[] arr = { -1 };
Marshal.Copy(opaque, arr, 0, 1);
int mutexIndex = arr[0];
Monitor.Enter(videos[mutexIndex].mutex);
IntPtr unmanagedData = (IntPtr)(opaque.ToInt64() + sizeof(int) * 2);
IntPtr[] ptrPtr = { unmanagedData };
Marshal.Copy(ptrPtr, 0, planes, 1);
return IntPtr.Zero;
}
static void VideoUnlockCallback(IntPtr opaque, IntPtr picture, IntPtr planes)
{
int[] arr = { -1 };
Marshal.Copy(opaque, arr, 0, 1);
int mutexIndex = arr[0];
arr[0] = 1;
IntPtr changedPtr = (IntPtr)(opaque.ToInt64() + sizeof(int));
Marshal.Copy(arr, 0, changedPtr, 1);
Monitor.Exit(videos[mutexIndex].mutex);
}
static void VideoDisplayCallback(IntPtr opaque,IntPtr picture)
{
//Assert(picture == IntPtr.Zero);
}
static void AudioPlayCallback(IntPtr data, IntPtr samples, uint count, long pts)
{
short[] buf = new short[count*2];
Marshal.Copy(samples, buf, 0, (int)count*2);
int[] arr = { -1 };
Marshal.Copy(data, arr, 0, 1);
int mutexIndex = arr[0];
Monitor.Enter(videos[mutexIndex].mutex);
videos[mutexIndex].sound.Enqueue(buf);
Monitor.Exit(videos[mutexIndex].mutex);
}
static void AudioPauseCallback(IntPtr data, long pts)
{
}
static void AudioResumeCallback(IntPtr data, long pts)
{
}
static void AudioFlushCallback(IntPtr data, long pts)
{
}
static void AudioDrainCallback(IntPtr data)
{
}
}
}
@@ -1,7 +1,22 @@
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework;
using Lidgren.Network;
using System;
using System.Collections.Generic;
namespace Barotrauma.Networking namespace Barotrauma.Networking
{ {
partial class BannedPlayer
{
public BannedPlayer(string name, UInt16 uniqueIdentifier, bool isRangeBan, string ip, ulong steamID)
{
this.Name = name;
this.SteamID = steamID;
this.IsRangeBan = isRangeBan;
this.IP = ip;
this.UniqueIdentifier = uniqueIdentifier;
}
}
partial class BanList partial class BanList
{ {
private GUIComponent banFrame; private GUIComponent banFrame;
@@ -11,12 +26,27 @@ namespace Barotrauma.Networking
get { return banFrame; } get { return banFrame; }
} }
public List<UInt16> localRemovedBans = new List<UInt16>();
public List<UInt16> localRangeBans = new List<UInt16>();
private void RecreateBanFrame()
{
if (banFrame != null)
{
var parent = banFrame.Parent;
parent.RemoveChild(banFrame);
CreateBanFrame(parent);
}
}
public GUIComponent CreateBanFrame(GUIComponent parent) public GUIComponent CreateBanFrame(GUIComponent parent)
{ {
banFrame = new GUIListBox(new RectTransform(Vector2.One, parent.RectTransform, Anchor.Center)); banFrame = new GUIListBox(new RectTransform(Vector2.One, parent.RectTransform, Anchor.Center));
foreach (BannedPlayer bannedPlayer in bannedPlayers) foreach (BannedPlayer bannedPlayer in bannedPlayers)
{ {
if (localRemovedBans.Contains(bannedPlayer.UniqueIdentifier)) continue;
var playerFrame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.25f), ((GUIListBox)banFrame).Content.RectTransform) { MinSize = new Point(0, 70) }, style: null) var playerFrame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.25f), ((GUIListBox)banFrame).Content.RectTransform) { MinSize = new Point(0, 70) }, style: null)
{ {
UserData = banFrame UserData = banFrame
@@ -28,8 +58,10 @@ namespace Barotrauma.Networking
RelativeSpacing = 0.05f RelativeSpacing = 0.05f
}; };
string ip = bannedPlayer.IP;
if (localRangeBans.Contains(bannedPlayer.UniqueIdentifier)) ip = ToRange(ip);
GUITextBlock textBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.3f), paddedPlayerFrame.RectTransform), GUITextBlock textBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.3f), paddedPlayerFrame.RectTransform),
bannedPlayer.IP + " (" + bannedPlayer.Name + ")"); bannedPlayer.Name + " (" + ip + ")");
var removeButton = new GUIButton(new RectTransform(new Vector2(0.2f, 0.4f), paddedPlayerFrame.RectTransform, Anchor.TopRight), TextManager.Get("BanListRemove")) var removeButton = new GUIButton(new RectTransform(new Vector2(0.2f, 0.4f), paddedPlayerFrame.RectTransform, Anchor.TopRight), TextManager.Get("BanListRemove"))
{ {
@@ -71,14 +103,9 @@ namespace Barotrauma.Networking
BannedPlayer banned = obj as BannedPlayer; BannedPlayer banned = obj as BannedPlayer;
if (banned == null) return false; if (banned == null) return false;
RemoveBan(banned); localRemovedBans.Add(banned.UniqueIdentifier);
if (banFrame != null) RecreateBanFrame();
{
var parent = banFrame.Parent;
parent.RemoveChild(banFrame);
CreateBanFrame(parent);
}
return true; return true;
} }
@@ -88,14 +115,9 @@ namespace Barotrauma.Networking
BannedPlayer banned = obj as BannedPlayer; BannedPlayer banned = obj as BannedPlayer;
if (banned == null) return false; if (banned == null) return false;
RangeBan(banned); localRangeBans.Add(banned.UniqueIdentifier);
if (banFrame != null) RecreateBanFrame();
{
var parent = banFrame.Parent;
parent.RemoveChild(banFrame);
CreateBanFrame(parent);
}
return true; return true;
} }
@@ -106,5 +128,66 @@ namespace Barotrauma.Networking
return true; return true;
} }
public void ClientAdminRead(NetBuffer incMsg)
{
bool hasPermission = incMsg.ReadBoolean();
if (!hasPermission)
{
incMsg.ReadPadBits();
return;
}
bool isOwner = incMsg.ReadBoolean();
incMsg.ReadPadBits();
bannedPlayers.Clear();
Int32 bannedPlayerCount = incMsg.ReadVariableInt32();
for (int i = 0; i < bannedPlayerCount; i++)
{
string name = incMsg.ReadString();
UInt16 uniqueIdentifier = incMsg.ReadUInt16();
bool isRangeBan = incMsg.ReadBoolean(); incMsg.ReadPadBits();
string ip = "";
UInt64 steamID = 0;
if (isOwner)
{
ip = incMsg.ReadString();
steamID = incMsg.ReadUInt64();
}
else
{
ip = "IP concealed by host";
steamID = 0;
}
bannedPlayers.Add(new BannedPlayer(name, uniqueIdentifier, isRangeBan, ip, steamID));
}
if (banFrame != null)
{
var parent = banFrame.Parent;
parent.RemoveChild(banFrame);
CreateBanFrame(parent);
}
}
public void ClientAdminWrite(NetBuffer outMsg)
{
outMsg.Write((UInt16)localRemovedBans.Count);
foreach (UInt16 uniqueId in localRemovedBans)
{
outMsg.Write(uniqueId);
}
outMsg.Write((UInt16)localRangeBans.Count);
foreach (UInt16 uniqueId in localRangeBans)
{
outMsg.Write(uniqueId);
}
localRemovedBans.Clear();
localRangeBans.Clear();
}
} }
} }
@@ -60,7 +60,7 @@ namespace Barotrauma.Networking
{ {
orderOption = order.Options[optionIndex]; orderOption = order.Options[optionIndex];
} }
txt = order.GetChatMessage(targetCharacter?.Name, senderCharacter?.CurrentHull?.RoomName, orderOption); txt = order.GetChatMessage(targetCharacter?.Name, senderCharacter?.CurrentHull?.RoomName, givingOrderToSelf: targetCharacter == senderCharacter, orderOption: orderOption);
if (order.TargetAllCharacters) if (order.TargetAllCharacters)
{ {
@@ -99,7 +99,7 @@ namespace Barotrauma.Networking
{ {
return; return;
} }
GameMain.Client.ServerLog?.WriteLine(txt, messageType); GameMain.Client.ServerSettings.ServerLog?.WriteLine(txt, messageType);
break; break;
default: default:
GameMain.Client.AddChatMessage(txt, type, senderName, senderCharacter); GameMain.Client.AddChatMessage(txt, type, senderName, senderCharacter);
@@ -0,0 +1,137 @@
using Barotrauma.Sounds;
using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
using System.Linq;
namespace Barotrauma.Networking
{
struct TempClient
{
public string Name;
public byte ID;
public UInt16 CharacterID;
public bool Muted;
}
partial class Client : IDisposable
{
public VoipSound VoipSound
{
get;
set;
}
private bool mutedLocally;
public bool MutedLocally
{
get { return mutedLocally; }
set
{
if (mutedLocally == value) { return; }
mutedLocally = value;
#if CLIENT
GameMain.NetLobbyScreen.SetPlayerVoiceIconState(this, muted, mutedLocally);
GameMain.GameSession?.CrewManager?.SetPlayerVoiceIconState(this, muted, mutedLocally);
#endif
}
}
public void UpdateSoundPosition()
{
if (VoipSound != null)
{
if (!VoipSound.IsPlaying)
{
DebugConsole.Log("Destroying voipsound");
VoipSound.Dispose();
VoipSound = null;
return;
}
if (character != null)
{
VoipSound.SetPosition(new Vector3(character.WorldPosition.X, character.WorldPosition.Y, 0.0f));
}
else
{
VoipSound.SetPosition(null);
}
}
}
partial void InitProjSpecific()
{
VoipQueue = null; VoipSound = null;
if (ID == GameMain.Client.ID) return;
VoipQueue = new VoipQueue(ID, false, true);
GameMain.Client.VoipClient.RegisterQueue(VoipQueue);
VoipSound = null;
}
public void SetPermissions(ClientPermissions permissions, List<string> permittedConsoleCommands)
{
List<DebugConsole.Command> permittedCommands = new List<DebugConsole.Command>();
foreach (string commandName in permittedConsoleCommands)
{
var consoleCommand = DebugConsole.Commands.Find(c => c.names.Contains(commandName));
if (consoleCommand != null)
{
permittedCommands.Add(consoleCommand);
}
}
SetPermissions(permissions, permittedCommands);
}
public void SetPermissions(ClientPermissions permissions, List<DebugConsole.Command> permittedConsoleCommands)
{
if (GameMain.Client == null)
{
return;
}
Permissions = permissions;
PermittedConsoleCommands = new List<DebugConsole.Command>(permittedConsoleCommands);
}
public void GivePermission(ClientPermissions permission)
{
if (GameMain.Client == null || !GameMain.Client.HasPermission(ClientPermissions.ManagePermissions))
{
return;
}
if (!Permissions.HasFlag(permission)) Permissions |= permission;
}
public void RemovePermission(ClientPermissions permission)
{
if (GameMain.Client == null || !GameMain.Client.HasPermission(ClientPermissions.ManagePermissions))
{
return;
}
if (Permissions.HasFlag(permission)) Permissions &= ~permission;
}
public bool HasPermission(ClientPermissions permission)
{
if (GameMain.Client == null)
{
return false;
}
return Permissions.HasFlag(permission);
}
partial void DisposeProjSpecific()
{
if (VoipQueue != null)
{
GameMain.Client.VoipClient.UnregisterQueue(VoipQueue);
}
if (VoipSound != null)
{
VoipSound.Dispose();
VoipSound = null;
}
}
}
}
@@ -6,8 +6,6 @@ namespace Barotrauma
{ {
public void ClientRead(ServerNetObject type, Lidgren.Network.NetBuffer message, float sendingTime) public void ClientRead(ServerNetObject type, Lidgren.Network.NetBuffer message, float sendingTime)
{ {
if (GameMain.Server != null) return;
bool remove = message.ReadBoolean(); bool remove = message.ReadBoolean();
if (remove) if (remove)

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