v0.10.5.1

This commit is contained in:
Juan Pablo Arce
2020-09-22 11:31:56 -03:00
parent 44032d0ae0
commit 0002ad2c50
343 changed files with 12276 additions and 5023 deletions
@@ -68,29 +68,52 @@ namespace Barotrauma.Items.Components
if (Window.Height > 0 && Window.Width > 0)
{
rect.Height = -(int)(Window.Y * item.Scale);
rect.Y += (int)(doorRect.Height * openState);
rect.Height = Math.Max(rect.Height - (rect.Y - doorRect.Y), 0);
rect.Y = Math.Min(doorRect.Y, rect.Y);
if (convexHull2 != null)
if (IsHorizontal)
{
Rectangle rect2 = doorRect;
rect2.Y += (int)(Window.Y * item.Scale - Window.Height * item.Scale);
rect2.Y += (int)(doorRect.Height * openState);
rect2.Y = Math.Min(doorRect.Y, rect2.Y);
rect2.Height = rect2.Y - (doorRect.Y - (int)(doorRect.Height * (1.0f - openState)));
if (rect2.Height == 0)
rect.Width = (int)(Window.X * item.Scale);
rect.X -= (int)(doorRect.Width * openState);
rect.Width = Math.Max(rect.Width - (doorRect.X - rect.X), 0);
rect.X = Math.Max(doorRect.X, rect.X);
if (convexHull2 != null)
{
convexHull2.Enabled = false;
Rectangle rect2 = doorRect;
rect2.X += (int)(Window.Right * item.Scale);
rect2.X -= (int)(doorRect.Width * openState);
rect2.X = Math.Max(doorRect.X, rect2.X);
rect2.Width = doorRect.Right - (int)(doorRect.Width * openState) - rect2.X;
if (rect2.Width == 0)
{
convexHull2.Enabled = false;
}
else
{
convexHull2.Enabled = true;
convexHull2.SetVertices(GetConvexHullCorners(rect2));
}
}
else
}
else
{
rect.Height = -(int)(Window.Y * item.Scale);
rect.Y += (int)(doorRect.Height * openState);
rect.Height = Math.Max(rect.Height - (rect.Y - doorRect.Y), 0);
rect.Y = Math.Min(doorRect.Y, rect.Y);
if (convexHull2 != null)
{
convexHull2.Enabled = true;
convexHull2.SetVertices(GetConvexHullCorners(rect2));
Rectangle rect2 = doorRect;
rect2.Y += (int)(Window.Y * item.Scale - Window.Height * item.Scale);
rect2.Y += (int)(doorRect.Height * openState);
rect2.Y = Math.Min(doorRect.Y, rect2.Y);
rect2.Height = rect2.Y - (doorRect.Y - (int)(doorRect.Height * (1.0f - openState)));
if (rect2.Height == 0)
{
convexHull2.Enabled = false;
}
else
{
convexHull2.Enabled = true;
convexHull2.SetVertices(GetConvexHullCorners(rect2));
}
}
}
}
@@ -251,8 +274,9 @@ namespace Barotrauma.Items.Components
bool open = msg.ReadBoolean();
bool broken = msg.ReadBoolean();
bool forcedOpen = msg.ReadBoolean();
bool isStuck = msg.ReadBoolean();
SetState(open, isNetworkMessage: true, sendNetworkMessage: false, forcedOpen: forcedOpen);
Stuck = msg.ReadRangedSingle(0.0f, 100.0f, 8);
stuck = msg.ReadRangedSingle(0.0f, 100.0f, 8);
UInt16 lastUserID = msg.ReadUInt16();
Character user = lastUserID == 0 ? null : Entity.FindEntityByID(lastUserID) as Character;
if (user != lastUser)
@@ -260,7 +284,7 @@ namespace Barotrauma.Items.Components
lastUser = user;
toggleCooldownTimer = ToggleCoolDown;
}
this.isStuck = isStuck;
if (isStuck) { OpenState = 0.0f; }
IsBroken = broken;
PredictedState = null;
@@ -0,0 +1,360 @@
#nullable enable
using System;
using System.Collections.Generic;
using System.Xml.Linq;
using Barotrauma.Networking;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace Barotrauma.Items.Components
{
internal partial class VineTile
{
public void Draw(SpriteBatch spriteBatch, Vector2 position, float depth, float leafDepth)
{
Vector2 pos = position + Position;
pos.Y = -pos.Y;
VineSprite vineSprite = Parent.VineSprites[Type];
Color color = Parent.Decayed ? Parent.DeadTint : Parent.VineTint;
float layer1 = depth + 0.01f, // flowers
layer2 = depth + 0.02f, // decay atlas
layer3 = depth + 0.03f; // branches and leaves
float scale = Parent.VineScale * VineStep;
if (Parent.VineAtlas != null)
{
spriteBatch.Draw(Parent.VineAtlas.Texture, pos + offset, vineSprite.SourceRect, color, 0f, vineSprite.AbsoluteOrigin, scale, SpriteEffects.None, layer3);
}
if (Parent.DecayAtlas != null)
{
spriteBatch.Draw(Parent.DecayAtlas.Texture, pos, vineSprite.SourceRect, HealthColor, 0f, vineSprite.AbsoluteOrigin, scale, SpriteEffects.None, layer2);
}
if (FlowerConfig.Variant >= 0 && !Parent.Decayed)
{
Sprite flowerSprite = Parent.FlowerSprites[FlowerConfig.Variant];
flowerSprite.Draw(spriteBatch, pos, Parent.FlowerTint, flowerSprite.Origin, scale: Parent.BaseFlowerScale * FlowerConfig.Scale * FlowerStep, rotate: FlowerConfig.Rotation, depth: layer1);
}
if (LeafConfig.Variant >= 0)
{
Sprite leafSprite = Parent.LeafSprites[LeafConfig.Variant];
leafSprite.Draw(spriteBatch, pos, Parent.Decayed ? Parent.DeadTint : Parent.LeafTint, leafSprite.Origin, scale: Parent.BaseLeafScale * LeafConfig.Scale * FlowerStep, rotate: LeafConfig.Rotation, depth: layer3 + leafDepth);
}
}
}
internal class VineSprite
{
[Serialize("0,0,0,0", false)]
public Rectangle SourceRect { get; private set; }
[Serialize("0.5,0.5", false)]
public Vector2 Origin { get; private set; }
public Vector2 AbsoluteOrigin;
public VineSprite(XElement element)
{
SerializableProperty.DeserializeProperties(this, element);
AbsoluteOrigin = new Vector2(SourceRect.Width * Origin.X, SourceRect.Height * Origin.Y);
}
}
internal partial class Growable
{
public readonly Dictionary<VineTileType, VineSprite> VineSprites = new Dictionary<VineTileType, VineSprite>();
public readonly List<Sprite> FlowerSprites = new List<Sprite>();
public readonly List<Sprite> LeafSprites = new List<Sprite>();
public Sprite? VineAtlas, DecayAtlas;
protected override void RemoveComponentSpecific()
{
VineAtlas?.Remove();
DecayAtlas?.Remove();
foreach (Sprite sprite in FlowerSprites)
{
sprite.Remove();
}
foreach (Sprite sprite in LeafSprites)
{
sprite.Remove();
}
}
public void Draw(SpriteBatch spriteBatch, Planter planter, Vector2 offset, float depth)
{
const float zStep = 0.0001f;
float leafDepth = 0f;
foreach (VineTile vine in Vines)
{
leafDepth += zStep;
vine.Draw(spriteBatch, planter.Item.DrawPosition + offset, depth, leafDepth);
}
if (GameMain.DebugDraw)
{
foreach (Rectangle rect in FailedRectangles)
{
Rectangle wRect = rect;
wRect.Y = -wRect.Y;
wRect.Y -= wRect.Height;
GUI.DrawRectangle(spriteBatch, wRect, Color.Red);
}
}
}
partial void LoadVines(XElement element)
{
string? vineAtlasPath = element.GetAttributeString("vineatlas", null);
string? decayAtlasPath = element.GetAttributeString("decayatlas", null);
if (vineAtlasPath != null)
{
VineAtlas = new Sprite(vineAtlasPath, Rectangle.Empty);
}
if (decayAtlasPath != null)
{
DecayAtlas = new Sprite(decayAtlasPath, Rectangle.Empty);
}
foreach (XElement subElement in element.Elements())
{
switch (subElement.Name.ToString().ToLowerInvariant())
{
case "vinesprite":
var tileType = subElement.GetAttributeString("type", null);
VineTileType type = Enum.Parse<VineTileType>(tileType);
VineSprites.Add(type, new VineSprite(subElement));
break;
case "flowersprite":
FlowerSprites.Add(new Sprite(subElement));
break;
case "leafsprite":
LeafSprites.Add(new Sprite(subElement));
break;
}
flowerVariants = FlowerSprites.Count;
leafVariants = LeafSprites.Count;
}
foreach (VineTileType type in Enum.GetValues(typeof(VineTileType)))
{
if (!VineSprites.ContainsKey(type))
{
DebugConsole.ThrowError($"Vine sprite missing from {item.prefab.Identifier}: {type}");
}
}
}
private readonly object mutex = new object();
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
{
Health = msg.ReadRangedSingle(0, MaxHealth, 8);
int startOffset = msg.ReadRangedInteger(-1, MaximumVines);
if (startOffset > -1)
{
int vineCount = msg.ReadRangedInteger(0, VineChunkSize);
List<VineTile> tiles = new List<VineTile>();
for (int i = 0; i < vineCount; i++)
{
VineTileType vineType = (VineTileType) msg.ReadRangedInteger(0b0000, 0b1111);
int flowerConfig = msg.ReadRangedInteger(0, 0xFFF);
int leafConfig = msg.ReadRangedInteger(0, 0xFFF);
sbyte posX = (sbyte) msg.ReadByte(), posY = (sbyte) msg.ReadByte();
Vector2 pos = new Vector2(posX * VineTile.Size, posY * VineTile.Size);
tiles.Add(new VineTile(this, pos, vineType, FoliageConfig.Deserialize(flowerConfig), FoliageConfig.Deserialize(leafConfig)));
}
// is this even needed??
lock (mutex)
{
for (var i = 0; i < vineCount; i++)
{
int index = i + startOffset;
if (index >= Vines.Count)
{
Vines.Add(tiles[i]);
continue;
}
VineTile oldVine = Vines[index];
VineTile newVine = tiles[i];
newVine.GrowthStep = oldVine.GrowthStep;
Vines[index] = newVine;
}
}
}
UpdateBranchHealth();
ResetPlanterSize();
}
private void ResetPlanterSize()
{
if (item.ParentInventory is ItemInventory itemInventory && itemInventory.Owner is Item parentItem)
{
if (parentItem.GetComponent<Planter>() is { } planter)
{
planter.Item.ResetCachedVisibleSize();
}
}
}
#if DEBUG
private int seed;
// Huge bowl of spaghetti
public void CreateDebugHUD(Planter planter, PlantSlot slot)
{
Vector2 relativeSize = new Vector2(0.3f, 0.6f);
GUIMessageBox msgBox = new GUIMessageBox(item.Name, "", new[] { TextManager.Get("applysettingsbutton") }, relativeSize);
GUILayoutGroup content = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.85f), msgBox.Content.RectTransform)) { Stretch = true };
GUINumberInput seedInput = CreateIntEntry("Random Seed", seed, content.RectTransform);
GUINumberInput vineTileSizeInput = CreateIntEntry("Vine Tile Size (Global)", VineTile.Size, content.RectTransform);
GUINumberInput[] leafScaleRangeInput = CreateMinMaxEntry("Leaf Scale Range (Global)", new []{ MinLeafScale, MaxLeafScale }, 1.5f, content.RectTransform);
GUINumberInput[] flowerScaleRangeInput = CreateMinMaxEntry("Flower Scale Range (Global)", new []{ MinFlowerScale, MaxFlowerScale }, 1.5f, content.RectTransform);
GUINumberInput vineCountInput = CreateIntEntry("Vine Count", MaximumVines, content.RectTransform);
GUINumberInput vineScaleInput = CreateFloatEntry("Vine Scale", VineScale, content.RectTransform);
GUINumberInput flowerInput = CreateIntEntry("Flower Quantity", FlowerQuantity, content.RectTransform);
GUINumberInput flowerScaleInput = CreateFloatEntry("Flower Scale", BaseFlowerScale, content.RectTransform);
GUINumberInput leafScaleInput = CreateFloatEntry("Leaf Scale", BaseLeafScale, content.RectTransform);
GUINumberInput leafProbabilityInput = CreateFloatEntry("Leaf Probability", LeafProbability, content.RectTransform);
GUINumberInput[] leafTintInputs = CreateMinMaxEntry("Leaf Tint", new []{ LeafTint.R / 255f, LeafTint.G / 255f, LeafTint.B / 255f }, 1.0f, content.RectTransform);
GUINumberInput[] flowerTintInputs = CreateMinMaxEntry("Flower Tint", new []{ FlowerTint.R / 255f, FlowerTint.G / 255f, FlowerTint.B / 255f }, 1.0f, content.RectTransform);
GUINumberInput[] vineTintInputs = CreateMinMaxEntry("Branch Tint", new []{ VineTint.R / 255f, VineTint.G / 255f, VineTint.B / 255f }, 1.0f, content.RectTransform);
// Apply
msgBox.Buttons[0].OnClicked = (button, o) =>
{
seed = seedInput.IntValue;
MaximumVines = vineCountInput.IntValue;
FlowerQuantity = flowerInput.IntValue;
BaseFlowerScale = flowerScaleInput.FloatValue;
VineScale = vineScaleInput.FloatValue;
BaseLeafScale = leafScaleInput.FloatValue;
LeafProbability = leafProbabilityInput.FloatValue;
VineTile.Size = vineTileSizeInput.IntValue;
MinFlowerScale = flowerScaleRangeInput[0].FloatValue;
MaxFlowerScale = flowerScaleRangeInput[1].FloatValue;
MinLeafScale = leafScaleRangeInput[0].FloatValue;
MaxLeafScale = leafScaleRangeInput[1].FloatValue;
LeafTint = new Color(leafTintInputs[0].FloatValue, leafTintInputs[1].FloatValue, leafTintInputs[2].FloatValue);
FlowerTint = new Color(flowerTintInputs[0].FloatValue, flowerTintInputs[1].FloatValue, flowerTintInputs[2].FloatValue);
VineTint = new Color(vineTintInputs[0].FloatValue, vineTintInputs[1].FloatValue, vineTintInputs[2].FloatValue);
if (FlowerQuantity >= MaximumVines - 1)
{
vineCountInput.Flash(Color.Red);
flowerInput.Flash(Color.Red);
return false;
}
if (MinFlowerScale > MaxFlowerScale)
{
foreach (GUINumberInput input in flowerScaleRangeInput)
{
input.Flash(Color.Red);
}
return false;
}
if (MinLeafScale > MaxLeafScale)
{
foreach (GUINumberInput input in leafScaleRangeInput)
{
input.Flash(Color.Red);
}
return false;
}
msgBox.Close();
Random random = new Random(seed);
Random flowerRandom = new Random(seed);
Vines.Clear();
GenerateFlowerTiles(flowerRandom);
GenerateStem();
Decayed = false;
FullyGrown = false;
while (MaximumVines > Vines.Count)
{
if (!CanGrowMore())
{
Decayed = true;
break;
}
TryGenerateBranches(planter, slot, random, flowerRandom);
}
if (!Decayed)
{
FullyGrown = true;
}
foreach (VineTile vineTile in Vines)
{
vineTile.GrowthStep = 2.0f;
}
return true;
};
}
private static GUINumberInput CreateIntEntry(string label, int defaultValue, RectTransform parent)
{
GUILayoutGroup layout = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.08f), parent), isHorizontal: true);
new GUITextBlock(new RectTransform(new Vector2(0.5f, 1f), layout.RectTransform), label);
GUINumberInput input = new GUINumberInput(new RectTransform(new Vector2(0.5f, 1f), layout.RectTransform), GUINumberInput.NumberType.Int) { IntValue = defaultValue };
return input;
}
private static GUINumberInput CreateFloatEntry(string label, float defaultValue, RectTransform parent)
{
GUILayoutGroup layout = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.08f), parent), isHorizontal: true);
new GUITextBlock(new RectTransform(new Vector2(0.5f, 1f), layout.RectTransform), label);
GUINumberInput input = new GUINumberInput(new RectTransform(new Vector2(0.5f, 1f), layout.RectTransform), GUINumberInput.NumberType.Float) { FloatValue = defaultValue, DecimalsToDisplay = 2 };
return input;
}
private static GUINumberInput[] CreateMinMaxEntry(string label, float[] values, float max, RectTransform parent, float min = 0f)
{
GUILayoutGroup layout = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.08f), parent), isHorizontal: true);
new GUITextBlock(new RectTransform(new Vector2(0.5f, 1f), layout.RectTransform), label);
GUINumberInput[] inputs = new GUINumberInput[values.Length];
for (var i = 0; i < values.Length; i++)
{
float value = values[i];
GUINumberInput input = new GUINumberInput(new RectTransform(new Vector2(0.5f / values.Length, 1f), layout.RectTransform), GUINumberInput.NumberType.Float)
{
FloatValue = value, DecimalsToDisplay = 2,
MinValueFloat = min,
MaxValueFloat = max
};
inputs[i] = input;
}
return inputs;
}
#endif
}
}
@@ -12,11 +12,11 @@ namespace Barotrauma.Items.Components
{
partial class RangedWeapon : ItemComponent
{
private Sprite crosshairSprite, crosshairPointerSprite;
protected Sprite crosshairSprite, crosshairPointerSprite;
private Vector2 crosshairPos, crosshairPointerPos;
protected Vector2 crosshairPos, crosshairPointerPos;
private float currentCrossHairScale, currentCrossHairPointerScale;
protected float currentCrossHairScale, currentCrossHairPointerScale;
private readonly List<ParticleEmitter> particleEmitters = new List<ParticleEmitter>();
@@ -86,7 +86,6 @@ namespace Barotrauma.Items.Components
public override void DrawHUD(SpriteBatch spriteBatch, Character character)
{
if (crosshairSprite == null) { return; }
if (character == null || !character.IsKeyDown(InputType.Aim)) { return; }
//camera focused on some other item/device, don't draw the crosshair
@@ -0,0 +1,338 @@
using Barotrauma.Networking;
using Barotrauma.Particles;
using FarseerPhysics;
using FarseerPhysics.Dynamics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
namespace Barotrauma.Items.Components
{
partial class Sprayer : RangedWeapon, IDrawableComponent
{
#if DEBUG
private Vector2 debugRayStartPos, debugRayEndPos;
#endif
public Vector2 DrawSize
{
get { return Vector2.Zero; }
}
private readonly List<ParticleEmitter> particleEmitters = new List<ParticleEmitter>();
private Hull targetHull;
private Vector2 rayStartWorldPosition;
private Color color;
partial void InitProjSpecific(XElement element)
{
currentCrossHairPointerScale = element.GetAttributeFloat("crosshairscale", 0.1f);
foreach (XElement subElement in element.Elements())
{
switch (subElement.Name.ToString().ToLowerInvariant())
{
case "particleemitter":
particleEmitters.Add(new ParticleEmitter(subElement));
break;
}
}
}
private readonly List<BackgroundSection> targetSections = new List<BackgroundSection>();
// 0 = 1x1, 1 = 2x2, 2 = 3x3
private int spraySetting = 0;
private readonly Point[] sprayArray = new Point[8];
public override void UpdateHUD(Character character, float deltaTime, Camera cam)
{
if (character == null || !character.IsKeyDown(InputType.Aim)) return;
#if DEBUG
if (PlayerInput.KeyHit(InputType.PreviousFireMode))
#else
if (PlayerInput.MouseWheelDownClicked())
#endif
{
if (spraySetting > 0)
{
spraySetting--;
}
else
{
spraySetting = 2;
}
targetSections.Clear();
}
#if DEBUG
if (PlayerInput.KeyHit(InputType.NextFireMode))
#else
if (PlayerInput.MouseWheelUpClicked())
#endif
{
if (spraySetting < 2)
{
spraySetting++;
}
else
{
spraySetting = 0;
}
targetSections.Clear();
}
crosshairPointerPos = PlayerInput.MousePosition;
Vector2 rayStart;
Vector2 sourcePos = character?.AnimController == null ? item.SimPosition : character.AnimController.AimSourceSimPos;
Vector2 barrelPos = item.SimPosition + TransformedBarrelPos;
//make sure there's no obstacles between the base of the item (or the shoulder of the character) and the end of the barrel
if (Submarine.PickBody(sourcePos, barrelPos, collisionCategory: Physics.CollisionItem | Physics.CollisionItemBlocking | Physics.CollisionWall) == null)
{
//no obstacles -> we start the raycast at the end of the barrel
rayStart = ConvertUnits.ToSimUnits(item.WorldPosition) + TransformedBarrelPos;
}
else
{
targetHull = null;
targetSections.Clear();
return;
}
Vector2 pos = character.CursorWorldPosition;
Vector2 rayEnd = ConvertUnits.ToSimUnits(pos);
rayStartWorldPosition = ConvertUnits.ToDisplayUnits(rayStart);
if (Vector2.Distance(rayStartWorldPosition, pos) > Range)
{
targetHull = null;
targetSections.Clear();
return;
}
#if DEBUG
debugRayStartPos = ConvertUnits.ToDisplayUnits(rayStart);
debugRayEndPos = ConvertUnits.ToDisplayUnits(rayEnd);
#endif
Submarine parentSub = character.Submarine ?? item.Submarine;
if (parentSub != null)
{
rayStart -= parentSub.SimPosition;
rayEnd -= parentSub.SimPosition;
}
var obstacles = Submarine.PickBodies(rayStart, rayEnd, collisionCategory: Physics.CollisionItem | Physics.CollisionItemBlocking | Physics.CollisionWall);
foreach (var body in obstacles)
{
if (body.UserData is Item item)
{
var door = item.GetComponent<Door>();
if (door != null && door.IsOpen || door.IsBroken) continue;
}
targetHull = null;
targetSections.Clear();
return;
}
targetHull = Hull.GetCleanTarget(pos);
if (targetHull == null)
{
targetSections.Clear();
return;
}
BackgroundSection mousedOverSection = targetHull.GetBackgroundSection(pos);
if (mousedOverSection == null)
{
targetSections.Clear();
return;
}
// No need to refresh
if (targetSections.Count > 0 && mousedOverSection == targetSections[0])
{
return;
}
targetSections.Clear();
targetSections.Add(mousedOverSection);
int mousedOverIndex = mousedOverSection.Index;
// Start with 2x2
if (spraySetting > 0)
{
sprayArray[0].X = mousedOverIndex + 1;
sprayArray[0].Y = mousedOverSection.RowIndex;
sprayArray[1].X = mousedOverIndex + targetHull.xBackgroundMax;
sprayArray[1].Y = mousedOverSection.RowIndex + 1;
sprayArray[2].X = sprayArray[1].X + 1;
sprayArray[2].Y = sprayArray[1].Y;
for (int i = 0; i < 3; i++)
{
if (targetHull.DoesSectionMatch(sprayArray[i].X, sprayArray[i].Y))
{
targetSections.Add(targetHull.BackgroundSections[sprayArray[i].X]);
}
}
// Add more if it's 3x3
if (spraySetting == 2)
{
sprayArray[3].X = mousedOverIndex - 1;
sprayArray[3].Y = mousedOverSection.RowIndex;
sprayArray[4].X = sprayArray[1].X - 1;
sprayArray[4].Y = sprayArray[1].Y;
sprayArray[5].X = sprayArray[3].X - targetHull.xBackgroundMax;
sprayArray[5].Y = sprayArray[3].Y - 1;
sprayArray[6].X = sprayArray[5].X + 1;
sprayArray[6].Y = sprayArray[5].Y;
sprayArray[7].X = sprayArray[6].X + 1;
sprayArray[7].Y = sprayArray[6].Y;
for (int i = 3; i < sprayArray.Length; i++)
{
if (targetHull.DoesSectionMatch(sprayArray[i].X, sprayArray[i].Y))
{
targetSections.Add(targetHull.BackgroundSections[sprayArray[i].X]);
}
}
}
}
}
public override void DrawHUD(SpriteBatch spriteBatch, Character character)
{
if (character == null || !character.IsKeyDown(InputType.Aim)) { return; }
GUI.HideCursor = targetSections.Count > 0;
}
public override bool Use(float deltaTime, Character character = null)
{
if (character == null) { return false; }
if (character == Character.Controlled)
{
if (targetSections.Count == 0) { return false; }
Spray(deltaTime);
return true;
}
else
{
//allow remote players to use the sprayer, but don't actually color the walls (we'll receive the data from the server)
return character.IsRemotePlayer;
}
}
public void Spray(float deltaTime)
{
if (targetSections.Count == 0) { return; }
Item liquidItem = liquidContainer?.Inventory.Items[0];
if (liquidItem == null) { return; }
bool isCleaning = false;
liquidColors.TryGetValue(liquidItem.prefab.Identifier, out color);
// Ethanol or other cleaning solvent
if (color.A == 0) { isCleaning = true; }
float sizeAdjustedSprayStrength = SprayStrength / targetSections.Count;
if (!isCleaning)
{
for (int i = 0; i < targetSections.Count; i++)
{
targetHull.SetSectionColorOrStrength(targetSections[i], color, sizeAdjustedSprayStrength * deltaTime, true, false);
}
}
else
{
for (int i = 0; i < targetSections.Count; i++)
{
targetHull.CleanSection(targetSections[i], -sizeAdjustedSprayStrength * deltaTime, true);
}
}
Vector2 particleStartPos = item.WorldPosition + ConvertUnits.ToDisplayUnits(TransformedBarrelPos);
Vector2 particleEndPos = Vector2.Zero;
for (int i = 0; i < targetSections.Count; i++)
{
particleEndPos += new Vector2(targetSections[i].Rect.Center.X, targetSections[i].Rect.Y - targetSections[i].Rect.Height / 2) + targetHull.Rect.Location.ToVector2();
}
particleEndPos /= targetSections.Count;
if (targetHull?.Submarine != null)
{
particleEndPos += targetHull.Submarine.Position;
}
float dist = Vector2.Distance(particleStartPos, particleEndPos);
foreach (ParticleEmitter particleEmitter in particleEmitters)
{
float particleAngle = item.body.Rotation + ((item.body.Dir > 0.0f) ? 0.0f : MathHelper.Pi);
float particleRange = particleEmitter.Prefab.VelocityMax * particleEmitter.Prefab.ParticlePrefab.LifeTime;
particleEmitter.Emit(
deltaTime, particleStartPos,
item.CurrentHull, particleAngle, particleEmitter.Prefab.CopyEntityAngle ? -particleAngle : 0, velocityMultiplier: dist / particleRange * 1.5f,
colorMultiplier: new Color(color.R, color.G, color.B, (byte)255));
}
}
public void Draw(SpriteBatch spriteBatch, bool editing, float itemDepth = -1)
{
#if DEBUG
if (GameMain.DebugDraw && Character.Controlled != null && Character.Controlled.IsKeyDown(InputType.Aim))
{
GUI.DrawLine(spriteBatch,
new Vector2(debugRayStartPos.X, -debugRayStartPos.Y),
new Vector2(debugRayEndPos.X, -debugRayEndPos.Y),
Color.Yellow);
}
#endif
if (Character.Controlled == null || !Character.Controlled.HasEquippedItem(item) || !Character.Controlled.IsKeyDown(InputType.Aim) || targetHull == null || targetSections.Count == 0) return;
Vector2 drawOffset = targetHull.Submarine == null ? Vector2.Zero : targetHull.Submarine.DrawPosition;
Point sectionSize = targetSections[0].Rect.Size;
Rectangle drawPositionRect = new Rectangle((int)(drawOffset.X + targetHull.Rect.X), (int)(drawOffset.Y + targetHull.Rect.Y), sectionSize.X, sectionSize.Y);
if (crosshairSprite == null && crosshairPointerSprite == null)
{
for (int i = 0; i < targetSections.Count; i++)
{
GUI.DrawRectangle(spriteBatch, new Vector2(drawPositionRect.X + targetSections[i].Rect.X, -(drawPositionRect.Y + targetSections[i].Rect.Y)), new Vector2(sectionSize.X, sectionSize.Y), Color.White, false, 0.0f, 1);
}
}
else if (targetSections.Count > 0)
{
Vector2 drawPos = Vector2.Zero;
for (int i = 0; i < targetSections.Count; i++)
{
drawPos += new Vector2(drawPositionRect.X + targetSections[i].Rect.X + sectionSize.X / 2, -(drawPositionRect.Y + targetSections[i].Rect.Y - sectionSize.Y / 2));
}
drawPos /= targetSections.Count;
crosshairSprite?.Draw(spriteBatch, drawPos, scale: sectionSize.X * 3 / crosshairSprite.size.X);
crosshairPointerSprite?.Draw(spriteBatch, drawPos, scale: sectionSize.X * (spraySetting + 1) / crosshairPointerSprite.size.X);
}
}
}
}
@@ -256,6 +256,7 @@ namespace Barotrauma.Items.Components
loopingSoundChannel = loopingSound.RoundSound.Sound.Play(
new Vector3(item.WorldPosition, 0.0f),
0.01f,
loopingSound.RoundSound.GetRandomFrequencyMultiplier(),
SoundPlayer.ShouldMuffleSound(Character.Controlled, item.WorldPosition, loopingSound.Range, Character.Controlled?.CurrentHull));
loopingSoundChannel.Looping = true;
//TODO: tweak
@@ -326,7 +327,7 @@ namespace Barotrauma.Items.Components
{
float volume = GetSoundVolume(itemSound);
if (volume <= 0.0001f) { return; }
var channel = SoundPlayer.PlaySound(itemSound.RoundSound.Sound, position, volume, itemSound.Range, item.CurrentHull);
var channel = SoundPlayer.PlaySound(itemSound.RoundSound.Sound, position, volume, itemSound.Range, itemSound.RoundSound.GetRandomFrequencyMultiplier(), item.CurrentHull);
if (channel != null) { playingOneshotSoundChannels.Add(channel); }
}
}
@@ -172,6 +172,8 @@ namespace Barotrauma.Items.Components
{
Vector2 transformedItemPos = ItemPos * item.Scale;
Vector2 transformedItemInterval = ItemInterval * item.Scale;
Vector2 transformedItemIntervalHorizontal = new Vector2(transformedItemInterval.X, 0.0f);
Vector2 transformedItemIntervalVertical = new Vector2(0.0f, transformedItemInterval.Y);
if (item.body == null)
{
@@ -180,15 +182,26 @@ namespace Barotrauma.Items.Components
transformedItemPos.X = -transformedItemPos.X;
transformedItemPos.X += item.Rect.Width;
transformedItemInterval.X = -transformedItemInterval.X;
transformedItemIntervalHorizontal.X = -transformedItemIntervalHorizontal.X;
}
if (item.FlippedY)
{
transformedItemPos.Y = -transformedItemPos.Y;
transformedItemPos.Y -= item.Rect.Height;
transformedItemInterval.Y = -transformedItemInterval.Y;
transformedItemIntervalVertical.Y = -transformedItemIntervalVertical.Y;
}
transformedItemPos += new Vector2(item.Rect.X, item.Rect.Y);
if (item.Submarine != null) { transformedItemPos += item.Submarine.DrawPosition; }
if (Math.Abs(item.Rotation) > 0.01f)
{
Matrix transform = Matrix.CreateRotationZ(MathHelper.ToRadians(-item.Rotation));
transformedItemPos = Vector2.Transform(transformedItemPos - item.DrawPosition, transform) + item.DrawPosition;
transformedItemInterval = Vector2.Transform(transformedItemInterval, transform);
transformedItemIntervalHorizontal = Vector2.Transform(transformedItemIntervalHorizontal, transform);
transformedItemIntervalVertical = Vector2.Transform(transformedItemIntervalVertical, transform);
}
}
else
{
@@ -197,9 +210,12 @@ namespace Barotrauma.Items.Components
{
transformedItemPos.X = -transformedItemPos.X;
transformedItemInterval.X = -transformedItemInterval.X;
transformedItemIntervalHorizontal.X = -transformedItemIntervalHorizontal.X;
}
transformedItemPos = Vector2.Transform(transformedItemPos, transform);
transformedItemInterval = Vector2.Transform(transformedItemInterval, transform);
transformedItemIntervalHorizontal = Vector2.Transform(transformedItemIntervalHorizontal, transform);
transformedItemPos += item.DrawPosition;
}
@@ -207,8 +223,14 @@ namespace Barotrauma.Items.Components
Vector2 currentItemPos = transformedItemPos;
SpriteEffects spriteEffects = SpriteEffects.None;
if ((item.body != null && item.body.Dir == -1) || item.FlippedX) { spriteEffects |= SpriteEffects.FlipHorizontally; }
if (item.FlippedY) { spriteEffects |= SpriteEffects.FlipVertically; }
if ((item.body != null && item.body.Dir == -1) || item.FlippedX)
{
spriteEffects |= MathUtils.NearlyEqual(ItemRotation % 180, 90.0f) ? SpriteEffects.FlipVertically : SpriteEffects.FlipHorizontally;
}
if (item.FlippedY)
{
spriteEffects |= MathUtils.NearlyEqual(ItemRotation % 180, 90.0f) ? SpriteEffects.FlipHorizontally : SpriteEffects.FlipVertically;
}
int i = 0;
foreach (Item containedItem in Inventory.Items)
@@ -233,7 +255,7 @@ namespace Barotrauma.Items.Components
new Vector2(currentItemPos.X, -currentItemPos.Y),
containedItem.GetSpriteColor(),
origin,
-(containedItem.body == null ? 0.0f : containedItem.body.DrawRotation),
-(containedItem.body == null ? 0.0f : containedItem.body.DrawRotation + MathHelper.ToRadians(-item.Rotation)),
containedItem.Scale,
spriteEffects,
depth: containedSpriteDepth);
@@ -248,11 +270,11 @@ namespace Barotrauma.Items.Components
if (Math.Abs(ItemInterval.X) > 0.001f && Math.Abs(ItemInterval.Y) > 0.001f)
{
//interval set on both axes -> use a grid layout
currentItemPos.X += transformedItemInterval.X;
currentItemPos += transformedItemIntervalHorizontal;
if (i % ItemsPerRow == 0)
{
currentItemPos.X = transformedItemPos.X;
currentItemPos.Y += transformedItemInterval.Y;
currentItemPos = transformedItemPos;
currentItemPos += transformedItemIntervalVertical * (i / ItemsPerRow);
}
}
else
@@ -264,6 +286,7 @@ namespace Barotrauma.Items.Components
public override void UpdateHUD(Character character, float deltaTime, Camera cam)
{
if (item.NonInteractable) { return; }
if (Inventory.RectTransform != null)
{
guiCustomComponent.RectTransform.Parent = Inventory.RectTransform;
@@ -272,7 +295,7 @@ namespace Barotrauma.Items.Components
//if the item is in the character's inventory, no need to update the item's inventory
//because the player can see it by hovering the cursor over the item
guiCustomComponent.Visible = item.ParentInventory?.Owner != character && DrawInventory;
if (!guiCustomComponent.Visible) return;
if (!guiCustomComponent.Visible) { return; }
Inventory.Update(deltaTime, cam);
}
@@ -1,4 +1,5 @@
using Microsoft.Xna.Framework;
using Barotrauma.Networking;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.Text;
@@ -225,5 +226,10 @@ namespace Barotrauma.Items.Components
textBlock.TextOffset = drawPos - textBlock.Rect.Location.ToVector2() + new Vector2(scrollAmount + scrollPadding, 0.0f);
textBlock.DrawManually(spriteBatch);
}
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
{
Text = msg.ReadString();
}
}
}
@@ -49,8 +49,8 @@ namespace Barotrauma.Items.Components
if (light.LightSprite != null && (item.body == null || item.body.Enabled) && lightBrightness > 0.0f && IsOn)
{
Vector2 origin = light.LightSprite.Origin;
if (light.LightSpriteEffect == SpriteEffects.FlipHorizontally) { origin.X = light.LightSprite.SourceRect.Width - origin.X; }
if (light.LightSpriteEffect == SpriteEffects.FlipVertically) { origin.Y = light.LightSprite.SourceRect.Height - origin.Y; }
if ((light.LightSpriteEffect & SpriteEffects.FlipHorizontally) == SpriteEffects.FlipHorizontally) { origin.X = light.LightSprite.SourceRect.Width - origin.X; }
if ((light.LightSpriteEffect & SpriteEffects.FlipVertically) == SpriteEffects.FlipVertically) { origin.Y = light.LightSprite.SourceRect.Height - origin.Y; }
light.LightSprite.Draw(spriteBatch, new Vector2(item.DrawPosition.X, -item.DrawPosition.Y), lightColor * lightBrightness, origin, -light.Rotation, item.Scale, light.LightSpriteEffect, item.SpriteDepth - 0.0001f);
}
}
@@ -52,7 +52,9 @@ namespace Barotrauma.Items.Components
RelativeOffset = new Vector2(0.05f, 0)
}, TextManager.Get("PumpAutoControl", fallBackTag: "ReactorAutoControl"), font: GUI.SubHeadingFont, style: "IndicatorLightYellow")
{
CanBeFocused = false
Selected = false,
Enabled = false,
ToolTip = TextManager.Get("AutoControlTip")
};
powerIndicator.TextBlock.Wrap = autoControlIndicator.TextBlock.Wrap = true;
powerIndicator.TextBlock.OverrideTextColor(GUI.Style.TextColor);
@@ -75,6 +77,7 @@ namespace Barotrauma.Items.Components
if (Math.Abs(newTargetForce - targetForce) < 0.01) { return false; }
targetForce = newTargetForce;
User = Character.Controlled;
if (GameMain.Client != null)
{
@@ -145,7 +148,7 @@ namespace Barotrauma.Items.Components
propellerSprite.Draw(spriteBatch, (int)Math.Floor(spriteIndex), drawPos, Color.White, propellerSprite.Origin, 0.0f, Vector2.One);
}
if (editing)
if (editing && !GUI.DisableHUD)
{
Vector2 drawPos = item.DrawPosition;
drawPos += PropellerPos;
@@ -164,11 +167,16 @@ namespace Barotrauma.Items.Components
{
if (correctionTimer > 0.0f)
{
StartDelayedCorrection(type, msg.ExtractBits(5), sendingTime);
StartDelayedCorrection(type, msg.ExtractBits(5 + 16), sendingTime);
return;
}
targetForce = msg.ReadRangedInteger(-10, 10) * 10.0f;
UInt16 userID = msg.ReadUInt16();
if (userID != Entity.NullEntityID)
{
User = Entity.FindEntityByID(userID) as Character;
}
}
}
}
@@ -100,7 +100,7 @@ namespace Barotrauma.Items.Components
OnSelected = (component, userdata) =>
{
selectedItem = userdata as FabricationRecipe;
if (selectedItem != null) SelectItem(Character.Controlled, selectedItem);
if (selectedItem != null) { SelectItem(Character.Controlled, selectedItem); }
return true;
}
};
@@ -292,7 +292,7 @@ namespace Barotrauma.Items.Components
foreach (Item item in inputContainer.Inventory.Items)
{
if (item == null) { continue; }
missingItems.Remove(missingItems.FirstOrDefault(mi => mi.ItemPrefab == item.prefab));
missingItems.Remove(missingItems.FirstOrDefault(mi => mi.ItemPrefabs.Contains(item.prefab)));
}
var availableIngredients = GetAvailableIngredients();
@@ -328,12 +328,12 @@ namespace Barotrauma.Items.Components
if (slotIndex >= inputContainer.Capacity) { break; }
var itemIcon = requiredItem.ItemPrefab.InventoryIcon ?? requiredItem.ItemPrefab.sprite;
var itemIcon = requiredItem.ItemPrefabs.First().InventoryIcon ?? requiredItem.ItemPrefabs.First().sprite;
Rectangle slotRect = inputContainer.Inventory.slots[slotIndex].Rect;
itemIcon.Draw(
spriteBatch,
slotRect.Center.ToVector2(),
color: requiredItem.ItemPrefab.InventoryIconColor * 0.3f,
color: requiredItem.ItemPrefabs.First().InventoryIconColor * 0.3f,
scale: Math.Min(slotRect.Width / itemIcon.size.X, slotRect.Height / itemIcon.size.Y));
if (requiredItem.UseCondition && requiredItem.MinCondition < 1.0f)
@@ -346,14 +346,16 @@ namespace Barotrauma.Items.Components
if (slotRect.Contains(PlayerInput.MousePosition))
{
string toolTipText = requiredItem.ItemPrefab.Name;
var suitableIngredients = requiredItem.ItemPrefabs.Select(ip => ip.Name);
string toolTipText = string.Join(", ", suitableIngredients.Count() > 3 ? suitableIngredients.SkipLast(suitableIngredients.Count() - 3) : suitableIngredients);
if (suitableIngredients.Count() > 3) { toolTipText += "..."; }
if (requiredItem.UseCondition && requiredItem.MinCondition < 1.0f)
{
toolTipText += " " + (int)Math.Round(requiredItem.MinCondition * 100) + "%";
}
if (!string.IsNullOrEmpty(requiredItem.ItemPrefab.Description))
if (!string.IsNullOrEmpty(requiredItem.ItemPrefabs.First().Description))
{
toolTipText += '\n' + requiredItem.ItemPrefab.Description;
toolTipText += '\n' + requiredItem.ItemPrefabs.First().Description;
}
tooltip = new Pair<Rectangle, string>(slotRect, toolTipText);
}
@@ -378,10 +380,11 @@ namespace Barotrauma.Items.Components
if (fabricatedItem != null)
{
float clampedProgressState = Math.Clamp(progressState, 0f, 1f);
GUI.DrawRectangle(spriteBatch,
new Rectangle(
slotRect.X, slotRect.Y + (int)(slotRect.Height * (1.0f - progressState)),
slotRect.Width, (int)(slotRect.Height * progressState)),
slotRect.X, slotRect.Y + (int)(slotRect.Height * (1.0f - clampedProgressState)),
slotRect.Width, (int)(slotRect.Height * clampedProgressState)),
GUI.Style.Green * 0.5f, isFilled: true);
}
@@ -429,8 +432,10 @@ namespace Barotrauma.Items.Components
return true;
}
private bool SelectItem(Character user, FabricationRecipe selectedItem)
private bool SelectItem(Character user, FabricationRecipe selectedItem, float? overrideRequiredTime = null)
{
this.selectedItem = selectedItem;
selectedItemFrame.ClearChildren();
selectedItemReqsFrame.ClearChildren();
@@ -496,7 +501,8 @@ namespace Barotrauma.Items.Components
float degreeOfSuccess = user == null ? 0.0f : FabricationDegreeOfSuccess(user, selectedItem.RequiredSkills);
if (degreeOfSuccess > 0.5f) { degreeOfSuccess = 1.0f; }
float requiredTime = user == null ? selectedItem.RequiredTime : GetRequiredTime(selectedItem, user);
float requiredTime = overrideRequiredTime ??
(user == null ? selectedItem.RequiredTime : GetRequiredTime(selectedItem, user));
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedReqFrame.RectTransform),
TextManager.Get("FabricatorRequiredTime") , textColor: ToolBox.GradientLerp(degreeOfSuccess, GUI.Style.Red, Color.Yellow, GUI.Style.Green), font: GUI.SubHeadingFont)
@@ -605,7 +611,7 @@ namespace Barotrauma.Items.Components
State = newState;
timeUntilReady = newTimeUntilReady;
if (newState == FabricatorState.Stopped || itemIndex == -1 || user == null)
if (newState == FabricatorState.Stopped || itemIndex == -1)
{
CancelFabricating();
}
@@ -81,7 +81,9 @@ namespace Barotrauma.Items.Components
autoControlIndicator = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.25f), rightArea.RectTransform, Anchor.TopLeft),
TextManager.Get("PumpAutoControl", fallBackTag: "ReactorAutoControl"), font: GUI.SubHeadingFont, style: "IndicatorLightYellow")
{
CanBeFocused = false
Selected = false,
Enabled = false,
ToolTip = TextManager.Get("AutoControlTip")
};
autoControlIndicator.TextBlock.AutoScaleHorizontal = true;
autoControlIndicator.TextBlock.OverrideTextColor(GUI.Style.TextColor);
@@ -131,17 +131,23 @@ namespace Barotrauma.Items.Components
criticalHeatWarning = new GUITickBox(new RectTransform(new Vector2(0.33f, 1.0f), topLeftArea.RectTransform) { MaxSize = maxIndicatorSize },
TextManager.Get("ReactorWarningCriticalTemp"), font: GUI.SubHeadingFont, style: "IndicatorLightRed")
{
CanBeFocused = false
Selected = false,
Enabled = false,
ToolTip = TextManager.Get("ReactorHeatTip")
};
lowTemperatureWarning = new GUITickBox(new RectTransform(new Vector2(0.33f, 1.0f), topLeftArea.RectTransform) { MaxSize = maxIndicatorSize },
TextManager.Get("ReactorWarningCriticalLowTemp"), font: GUI.SubHeadingFont, style: "IndicatorLightRed")
{
CanBeFocused = false
Selected = false,
Enabled = false,
ToolTip = TextManager.Get("ReactorTempTip")
};
criticalOutputWarning = new GUITickBox(new RectTransform(new Vector2(0.33f, 1.0f), topLeftArea.RectTransform) { MaxSize = maxIndicatorSize },
TextManager.Get("ReactorWarningCriticalOutput"), font: GUI.SubHeadingFont, style: "IndicatorLightRed")
{
CanBeFocused = false
Selected = false,
Enabled = false,
ToolTip = TextManager.Get("ReactorOutputTip")
};
List<GUITickBox> indicatorLights = new List<GUITickBox>() { criticalHeatWarning, lowTemperatureWarning, criticalOutputWarning };
indicatorLights.ForEach(l => l.TextBlock.OverrideTextColor(GUI.Style.TextColor));
@@ -6,7 +6,6 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using Barotrauma.Extensions;
namespace Barotrauma.Items.Components
{
@@ -20,7 +19,7 @@ namespace Barotrauma.Items.Components
private PathFinder pathFinder;
private bool dynamicDockingIndicator = true;
private readonly bool dynamicDockingIndicator = true;
private bool unsentChanges;
private float networkUpdateTimer;
@@ -378,7 +377,6 @@ namespace Barotrauma.Items.Components
float edgeDist = Rand.Range(0.0f, 1.0f);
Vector2 blipPos = trigger.WorldPosition + Rand.Vector(trigger.ColliderRadius * edgeDist);
Vector2 blipVel = flow;
if (trigger.ForceFalloff) flow *= (1.0f - edgeDist);
//go through other triggers in range and add the flows of the ones that the blip is inside
foreach (KeyValuePair<LevelTrigger, Vector2> triggerFlow2 in levelTriggerFlows)
@@ -387,7 +385,7 @@ namespace Barotrauma.Items.Components
if (trigger2 != trigger && Vector2.DistanceSquared(blipPos, trigger2.WorldPosition) < trigger2.ColliderRadius * trigger2.ColliderRadius)
{
Vector2 trigger2flow = triggerFlow2.Value;
if (trigger2.ForceFalloff) trigger2flow *= (1.0f - Vector2.Distance(blipPos, trigger2.WorldPosition) / trigger2.ColliderRadius);
if (trigger2.ForceFalloff) trigger2flow *= 1.0f - Vector2.Distance(blipPos, trigger2.WorldPosition) / trigger2.ColliderRadius;
blipVel += trigger2flow;
}
}
@@ -507,7 +505,7 @@ namespace Barotrauma.Items.Components
float passivePingRadius = (float)(Timing.TotalTime % 1.0f);
if (passivePingRadius > 0.0f)
{
disruptedDirections.Clear();
if (activePingsCount == 0) { disruptedDirections.Clear(); }
foreach (AITarget t in AITarget.List)
{
if (t.Entity is Character c && c.Params.HideInSonar) { continue; }
@@ -581,14 +579,14 @@ namespace Barotrauma.Items.Components
}
}
if (currentMode == Mode.Active && currentPingIndex != -1)
if (currentPingIndex != -1)
{
var activePing = activePings[currentPingIndex];
if (activePing.IsDirectional && directionalPingCircle != null)
{
directionalPingCircle.Draw(spriteBatch, center, Color.White * (1.0f - activePing.State),
rotate: MathUtils.VectorToAngle(activePing.Direction),
scale: (DisplayRadius / directionalPingCircle.size.X) * activePing.State);
rotate: MathUtils.VectorToAngle(activePing.Direction),
scale: DisplayRadius / directionalPingCircle.size.X * activePing.State);
}
else
{
@@ -611,13 +609,13 @@ namespace Barotrauma.Items.Components
if (sonarBlips.Count > 0)
{
zoomSqrt = (float)Math.Sqrt(zoom);
float blipScale = 0.08f * (float)Math.Sqrt(zoom) * (rect.Width / 700.0f);
spriteBatch.End();
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.Additive);
foreach (SonarBlip sonarBlip in sonarBlips)
{
DrawBlip(spriteBatch, sonarBlip, transducerCenter, center, sonarBlip.FadeTimer / 2.0f * signalStrength);
DrawBlip(spriteBatch, sonarBlip, transducerCenter, center, sonarBlip.FadeTimer / 2.0f * signalStrength, blipScale);
}
spriteBatch.End();
@@ -1297,7 +1295,7 @@ namespace Barotrauma.Items.Components
return true;
}
private void DrawBlip(SpriteBatch spriteBatch, SonarBlip blip, Vector2 transducerPos, Vector2 center, float strength)
private void DrawBlip(SpriteBatch spriteBatch, SonarBlip blip, Vector2 transducerPos, Vector2 center, float strength, float blipScale)
{
strength = MathHelper.Clamp(strength, 0.0f, 1.0f);
@@ -1306,8 +1304,8 @@ namespace Barotrauma.Items.Components
Vector2 pos = (blip.Position - transducerPos) * displayScale * zoom;
pos.Y = -pos.Y;
if (Rand.Range(0.5f, 2.0f) < distort) pos.X = -pos.X;
if (Rand.Range(0.5f, 2.0f) < distort) pos.Y = -pos.Y;
if (Rand.Range(0.5f, 2.0f) < distort) { pos.X = -pos.X; }
if (Rand.Range(0.5f, 2.0f) < distort) { pos.Y = -pos.Y; }
float posDistSqr = pos.LengthSquared();
if (posDistSqr > DisplayRadius * DisplayRadius)
@@ -1324,15 +1322,15 @@ namespace Barotrauma.Items.Components
Vector2 dir = pos / (float)Math.Sqrt(posDistSqr);
Vector2 normal = new Vector2(dir.Y, -dir.X);
float scale = (strength + 3.0f) * blip.Scale * zoomSqrt;
float scale = (strength + 3.0f) * blip.Scale * blipScale;
Color color = ToolBox.GradientLerp(strength, blipColorGradient[blip.BlipType]);
sonarBlip.Draw(spriteBatch, center + pos, color, sonarBlip.Origin, blip.Rotation ?? MathUtils.VectorToAngle(pos),
blip.Size * scale * 0.04f, SpriteEffects.None, 0);
blip.Size * scale * 0.5f, SpriteEffects.None, 0);
pos += Rand.Range(0.0f, 1.0f) * dir + Rand.Range(-scale, scale) * normal;
sonarBlip.Draw(spriteBatch, center + pos, color * 0.5f, sonarBlip.Origin, 0, scale * 0.08f, SpriteEffects.None, 0);
sonarBlip.Draw(spriteBatch, center + pos, color * 0.5f, sonarBlip.Origin, 0, scale, SpriteEffects.None, 0);
}
private void DrawMarker(SpriteBatch spriteBatch, string label, string iconIdentifier, object targetIdentifier, Vector2 worldPosition, Vector2 transducerPosition, float scale, Vector2 center, float radius)
@@ -22,6 +22,7 @@ namespace Barotrauma.Items.Components
LevelEnd,
LevelStart
};
private GUITickBox maintainPosTickBox, levelEndTickBox, levelStartTickBox;
private GUIComponent statusContainer, dockingContainer, controlContainer;
@@ -349,20 +350,34 @@ namespace Barotrauma.Items.Components
{
OnClicked = (btn, userdata) =>
{
if (GameMain.GameSession?.Campaign != null)
if (GameMain.GameSession?.Campaign is CampaignMode campaign)
{
if (Level.IsLoadedOutpost &&
DockingSources.Any(d => d.Docked && (d.DockingTarget?.Item.Submarine?.Info?.IsOutpost ?? false)))
{
GameMain.GameSession.Campaign.CampaignUI.SelectTab(CampaignMode.InteractionType.Map);
GameMain.GameSession.Campaign.ShowCampaignUI = true;
// Undocking from an outpost
campaign.CampaignUI.SelectTab(CampaignMode.InteractionType.Map);
campaign.ShowCampaignUI = true;
return false;
}
else if (!Level.IsLoadedOutpost && DockingModeEnabled && ActiveDockingSource != null &&
!ActiveDockingSource.Docked && (DockingTarget?.Item?.Submarine?.Info.IsOutpost ?? false))
!ActiveDockingSource.Docked && DockingTarget?.Item?.Submarine == Level.Loaded.StartOutpost && (DockingTarget?.Item?.Submarine?.Info.IsOutpost ?? false))
{
enterOutpostPrompt = new GUIMessageBox("", TextManager.GetWithVariable("campaignenteroutpostprompt", "[locationname]", DockingTarget.Item.Submarine.Info.Name), new string[] { TextManager.Get("yes"), TextManager.Get("no") });
// Docking to an outpost
var subsToLeaveBehind = campaign.GetSubsToLeaveBehind(Item.Submarine);
if (subsToLeaveBehind.Any())
{
enterOutpostPrompt = new GUIMessageBox(
TextManager.GetWithVariable("enterlocation", "[locationname]", DockingTarget.Item.Submarine.Info.Name),
TextManager.Get(subsToLeaveBehind.Count == 1 ? "LeaveSubBehind" : "LeaveSubsBehind"),
new string[] { TextManager.Get("yes"), TextManager.Get("no") });
}
else
{
enterOutpostPrompt = new GUIMessageBox("",
TextManager.GetWithVariable("campaignenteroutpostprompt", "[locationname]", DockingTarget.Item.Submarine.Info.Name),
new string[] { TextManager.Get("yes"), TextManager.Get("no") });
}
enterOutpostPrompt.Buttons[0].OnClicked += (btn, userdata) =>
{
SendDockingSignal();
@@ -780,10 +795,16 @@ namespace Barotrauma.Items.Components
}
checkConnectedPortsTimer = CheckConnectedPortsInterval;
}
else
{
checkConnectedPortsTimer -= deltaTime;
}
float closestDist = DockingAssistThreshold * DockingAssistThreshold;
DockingModeEnabled = false;
if (connectedPorts.None()) { return; }
float closestDist = DockingAssistThreshold * DockingAssistThreshold;
foreach (DockingPort sourcePort in connectedPorts)
{
if (sourcePort.Docked || sourcePort.Item.Submarine == null) { continue; }
@@ -795,15 +816,14 @@ namespace Barotrauma.Items.Components
{
if (targetPort.Docked || targetPort.Item.Submarine == null) { continue; }
if (targetPort.Item.Submarine == controlledSub || targetPort.IsHorizontal != sourcePort.IsHorizontal) { continue; }
if (targetPort.Item.Submarine.DockedTo?.Contains(sourcePort.Item.Submarine) ?? false) { continue; }
if (Level.Loaded != null && targetPort.Item.Submarine.WorldPosition.Y > Level.Loaded.Size.Y) { continue; }
int targetDir = targetPort.GetDir();
if (sourceDir == targetDir) { continue; }
if (sourceDir == targetPort.GetDir()) { continue; }
float dist = Vector2.DistanceSquared(sourcePort.Item.WorldPosition, targetPort.Item.WorldPosition);
if (dist < closestDist)
{
closestDist = dist;
DockingModeEnabled = true;
ActiveDockingSource = sourcePort;
DockingTarget = targetPort;
@@ -0,0 +1,55 @@
using System;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace Barotrauma.Items.Components
{
internal partial class Planter
{
public Vector2 DrawSize => CalculateSize();
private Vector2 CalculateSize()
{
if (GrowableSeeds.All(s => s == null)) { return Vector2.Zero; }
Point pos = item.DrawPosition.ToPoint();
Rectangle rect = new Rectangle(pos, Point.Zero);
for (int i = 0; i < GrowableSeeds.Length; i++)
{
Growable seed = GrowableSeeds[i];
PlantSlot slot = PlantSlots.ContainsKey(i) ? PlantSlots[i] : NullSlot;
if (seed == null) { continue; }
foreach (VineTile vine in seed.Vines)
{
Rectangle worldRect = vine.Rect;
worldRect.Location += slot.Offset.ToPoint();
worldRect.Location += pos;
rect = Rectangle.Union(rect, worldRect);
}
}
Vector2 result = new Vector2(MaxDistance(pos.X, rect.Left, rect.Right) * 2, MaxDistance(pos.Y, rect.Top, rect.Bottom) * 2);
return result;
static float MaxDistance(float origin, float x, float y)
{
return Math.Max(Math.Abs(origin - x), Math.Abs(origin - y));
}
}
private LightComponent lightComponent;
public void Draw(SpriteBatch spriteBatch, bool editing, float itemDepth = -1)
{
for (var i = 0; i < GrowableSeeds.Length; i++)
{
Growable growable = GrowableSeeds[i];
PlantSlot slot = PlantSlots.ContainsKey(i) ? PlantSlots[i] : NullSlot;
growable?.Draw(spriteBatch, this, slot.Offset, itemDepth);
}
}
}
}
@@ -29,6 +29,7 @@ namespace Barotrauma.Items.Components
private List<Pair<RelatedItem, ParticleEmitter>> particleEmitterHitItem = new List<Pair<RelatedItem, ParticleEmitter>>();
private float prevProgressBarState;
private Item prevProgressBarTarget = null;
partial void InitProjSpecific(XElement element)
{
@@ -65,7 +66,7 @@ namespace Barotrauma.Items.Components
{
foreach (ParticleEmitter particleEmitter in particleEmitters)
{
float particleAngle = item.body.Rotation + ((item.body.Dir > 0.0f) ? 0.0f : MathHelper.Pi);
float particleAngle = item.body.Rotation + MathHelper.ToRadians(BarrelRotation) + ((item.body.Dir > 0.0f) ? 0.0f : MathHelper.Pi);
particleEmitter.Emit(
deltaTime, ConvertUnits.ToDisplayUnits(raystart),
item.CurrentHull, particleAngle, particleEmitter.Prefab.CopyEntityAngle ? -particleAngle : 0);
@@ -92,7 +93,7 @@ namespace Barotrauma.Items.Components
if (targetStructure.Submarine != null) particlePos += targetStructure.Submarine.DrawPosition;
foreach (var emitter in particleEmitterHitStructure)
{
float particleAngle = item.body.Rotation + ((item.body.Dir > 0.0f) ? 0.0f : MathHelper.Pi);
float particleAngle = item.body.Rotation + MathHelper.ToRadians(BarrelRotation) + ((item.body.Dir > 0.0f) ? 0.0f : MathHelper.Pi);
emitter.Emit(deltaTime, particlePos, item.CurrentHull, particleAngle + MathHelper.Pi, -particleAngle + MathHelper.Pi);
}
}
@@ -103,7 +104,7 @@ namespace Barotrauma.Items.Components
if (targetCharacter.Submarine != null) particlePos += targetCharacter.Submarine.DrawPosition;
foreach (var emitter in particleEmitterHitCharacter)
{
float particleAngle = item.body.Rotation + ((item.body.Dir > 0.0f) ? 0.0f : MathHelper.Pi);
float particleAngle = item.body.Rotation + MathHelper.ToRadians(BarrelRotation) + ((item.body.Dir > 0.0f) ? 0.0f : MathHelper.Pi);
emitter.Emit(deltaTime, particlePos, item.CurrentHull, particleAngle + MathHelper.Pi, -particleAngle + MathHelper.Pi);
}
}
@@ -111,7 +112,7 @@ namespace Barotrauma.Items.Components
partial void FixItemProjSpecific(Character user, float deltaTime, Item targetItem)
{
float progressBarState = targetItem.ConditionPercentage / 100.0f;
if (!MathUtils.NearlyEqual(progressBarState, prevProgressBarState))
if (!MathUtils.NearlyEqual(progressBarState, prevProgressBarState) || prevProgressBarTarget != targetItem)
{
var door = targetItem.GetComponent<Door>();
if (door == null || door.Stuck <= 0)
@@ -121,18 +122,20 @@ namespace Barotrauma.Items.Components
targetItem,
progressBarPos,
progressBarState,
GUI.Style.Red, GUI.Style.Green);
GUI.Style.Red, GUI.Style.Green,
progressBarState < prevProgressBarState ? "progressbar.cutting" : "");
if (progressBar != null) { progressBar.Size = new Vector2(60.0f, 20.0f); }
}
prevProgressBarState = progressBarState;
prevProgressBarTarget = targetItem;
}
Vector2 particlePos = ConvertUnits.ToDisplayUnits(pickedPosition);
if (targetItem.Submarine != null) particlePos += targetItem.Submarine.DrawPosition;
foreach (var emitter in particleEmitterHitItem)
{
if (!emitter.First.MatchesItem(targetItem)) continue;
float particleAngle = item.body.Rotation + ((item.body.Dir > 0.0f) ? 0.0f : MathHelper.Pi);
if (!emitter.First.MatchesItem(targetItem)) { continue; }
float particleAngle = item.body.Rotation + MathHelper.ToRadians(BarrelRotation) + ((item.body.Dir > 0.0f) ? 0.0f : MathHelper.Pi);
emitter.Second.Emit(deltaTime, particlePos, item.CurrentHull, particleAngle + MathHelper.Pi, -particleAngle + MathHelper.Pi);
}
}
@@ -192,6 +192,7 @@ namespace Barotrauma.Items.Components
foreach (Wire wire in panel.DisconnectedWires)
{
if (wire == DraggingConnected && mouseInRect) { continue; }
if (wire.HiddenInGame && Screen.Selected == GameMain.GameScreen) { continue; }
Connection recipient = wire.OtherConnection(null);
string label = recipient == null ? "" : recipient.item.Name + $" ({recipient.DisplayName})";
@@ -238,6 +239,7 @@ namespace Barotrauma.Items.Components
for (int i = 0; i < MaxLinked; i++)
{
if (wires[i] == null || wires[i].Hidden || (DraggingConnected == wires[i] && (mouseIn || Screen.Selected == GameMain.SubEditorScreen))) { continue; }
if (wires[i].HiddenInGame && Screen.Selected == GameMain.GameScreen) { continue; }
Connection recipient = wires[i].OtherConnection(this);
string label = recipient == null ? "" : recipient.item.Name + $" ({recipient.DisplayName})";
@@ -289,7 +291,7 @@ namespace Barotrauma.Items.Components
flashColor * (float)Math.Sin(FlashTimer % flashCycleDuration / flashCycleDuration * MathHelper.Pi * 0.8f), scale: connectorSpriteScale);
}
if (Wires.Any(w => w != null && w != DraggingConnected && !w.Hidden))
if (Wires.Any(w => w != null && w != DraggingConnected && !w.Hidden && (!w.HiddenInGame || Screen.Selected != GameMain.GameScreen)))
{
int screwIndex = (int)Math.Floor(position.Y / 30.0f) % screwSprites.Count;
screwSprites[screwIndex].Draw(spriteBatch, position, scale: connectorSpriteScale);
@@ -325,7 +327,7 @@ namespace Barotrauma.Items.Components
canDrag &&
((PlayerInput.MousePosition.X > Math.Min(start.X, end.X) &&
PlayerInput.MousePosition.X < Math.Max(start.X, end.X) &&
MathUtils.LineToPointDistance(start, end, PlayerInput.MousePosition) < 6) ||
MathUtils.LineToPointDistanceSquared(start, end, PlayerInput.MousePosition) < 36) ||
Vector2.Distance(end, PlayerInput.MousePosition) < 20.0f ||
new Rectangle((start.X < end.X) ? textX - 100 : textX, (int)start.Y - 5, 100, 14).Contains(PlayerInput.MousePosition));
@@ -0,0 +1,12 @@
using Barotrauma.Networking;
namespace Barotrauma.Items.Components
{
partial class MemoryComponent : ItemComponent
{
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
{
Value = msg.ReadString();
}
}
}
@@ -165,6 +165,12 @@ namespace Barotrauma.Items.Components
}
else
{
if (!string.IsNullOrEmpty(target.customInteractHUDText) && target.AllowCustomInteract)
{
texts.Add(target.customInteractHUDText);
textColors.Add(GUI.Style.Green);
}
if (target.IsUnconscious)
{
texts.Add(TextManager.Get("Unconscious"));
@@ -17,6 +17,17 @@ namespace Barotrauma.Items.Components
private GUIProgressBar powerIndicator;
public int UIElementHeight
{
get
{
int height = 0;
if (ShowChargeIndicator) { height += powerIndicator.Rect.Height; }
if (ShowProjectileIndicator) { height += (int)(Inventory.SlotSpriteSmall.size.Y * Inventory.UIScale) + 5; }
return height;
}
}
private float recoilTimer;
private float RetractionTime => Math.Max(Reload * RetractionDurationMultiplier, RecoilTime);
@@ -235,12 +246,11 @@ namespace Barotrauma.Items.Components
public void Draw(SpriteBatch spriteBatch, bool editing = false, float itemDepth = -1)
{
Vector2 drawPos = new Vector2(item.Rect.X + transformedBarrelPos.X, item.Rect.Y - transformedBarrelPos.Y);
if (item.Submarine != null)
if (!MathUtils.NearlyEqual(item.Rotation, prevBaseRotation))
{
drawPos += item.Submarine.DrawPosition;
UpdateTransformedBarrelPos();
}
drawPos.Y = -drawPos.Y;
Vector2 drawPos = GetDrawPos();
float recoilOffset = 0.0f;
if (Math.Abs(RecoilDistance) > 0.0f && recoilTimer > 0.0f)
@@ -275,7 +285,7 @@ namespace Barotrauma.Items.Components
rotation + MathHelper.PiOver2, item.Scale,
SpriteEffects.None, item.SpriteDepth + (barrelSprite.Depth - item.Sprite.Depth));
if (!editing) { return; }
if (!editing || GUI.DisableHUD) { return; }
float widgetRadius = 60.0f;
@@ -310,7 +320,7 @@ namespace Barotrauma.Items.Components
};
widget.MouseHeld += (deltaTime) =>
{
minRotation = GetRotationAngle(drawPos);
minRotation = GetRotationAngle(GetDrawPos());
if (minRotation > maxRotation)
{
float temp = minRotation;
@@ -332,7 +342,7 @@ namespace Barotrauma.Items.Components
widget.PreDraw += (sprtBtch, deltaTime) =>
{
widget.tooltip = "Min: " + (int)MathHelper.ToDegrees(minRotation);
widget.DrawPos = drawPos + new Vector2((float)Math.Cos(minRotation), (float)Math.Sin(minRotation)) * widgetRadius;
widget.DrawPos = GetDrawPos() + new Vector2((float)Math.Cos(minRotation), (float)Math.Sin(minRotation)) * widgetRadius;
widget.Update(deltaTime);
};
});
@@ -351,7 +361,7 @@ namespace Barotrauma.Items.Components
};
widget.MouseHeld += (deltaTime) =>
{
maxRotation = GetRotationAngle(drawPos);
maxRotation = GetRotationAngle(GetDrawPos());
if (minRotation > maxRotation)
{
float temp = minRotation;
@@ -373,12 +383,20 @@ namespace Barotrauma.Items.Components
widget.PreDraw += (sprtBtch, deltaTime) =>
{
widget.tooltip = "Max: " + (int)MathHelper.ToDegrees(maxRotation);
widget.DrawPos = drawPos + new Vector2((float)Math.Cos(maxRotation), (float)Math.Sin(maxRotation)) * widgetRadius;
widget.DrawPos = GetDrawPos() + new Vector2((float)Math.Cos(maxRotation), (float)Math.Sin(maxRotation)) * widgetRadius;
widget.Update(deltaTime);
};
});
minRotationWidget.Draw(spriteBatch, (float)Timing.Step);
maxRotationWidget.Draw(spriteBatch, (float)Timing.Step);
Vector2 GetDrawPos()
{
Vector2 drawPos = new Vector2(item.Rect.X + transformedBarrelPos.X, item.Rect.Y - transformedBarrelPos.Y);
if (item.Submarine != null) { drawPos += item.Submarine.DrawPosition; }
drawPos.Y = -drawPos.Y;
return drawPos;
}
}
private Widget GetWidget(string id, SpriteBatch spriteBatch, int size = 5, Action<Widget> initMethod = null)