v1.5.7.0 (Summer Update)

This commit is contained in:
Regalis11
2024-06-18 16:49:51 +03:00
parent 4a63dacbce
commit 230d1b6e78
263 changed files with 7792 additions and 2845 deletions
@@ -785,7 +785,7 @@ namespace Barotrauma
{
if (item.Container == null || character.Inventory.FindIndex(item.Container) == -1) // Not a subinventory in the character's inventory
{
if (character.HeldItems.Any(i => i.OwnInventory != null && i.OwnInventory.CanBePut(item)))
if (character.HeldItems.Any(i => i.OwnInventory != null && i.OwnInventory.CanBePut(item) && character.CanAccessInventory(i.OwnInventory)))
{
return QuickUseAction.PutToEquippedItem;
}
@@ -843,13 +843,14 @@ namespace Barotrauma
else if (character.HeldItems.FirstOrDefault(i =>
i.OwnInventory != null &&
i.OwnInventory.Container.DrawInventory &&
character.CanAccessInventory(i.OwnInventory) &&
(i.OwnInventory.CanBePut(item) || ((i.OwnInventory.Capacity == 1 || i.OwnInventory.Container.HasSubContainers) && i.OwnInventory.AllowSwappingContainedItems && i.OwnInventory.Container.CanBeContained(item)))) is { } equippedContainer)
{
if (allowEquip)
{
if (!character.HasEquippedItem(item))
{
if (equippedContainer.GetComponent<ItemContainer>() is { QuickUseMovesItemsInside: false})
if (equippedContainer.GetComponent<ItemContainer>() is { QuickUseMovesItemsInside: false })
{
//put the item in a hand slot if that hand is free
if ((item.AllowedSlots.Contains(InvSlotType.RightHand) && character.Inventory.GetItemInLimbSlot(InvSlotType.RightHand) == null) ||
@@ -79,7 +79,8 @@ namespace Barotrauma.Items.Components
set;
}
[Serialize(false, IsPropertySaveable.No, description: "If true, the contained state indicator calculates how full the item is based on the total amount of items that can be stacked inside it, as opposed to how many of the inventory slots are occupied.")]
[Serialize(false, IsPropertySaveable.No, description: "If true, the contained state indicator calculates how full the item is based on the total amount of items that can be stacked inside it, as opposed to how many of the inventory slots are occupied." +
" Note that only items in the main container or in the subcontainer are counted, depending on which container the first containable item match is found in. The item determining this can be defined with ContainedStateIndicatorSlot")]
public bool ShowTotalStackCapacityInContainedStateIndicator { get; set; }
[Serialize(false, IsPropertySaveable.No, description: "Should the inventory of this item be kept open when the item is equipped by a character.")]
@@ -274,8 +275,14 @@ namespace Barotrauma.Items.Components
}
}
itemsPerSlot.Sort((i1, i2) => i1.First().Name.CompareTo(i2.First().Name));
foreach (var items in itemsPerSlot)
var sortedItems = itemsPerSlot
.OrderBy(i => i.First().Name)
//if there's multiple items with the same name, sort largest stacks first
.ThenByDescending(i => i.Count)
//same name and stack size, sort items with most items inside first
.ThenByDescending(i => i.First().ContainedItems.Count());
foreach (var items in sortedItems)
{
int firstFreeSlot = -1;
for (int i = 0; i < Inventory.Capacity; i++)
@@ -591,7 +598,8 @@ namespace Barotrauma.Items.Components
contained.Item.Scale,
spriteEffects,
depth: containedSpriteDepth);
contained.Item.DrawDecorativeSprites(spriteBatch, itemPos, flipX,flipY, (contained.Item.body == null ? 0.0f : contained.Item.body.DrawRotation), containedSpriteDepth);
contained.Item.DrawDecorativeSprites(spriteBatch, itemPos, flipX,flipY, (contained.Item.body == null ? 0.0f : contained.Item.body.DrawRotation),
containedSpriteDepth, overrideColor);
foreach (ItemContainer ic in contained.Item.GetComponents<ItemContainer>())
{
@@ -40,7 +40,7 @@ namespace Barotrauma.Items.Components
partial void SetLightSourceState(bool enabled, float brightness)
{
if (Light == null) { return; }
if (item.HiddenInGame) { enabled = false; }
if (item.IsHidden) { enabled = false; }
Light.Enabled = enabled;
lightColorMultiplier = brightness;
if (enabled)
@@ -429,7 +429,7 @@ namespace Barotrauma.Items.Components
{
if (it?.Submarine == null) { return false; }
if (item.Submarine == null || !item.Submarine.IsEntityFoundOnThisSub(it, includingConnectedSubs: true)) { return false; }
if (it.NonInteractable || it.HiddenInGame) { return false; }
if (it.NonInteractable || it.IsHidden) { return false; }
if (it.GetComponent<Pickable>() == null) { return false; }
var holdable = it.GetComponent<Holdable>();
@@ -470,10 +470,10 @@ namespace Barotrauma.Items.Components
scissorComponent = new GUIScissorComponent(new RectTransform(Vector2.One, submarineContainer.RectTransform, Anchor.Center));
miniMapContainer = new GUIFrame(new RectTransform(Vector2.One, scissorComponent.Content.RectTransform, Anchor.Center), style: null) { CanBeFocused = false };
ImmutableHashSet<Item> hullPointsOfInterest = Item.ItemList.Where(it => item.Submarine.IsEntityFoundOnThisSub(it, includingConnectedSubs: true) && !it.HiddenInGame && !it.NonInteractable && it.Prefab.ShowInStatusMonitor && (it.GetComponent<Door>() != null || it.GetComponent<Turret>() != null)).ToImmutableHashSet();
ImmutableHashSet<Item> hullPointsOfInterest = Item.ItemList.Where(it => item.Submarine.IsEntityFoundOnThisSub(it, includingConnectedSubs: true) && !it.IsHidden && !it.NonInteractable && it.Prefab.ShowInStatusMonitor && (it.GetComponent<Door>() != null || it.GetComponent<Turret>() != null)).ToImmutableHashSet();
miniMapFrame = CreateMiniMap(item.Submarine, submarineContainer, MiniMapSettings.Default, hullPointsOfInterest, out hullStatusComponents);
IEnumerable<Item> electricalPointsOfInterest = Item.ItemList.Where(it => item.Submarine.IsEntityFoundOnThisSub(it, includingConnectedSubs: true) && !it.HiddenInGame && !it.NonInteractable && it.GetComponent<Repairable>() != null);
IEnumerable<Item> electricalPointsOfInterest = Item.ItemList.Where(it => item.Submarine.IsEntityFoundOnThisSub(it, includingConnectedSubs: true) && !it.IsHidden && !it.NonInteractable && it.GetComponent<Repairable>() != null);
electricalFrame = CreateMiniMap(item.Submarine, miniMapContainer, new MiniMapSettings(createHullElements: false), electricalPointsOfInterest, out electricalMapComponents);
Dictionary<MiniMapGUIComponent, GUIComponent> electricChildren = new Dictionary<MiniMapGUIComponent, GUIComponent>();
@@ -566,7 +566,7 @@ namespace Barotrauma.Items.Components
displayedSubs.Add(item.Submarine);
displayedSubs.AddRange(item.Submarine.DockedTo.Where(s => s.TeamID == item.Submarine.TeamID));
subEntities = MapEntity.MapEntityList.Where(me => (item.Submarine is { } sub && sub.IsEntityFoundOnThisSub(me, includingConnectedSubs: true, allowDifferentType: false)) && !me.HiddenInGame).OrderByDescending(w => w.SpriteDepth).ToList();
subEntities = MapEntity.MapEntityList.Where(me => (item.Submarine is { } sub && sub.IsEntityFoundOnThisSub(me, includingConnectedSubs: true, allowDifferentType: false)) && !me.IsHidden).OrderByDescending(w => w.SpriteDepth).ToList();
BakeSubmarine(item.Submarine, parentRect);
elementSize = GuiFrame.Rect.Size;
@@ -763,7 +763,7 @@ namespace Barotrauma.Items.Components
worldBorders.Location += item.Submarine.WorldPosition.ToPoint();
foreach (Gap gap in Gap.GapList)
{
if (gap.IsRoomToRoom || gap.linkedTo.Count == 0 || gap.Submarine != item.Submarine || gap.ConnectedDoor != null || gap.HiddenInGame) { continue; }
if (gap.IsRoomToRoom || gap.linkedTo.Count == 0 || gap.Submarine != item.Submarine || gap.ConnectedDoor != null || gap.IsHidden) { continue; }
RectangleF entityRect = ScaleRectToUI(gap, miniMapFrame.Rect, worldBorders);
Vector2 scale = new Vector2(entityRect.Size.X / spriteSize.X, entityRect.Size.Y / spriteSize.Y) * 2.0f;
@@ -930,7 +930,7 @@ namespace Barotrauma.Items.Components
if (DisplayAsSameItem(it.Prefab, searchedPrefab))
{
// ignore items on players and hidden inventories
if (it.FindParentInventory(inv => inv is CharacterInventory || inv is ItemInventory { Owner: Item { HiddenInGame: true }}) is { }) { continue; }
if (it.FindParentInventory(inv => inv is CharacterInventory || inv is ItemInventory { Owner: Item { IsHidden: true }}) is { }) { continue; }
if (it.FindParentInventory(inventory => inventory is ItemInventory { Owner: Item { ParentInventory: null } }) is ItemInventory parent)
{
@@ -1112,7 +1112,7 @@ namespace Barotrauma.Items.Components
if (ShowHullIntegrity)
{
float amount = 1f + hullData.LinkedHulls.Count;
gapOpenSum = hull.ConnectedGaps.Concat(hullData.LinkedHulls.SelectMany(h => h.ConnectedGaps)).Where(g => g.linkedTo.Count == 1 && !g.HiddenInGame).Sum(g => g.Open) / amount;
gapOpenSum = hull.ConnectedGaps.Concat(hullData.LinkedHulls.SelectMany(h => h.ConnectedGaps)).Where(g => g.linkedTo.Count == 1 && !g.IsHidden).Sum(g => g.Open) / amount;
borderColor = Color.Lerp(neutralColor, GUIStyle.Red, Math.Min(gapOpenSum, 1.0f));
}
@@ -1557,7 +1557,7 @@ namespace Barotrauma.Items.Components
{
if (linkedEntity is Hull linkedHull)
{
if (linkedHulls.Contains(linkedHull) || linkedHull.HiddenInGame) { continue; }
if (linkedHulls.Contains(linkedHull) || linkedHull.IsHidden) { continue; }
linkedHulls.Add(linkedHull);
GetLinkedHulls(linkedHull, linkedHulls);
}
@@ -1737,7 +1737,7 @@ namespace Barotrauma.Items.Components
bool IsPartofSub(MapEntity entity)
{
if (entity.Submarine != sub && !connectedSubs.Contains(entity.Submarine) || entity.HiddenInGame) { return false; }
if (entity.Submarine != sub && !connectedSubs.Contains(entity.Submarine) || entity.IsHidden) { return false; }
return sub.IsEntityFoundOnThisSub(entity, true);
}
@@ -1186,7 +1186,7 @@ namespace Barotrauma.Items.Components
foreach (DockingPort dockingPort in DockingPort.List)
{
if (Level.Loaded != null && dockingPort.Item.Submarine.WorldPosition.Y > Level.Loaded.Size.Y) { continue; }
if (dockingPort.Item.HiddenInGame) { continue; }
if (dockingPort.Item.IsHidden) { continue; }
if (dockingPort.Item.Submarine == null) { continue; }
if (dockingPort.Item.Submarine.Info.IsWreck) { continue; }
// docking ports should be shown even if defined as not, if the submarine is the same as the sonar's
@@ -60,7 +60,7 @@ namespace Barotrauma.Items.Components
public override bool ShouldDrawHUD(Character character)
{
if (item.HiddenInGame) { return false; }
if (item.IsHidden) { return false; }
if (!HasRequiredItems(character, false) || character.SelectedItem != item) { return false; }
if (character.IsTraitor && item.ConditionPercentage > MinSabotageCondition) { return true; }
if (item.ConditionPercentageRelativeToDefaultMaxCondition < RepairThreshold) { return true; }
@@ -224,7 +224,7 @@ namespace Barotrauma.Items.Components
partial void UpdateProjSpecific(float deltaTime)
{
if (item.HiddenInGame) { return; }
if (item.IsHidden) { return; }
if (FakeBrokenTimer > 0.0f)
{
item.FakeBroken = true;
@@ -397,6 +397,12 @@ namespace Barotrauma.Items.Components
GUI.DrawString(spriteBatch,
new Vector2(item.DrawPosition.X, -item.DrawPosition.Y + 20), "Condition: " + (int)item.Condition + "/" + (int)item.MaxCondition,
GUIStyle.Orange);
if (MaxStressDeteriorationMultiplier > 1.0f)
{
GUI.DrawString(spriteBatch,
new Vector2(item.DrawPosition.X, -item.DrawPosition.Y + 40), "Stress multiplier: " + StressDeteriorationMultiplier.ToString("0.00"),
GUIStyle.Red);
}
}
}
@@ -303,6 +303,17 @@ namespace Barotrauma.Items.Components
CreateClientEvent(new CircuitBoxRenameLabelEvent(label.ID, color, header, body));
}
public void SetConnectionLabelOverrides(CircuitBoxInputOutputNode node, Dictionary<string, string> newOverrides)
{
if (GameMain.NetworkMember is null)
{
node.ReplaceAllConnectionLabelOverrides(newOverrides);
return;
}
CreateClientEvent(new CircuitBoxRenameConnectionLabelsEvent(node.NodeType, newOverrides.ToNetDictionary()));
}
public void ResizeNode(CircuitBoxNode node, CircuitBoxResizeDirection dir, Vector2 amount)
{
if (Locked) { return; }
@@ -528,6 +539,12 @@ namespace Barotrauma.Items.Components
_ => node.Position
};
}
foreach (var labelOverride in data.LabelOverrides)
{
RenameConnectionLabelsInternal(labelOverride.Type, labelOverride.Override.ToDictionary());
}
wasInitializedByServer = true;
break;
}
@@ -556,6 +573,12 @@ namespace Barotrauma.Items.Components
ResizeLabelInternal(data.ID, data.Position, data.Size);
break;
}
case CircuitBoxOpcode.RenameConnections:
{
var data = INetSerializableStruct.Read<CircuitBoxRenameConnectionLabelsEvent>(msg);
RenameConnectionLabelsInternal(data.Type, data.Override.ToDictionary());
break;
}
default:
throw new ArgumentOutOfRangeException(nameof(header), header, "This opcode cannot be handled using entity events");
}
@@ -292,8 +292,17 @@ namespace Barotrauma.Items.Components
if (wire.HiddenInGame && Screen.Selected == GameMain.GameScreen) { continue; }
Connection recipient = wire.OtherConnection(this);
LocalizedString label = recipient == null ? "" : recipient.item.Name + $" ({recipient.DisplayName})";
if (wire.Locked) { label += "\n" + TextManager.Get("ConnectionLocked"); }
LocalizedString label;
if (wire.Item.IsLayerHidden)
{
label = TextManager.Get("ConnectionLocked");
}
else
{
label = recipient == null ? "" : recipient.item.Name + $" ({recipient.DisplayName})";
if (wire.Locked) { label += "\n" + TextManager.Get("ConnectionLocked"); }
}
DrawWire(spriteBatch, wire, position, wirePosition, equippedWire, panel, label);
wirePosition.Y += wireInterval;
@@ -494,7 +503,7 @@ namespace Barotrauma.Items.Components
ConnectionPanel.HighlightedWire = wire;
bool allowRewiring = GameMain.NetworkMember?.ServerSettings == null || GameMain.NetworkMember.ServerSettings.AllowRewiring || panel.AlwaysAllowRewiring;
if (allowRewiring && (!wire.Locked && !panel.Locked && !panel.TemporarilyLocked || Screen.Selected == GameMain.SubEditorScreen))
if (allowRewiring && (!wire.Locked && !wire.Item.IsLayerHidden && !panel.Locked && !panel.TemporarilyLocked || Screen.Selected == GameMain.SubEditorScreen))
{
//start dragging the wire
if (PlayerInput.PrimaryMouseButtonHeld()) { DraggingConnected = wire; }
@@ -283,12 +283,12 @@ namespace Barotrauma.Items.Components
texts.Add(CharacterHUD.GetCachedHudText("PlayHint", InputType.Use));
textColors.Add(GUIStyle.Green);
}
if (target.CharacterHealth.UseHealthWindow && !target.DisableHealthWindow && equipper?.FocusedCharacter == target && equipper.CanInteractWith(target, 160f, false))
if (equipper?.FocusedCharacter == target && target.CanBeHealedBy(equipper, checkFriendlyTeam: false))
{
texts.Add(CharacterHUD.GetCachedHudText("HealHint", InputType.Health));
textColors.Add(GUIStyle.Green);
}
if (target.CanBeDragged)
if (target.CanBeDraggedBy(Character.Controlled))
{
texts.Add(CharacterHUD.GetCachedHudText("GrabHint", InputType.Grab));
textColors.Add(GUIStyle.Green);
@@ -196,7 +196,7 @@ namespace Barotrauma.Items.Components
Vector2 particlePos = GetRelativeFiringPosition();
foreach (ParticleEmitter emitter in particleEmitters)
{
emitter.Emit(1.0f, particlePos, hullGuess: null, angle: -rotation, particleRotation: rotation);
emitter.Emit(1.0f, particlePos, hullGuess: null, angle: -Rotation, particleRotation: Rotation);
}
}
@@ -213,7 +213,7 @@ namespace Barotrauma.Items.Components
if (crosshairSprite != null)
{
Vector2 itemPos = cam.WorldToScreen(new Vector2(item.WorldRect.X + transformedBarrelPos.X, item.WorldRect.Y - transformedBarrelPos.Y));
Vector2 turretDir = new Vector2((float)Math.Cos(rotation), (float)Math.Sin(rotation));
Vector2 turretDir = new Vector2((float)Math.Cos(Rotation), (float)Math.Sin(Rotation));
Vector2 mouseDiff = itemPos - PlayerInput.MousePosition;
crosshairPos = new Vector2(
@@ -268,7 +268,7 @@ namespace Barotrauma.Items.Components
foreach (ParticleEmitter emitter in particleEmitterCharges)
{
// color is currently not connected to ammo type, should be updated when ammo is changed
emitter.Emit(deltaTime, particlePos, hullGuess: null, angle: -rotation, particleRotation: rotation, sizeMultiplier: sizeMultiplier, colorMultiplier: emitter.Prefab.Properties.ColorMultiplier);
emitter.Emit(deltaTime, particlePos, hullGuess: null, angle: -Rotation, particleRotation: Rotation, sizeMultiplier: sizeMultiplier, colorMultiplier: emitter.Prefab.Properties.ColorMultiplier);
}
if (chargeSoundChannel == null || !chargeSoundChannel.IsPlaying)
@@ -339,7 +339,7 @@ namespace Barotrauma.Items.Components
if (crosshairSprite != null)
{
Vector2 itemPos = cam.WorldToScreen(item.WorldPosition);
Vector2 turretDir = new Vector2((float)Math.Cos(rotation), (float)Math.Sin(rotation));
Vector2 turretDir = new Vector2((float)Math.Cos(Rotation), (float)Math.Sin(Rotation));
Vector2 mouseDiff = itemPos - PlayerInput.MousePosition;
crosshairPos = new Vector2(
@@ -372,7 +372,7 @@ namespace Barotrauma.Items.Components
recoilOffset = RecoilDistance;
}
}
return new Vector2((float)Math.Cos(rotation), (float)Math.Sin(rotation)) * recoilOffset;
return new Vector2((float)Math.Cos(Rotation), (float)Math.Sin(Rotation)) * recoilOffset;
}
public void Draw(SpriteBatch spriteBatch, bool editing = false, float itemDepth = -1, Color? overrideColor = null)
@@ -388,13 +388,13 @@ namespace Barotrauma.Items.Components
railSprite?.Draw(spriteBatch,
drawPos,
overrideColor ?? item.SpriteColor,
rotation + MathHelper.PiOver2, item.Scale,
Rotation + MathHelper.PiOver2, item.Scale,
SpriteEffects.None, item.SpriteDepth + (railSprite.Depth - item.Sprite.Depth));
barrelSprite?.Draw(spriteBatch,
drawPos - GetRecoilOffset() * item.Scale,
overrideColor ?? item.SpriteColor,
rotation + MathHelper.PiOver2, item.Scale,
Rotation + MathHelper.PiOver2, item.Scale,
SpriteEffects.None, item.SpriteDepth + (barrelSprite.Depth - item.Sprite.Depth));
float chargeRatio = currentChargeTime / MaxChargeTime;
@@ -402,9 +402,9 @@ namespace Barotrauma.Items.Components
foreach ((Sprite chargeSprite, Vector2 position) in chargeSprites)
{
chargeSprite?.Draw(spriteBatch,
drawPos - MathUtils.RotatePoint(new Vector2(position.X * chargeRatio, position.Y * chargeRatio) * item.Scale, rotation + MathHelper.PiOver2),
drawPos - MathUtils.RotatePoint(new Vector2(position.X * chargeRatio, position.Y * chargeRatio) * item.Scale, Rotation + MathHelper.PiOver2),
item.SpriteColor,
rotation + MathHelper.PiOver2, item.Scale,
Rotation + MathHelper.PiOver2, item.Scale,
SpriteEffects.None, item.SpriteDepth + (chargeSprite.Depth - item.Sprite.Depth));
}
@@ -427,9 +427,9 @@ namespace Barotrauma.Items.Components
float newPositionOffset = barrelPositionModifier * SpinningBarrelDistance;
spinningBarrel.Draw(spriteBatch,
drawPos - MathUtils.RotatePoint(new Vector2(newPositionOffset, 0f) * item.Scale, rotation + MathHelper.PiOver2),
drawPos - MathUtils.RotatePoint(new Vector2(newPositionOffset, 0f) * item.Scale, Rotation + MathHelper.PiOver2),
Color.Lerp(overrideColor ?? item.SpriteColor, newColorModifier, 0.8f),
rotation + MathHelper.PiOver2, item.Scale,
Rotation + MathHelper.PiOver2, item.Scale,
SpriteEffects.None, newDepth);
}
}
@@ -475,9 +475,9 @@ namespace Barotrauma.Items.Components
{
spriteBatch.DrawLine(drawPos, drawPos + center * circleRadius, GUIStyle.Green, thickness: lineThickness);
}
else if (radians > Math.PI * 2)
else if (radians >= MathHelper.TwoPi)
{
spriteBatch.DrawCircle(drawPos, circleRadius, 180, GUIStyle.Red, thickness: lineThickness);
spriteBatch.DrawCircle(drawPos, circleRadius, 180, GUIStyle.Green, thickness: lineThickness);
}
else
{
@@ -510,7 +510,12 @@ namespace Barotrauma.Items.Components
};
widget.MouseHeld += (deltaTime) =>
{
minRotation = GetRotationAngle(GetDrawPos());
float newMinRotation = GetRotationAngle(GetDrawPos());
AngleWrapAdjustment(minRotation, newMinRotation, ref maxRotation);
// clamp value here to keep widget movement within max range
minRotation = MathHelper.Clamp(newMinRotation, maxRotation - MathHelper.TwoPi, maxRotation);
UpdateBarrel();
MapEntity.DisableSelect = true;
};
@@ -554,7 +559,12 @@ namespace Barotrauma.Items.Components
};
widget.MouseHeld += (deltaTime) =>
{
maxRotation = GetRotationAngle(GetDrawPos());
float newMaxRotation = GetRotationAngle(GetDrawPos());
AngleWrapAdjustment(maxRotation, newMaxRotation, ref minRotation);
// clamp value here to keep widget movement within max range
maxRotation = MathHelper.Clamp(newMaxRotation, minRotation, minRotation + MathHelper.TwoPi);
UpdateBarrel();
MapEntity.DisableSelect = true;
};
@@ -580,10 +590,44 @@ namespace Barotrauma.Items.Components
void UpdateBarrel()
{
rotation = (minRotation + maxRotation) / 2;
Rotation = (minRotation + maxRotation) / 2;
}
}
private static void AngleWrapAdjustment(float currentRotation, float newRotation, ref float rangeLockedRotation)
{
if (DetectAngleWrapAround(currentRotation, newRotation))
{
// if there's a wrap-around, also wrap the other rotation limit to keep range
if (newRotation < currentRotation)
{
rangeLockedRotation -= MathHelper.TwoPi;
}
else
{
rangeLockedRotation += MathHelper.TwoPi;
}
}
}
private static bool DetectAngleWrapAround(float rotation, float newRotation)
{
float deltaRotation = MathF.Abs(rotation - newRotation);
// turret angle wraps around to 0 from -2Pi and 2Pi.
// Detect wrap-around when dragging the widgets, where usual rotation delta is small,
// so a large jump in rotation (here, an arbitrary big value in the range of 0 to 2Pi)
// is considered a wrap-around for this purpose.
// NOTE: this is not a reliable way to detect angle wrap-around in general, and is only intended for
// the angle widgets!
if (deltaRotation > MathHelper.TwoPi * 0.8f)
{
return true;
}
return false;
}
public Vector2 GetDrawPos()
{
Vector2 drawPos = new Vector2(item.Rect.X + transformedBarrelPos.X, item.Rect.Y - transformedBarrelPos.Y);
@@ -764,7 +808,7 @@ namespace Barotrauma.Items.Components
if (projectileID == 0) { return; }
//ID ushort.MaxValue = launched without a projectile
if (projectileID == ushort.MaxValue)
if (projectileID == LaunchWithoutProjectileId)
{
Launch(null, user);
}
@@ -319,7 +319,7 @@ namespace Barotrauma
}
}
string colorStr = (item.SpawnedInCurrentOutpost && !item.AllowStealing ? GUIStyle.Red : Color.White).ToStringHex();
string colorStr = (item.Illegitimate ? GUIStyle.Red : Color.White).ToStringHex();
toolTip = $"‖color:{colorStr}‖{name}‖color:end‖";
if (item.GetComponent<Quality>() != null)
@@ -478,10 +478,11 @@ namespace Barotrauma
{
int row = (int)Math.Floor((double)i / slotsPerRow);
int slotsPerThisRow = Math.Min(slotsPerRow, capacity - row * slotsPerRow);
int slotNumberOnThisRow = i - row * slotsPerRow;
int rowWidth = (int)(rectSize.X * slotsPerThisRow + spacing.X * (slotsPerThisRow - 1));
slotRect.X = (int)(center.X) - rowWidth / 2;
slotRect.X += (int)((rectSize.X + spacing.X) * (i % slotsPerThisRow));
slotRect.X += (int)((rectSize.X + spacing.X) * (slotNumberOnThisRow % slotsPerThisRow));
slotRect.Y = (int)(topLeft.Y + (rectSize.Y + spacing.Y) * row);
visualSlots[i] = new VisualSlot(slotRect);
@@ -1185,6 +1186,7 @@ namespace Barotrauma
{
DraggingItems.RemoveAll(it => !Character.Controlled.CanInteractWith(it));
}
if (DraggingItems.Any() && PlayerInput.PrimaryMouseButtonReleased())
{
Character.Controlled.ClearInputs();
@@ -1193,198 +1195,234 @@ namespace Barotrauma
if (!DetermineMouseOnInventory(ignoreDraggedItem: true) &&
(CharacterHealth.OpenHealthWindow != null || mouseOnPortrait))
{
bool dropSuccessful = false;
foreach (Item item in DraggingItems)
if (TryPortraitAndHealthDrop(mouseOnPortrait))
{
var inventory = item.ParentInventory;
var indices = inventory?.FindIndices(item);
dropSuccessful |= (CharacterHealth.OpenHealthWindow ?? Character.Controlled.CharacterHealth).OnItemDropped(item, ignoreMousePos: mouseOnPortrait);
if (dropSuccessful)
{
if (indices != null && inventory.visualSlots != null)
{
foreach (int i in indices)
{
inventory.visualSlots[i]?.ShowBorderHighlight(GUIStyle.Green, 0.1f, 0.4f);
}
}
break;
}
}
if (dropSuccessful)
{
DraggingItems.Clear();
return;
}
}
if (selectedSlot == null)
{
if (DraggingItemToWorld &&
Character.Controlled.FocusedItem is { OwnInventory: { } inventory } item && item.GetComponent<ItemContainer>() is { } container &&
container.HasRequiredItems(Character.Controlled, addMessage: false) &&
container.AllowDragAndDrop &&
inventory.CanBePut(DraggingItems.FirstOrDefault()))
HandleOutsideInventoryDrop();
}
else if (!DraggingItems.Any(it => selectedSlot.ParentInventory.slots[selectedSlot.SlotIndex].Contains(it)))
{
HandleInventorySlotDrop();
}
DraggingItems.Clear();
}
if (selectedSlot != null && !CanSelectSlot(selectedSlot))
{
selectedSlot = null;
}
bool TryPortraitAndHealthDrop(bool mouseOnPortrait)
{
bool dropSuccessful = false;
foreach (Item item in DraggingItems)
{
var inventory = item.ParentInventory;
var indices = inventory?.FindIndices(item);
dropSuccessful |= (CharacterHealth.OpenHealthWindow ?? Character.Controlled.CharacterHealth).OnItemDropped(item, ignoreMousePos: mouseOnPortrait);
if (dropSuccessful)
{
bool anySuccess = false;
foreach (Item it in DraggingItems)
if (indices != null && inventory.visualSlots != null)
{
bool success = Character.Controlled.FocusedItem.OwnInventory.TryPutItem(it, Character.Controlled);
if (!success) { break; }
anySuccess |= success;
}
if (anySuccess) { SoundPlayer.PlayUISound(GUISoundType.PickItem); }
}
else
{
if (Screen.Selected is SubEditorScreen)
{
if (DraggingItems.First()?.ParentInventory != null)
foreach (int i in indices)
{
SubEditorScreen.StoreCommand(new InventoryPlaceCommand(DraggingItems.First().ParentInventory, new List<Item>(DraggingItems), true));
inventory.visualSlots[i]?.ShowBorderHighlight(GUIStyle.Green, 0.1f, 0.4f);
}
}
SoundPlayer.PlayUISound(GUISoundType.DropItem);
bool removed = false;
if (Screen.Selected is SubEditorScreen editor)
break;
}
}
if (dropSuccessful)
{
DraggingItems.Clear();
return true;
}
return false;
}
void HandleOutsideInventoryDrop()
{
bool isTargetingValidContainer = Character.Controlled.FocusedItem is { OwnInventory: { } inventory } item &&
item.GetComponent<ItemContainer>() is { } container &&
container.HasRequiredItems(Character.Controlled, addMessage: false) &&
container.AllowDragAndDrop &&
inventory.CanBePut(DraggingItems.FirstOrDefault());
bool isTargetingValidCharacter = IsValidTargetForDragDropGive(Character.Controlled, Character.Controlled.FocusedCharacter);
if (DraggingItemToWorld && (isTargetingValidContainer || isTargetingValidCharacter))
{
bool anySuccess = false;
foreach (Item it in DraggingItems)
{
bool success = false;
if (isTargetingValidContainer)
{
if (editor.EntityMenu.Rect.Contains(PlayerInput.MousePosition))
success = Character.Controlled.FocusedItem.OwnInventory.TryPutItem(it, Character.Controlled);
}
if (!success && isTargetingValidCharacter)
{
success = Character.Controlled.FocusedCharacter.Inventory.TryPutItem(it, Character.Controlled, CharacterInventory.AnySlot);
}
if (!success) { break; }
anySuccess = true;
}
if (anySuccess) { SoundPlayer.PlayUISound(GUISoundType.PickItem); }
}
else
{
if (Screen.Selected is SubEditorScreen)
{
if (DraggingItems.First()?.ParentInventory != null)
{
SubEditorScreen.StoreCommand(new InventoryPlaceCommand(DraggingItems.First().ParentInventory, new List<Item>(DraggingItems), true));
}
}
SoundPlayer.PlayUISound(GUISoundType.DropItem);
bool removed = false;
if (Screen.Selected is SubEditorScreen editor)
{
if (editor.EntityMenu.Rect.Contains(PlayerInput.MousePosition))
{
DraggingItems.ForEachMod(it => it.Remove());
removed = true;
}
else
{
if (editor.WiringMode)
{
DraggingItems.ForEachMod(it => it.Remove());
removed = true;
}
else
{
if (editor.WiringMode)
{
DraggingItems.ForEachMod(it => it.Remove());
removed = true;
}
else
{
DraggingItems.ForEachMod(it => it.Drop(Character.Controlled));
}
DraggingItems.ForEachMod(it => it.Drop(Character.Controlled));
}
}
else
{
DraggingItems.ForEachMod(it => it.Drop(Character.Controlled));
DraggingItems.First().CreateDroppedStack(DraggingItems, allowClientExecute: false);
}
SoundPlayer.PlayUISound(removed ? GUISoundType.PickItem : GUISoundType.DropItem);
}
}
else if (!DraggingItems.Any(it => selectedSlot.ParentInventory.slots[selectedSlot.SlotIndex].Contains(it)))
{
Inventory oldInventory = DraggingItems.First().ParentInventory;
Inventory selectedInventory = selectedSlot.ParentInventory;
int slotIndex = selectedSlot.SlotIndex;
int oldSlot = oldInventory == null ? 0 : Array.IndexOf(oldInventory.slots, DraggingItems);
//if attempting to drop into an invalid slot in the same inventory, try to move to the correct slot
if (selectedInventory.slots[slotIndex].Empty() &&
selectedInventory == Character.Controlled.Inventory &&
!DraggingItems.First().AllowedSlots.Any(a => a.HasFlag(Character.Controlled.Inventory.SlotTypes[slotIndex])) &&
DraggingItems.Any(it => selectedInventory.TryPutItem(it, Character.Controlled, it.AllowedSlots)))
else
{
if (selectedInventory.visualSlots != null)
DraggingItems.ForEachMod(it => it.Drop(Character.Controlled));
DraggingItems.First().CreateDroppedStack(DraggingItems, allowClientExecute: false);
}
SoundPlayer.PlayUISound(removed ? GUISoundType.PickItem : GUISoundType.DropItem);
}
}
void HandleInventorySlotDrop()
{
Inventory oldInventory = DraggingItems.First().ParentInventory;
Inventory selectedInventory = selectedSlot.ParentInventory;
int slotIndex = selectedSlot.SlotIndex;
int oldSlot = oldInventory == null ? 0 : Array.IndexOf(oldInventory.slots, DraggingItems);
//if attempting to drop into an invalid slot in the same inventory, try to move to the correct slot
if (selectedInventory.slots[slotIndex].Empty() &&
selectedInventory == Character.Controlled.Inventory &&
!DraggingItems.First().AllowedSlots.Any(a => a.HasFlag(Character.Controlled.Inventory.SlotTypes[slotIndex])) &&
DraggingItems.Any(it => selectedInventory.TryPutItem(it, Character.Controlled, it.AllowedSlots)))
{
if (selectedInventory.visualSlots != null)
{
for (int i = 0; i < selectedInventory.visualSlots.Length; i++)
{
for (int i = 0; i < selectedInventory.visualSlots.Length; i++)
if (DraggingItems.Any(it => selectedInventory.slots[i].Contains(it)))
{
if (DraggingItems.Any(it => selectedInventory.slots[i].Contains(it)))
selectedInventory.visualSlots[slotIndex].ShowBorderHighlight(Color.White, 0.1f, 0.4f);
}
}
selectedInventory.visualSlots[slotIndex].ShowBorderHighlight(GUIStyle.Red, 0.1f, 0.9f);
}
SoundPlayer.PlayUISound(GUISoundType.PickItem);
}
else
{
bool anySuccess = false;
//if we're dragging a stack of partial items or trying to drag to a stack of partial items
//(which should not normally exist, but can happen when e.g. fire damages a stack of items)
//don't allow combining because it leads to weird behavior (stack of items of mixed quality)
bool allowCombine = !(DraggingItems.Count(it => !it.IsFullCondition && it.Condition > 0.0f) > 1 ||
selectedInventory.GetItemsAt(slotIndex).Count(it => !it.IsFullCondition && it.Condition > 0.0f) > 1);
int itemCount = 0;
foreach (Item item in DraggingItems)
{
if (selectedInventory.GetItemAt(slotIndex)?.OwnInventory?.Container is { } container &&
container.Inventory.CanBePut(item))
{
if (!container.AllowDragAndDrop || !container.AllowAccess)
{
allowCombine = false;
}
}
bool success = selectedInventory.TryPutItem(item, slotIndex, allowSwapping: !anySuccess, allowCombine, Character.Controlled);
if (success)
{
anySuccess = true;
itemCount++;
}
if (!success || itemCount >= item.Prefab.GetMaxStackSize(selectedInventory))
{
break;
}
}
if (anySuccess)
{
highlightedSubInventorySlots.RemoveWhere(s => s.ParentInventory == oldInventory || s.ParentInventory == selectedInventory);
if (SubEditorScreen.IsSubEditor())
{
foreach (Item draggingItem in DraggingItems)
{
if (selectedInventory.slots[slotIndex].Contains(draggingItem))
{
selectedInventory.visualSlots[slotIndex].ShowBorderHighlight(Color.White, 0.1f, 0.4f);
SubEditorScreen.StoreCommand(new InventoryMoveCommand(oldInventory, selectedInventory, draggingItem, oldSlot, slotIndex));
}
}
selectedInventory.visualSlots[slotIndex].ShowBorderHighlight(GUIStyle.Red, 0.1f, 0.9f);
}
if (selectedInventory.visualSlots != null) { selectedInventory.visualSlots[slotIndex].ShowBorderHighlight(Color.White, 0.1f, 0.4f); }
SoundPlayer.PlayUISound(GUISoundType.PickItem);
}
else
{
bool anySuccess = false;
bool allowCombine = true;
//if we're dragging a stack of partial items or trying to drag to a stack of partial items
//(which should not normally exist, but can happen when e.g. fire damages a stack of items)
//don't allow combining because it leads to weird behavior (stack of items of mixed quality)
if (DraggingItems.Count(it => !it.IsFullCondition && it.Condition > 0.0f) > 1 ||
selectedInventory.GetItemsAt(slotIndex).Count(it => !it.IsFullCondition && it.Condition > 0.0f) > 1)
{
allowCombine = false;
}
int itemCount = 0;
foreach (Item item in DraggingItems)
{
if (selectedInventory.GetItemAt(slotIndex)?.OwnInventory?.Container is { } container &&
container.Inventory.CanBePut(item))
{
if (!container.AllowDragAndDrop || !container.AllowAccess)
{
allowCombine = false;
}
}
bool success = selectedInventory.TryPutItem(item, slotIndex, allowSwapping: !anySuccess, allowCombine, Character.Controlled);
if (success)
{
anySuccess = true;
itemCount++;
}
if (!success || itemCount >= item.Prefab.GetMaxStackSize(selectedInventory))
{
break;
}
}
if (anySuccess)
{
highlightedSubInventorySlots.RemoveWhere(s => s.ParentInventory == oldInventory || s.ParentInventory == selectedInventory);
if (SubEditorScreen.IsSubEditor())
{
foreach (Item draggingItem in DraggingItems)
{
if (selectedInventory.slots[slotIndex].Contains(draggingItem))
{
SubEditorScreen.StoreCommand(new InventoryMoveCommand(oldInventory, selectedInventory, draggingItem, oldSlot, slotIndex));
}
}
}
if (selectedInventory.visualSlots != null) { selectedInventory.visualSlots[slotIndex].ShowBorderHighlight(Color.White, 0.1f, 0.4f); }
SoundPlayer.PlayUISound(GUISoundType.PickItem);
}
else
{
if (selectedInventory.visualSlots != null){ selectedInventory.visualSlots[slotIndex].ShowBorderHighlight(GUIStyle.Red, 0.1f, 0.9f); }
SoundPlayer.PlayUISound(GUISoundType.PickItemFail);
}
if (selectedInventory.visualSlots != null){ selectedInventory.visualSlots[slotIndex].ShowBorderHighlight(GUIStyle.Red, 0.1f, 0.9f); }
SoundPlayer.PlayUISound(GUISoundType.PickItemFail);
}
selectedInventory.HideTimer = 2.0f;
if (selectedSlot.ParentInventory?.Owner is Item parentItem && parentItem.ParentInventory != null)
{
for (int i = 0; i < parentItem.ParentInventory.capacity; i++)
{
if (parentItem.ParentInventory.HideSlot(i)) { continue; }
if (parentItem.ParentInventory.slots[i].FirstOrDefault() != parentItem) { continue; }
highlightedSubInventorySlots.Add(new SlotReference(
parentItem.ParentInventory, parentItem.ParentInventory.visualSlots[i],
i, false, selectedSlot.ParentInventory));
break;
}
}
DraggingItems.Clear();
DraggingSlot = null;
}
DraggingItems.Clear();
}
selectedInventory.HideTimer = 2.0f;
if (selectedSlot.ParentInventory?.Owner is Item parentItem && parentItem.ParentInventory != null)
{
for (int i = 0; i < parentItem.ParentInventory.capacity; i++)
{
if (parentItem.ParentInventory.HideSlot(i)) { continue; }
if (parentItem.ParentInventory.slots[i].FirstOrDefault() != parentItem) { continue; }
if (selectedSlot != null && !CanSelectSlot(selectedSlot))
{
selectedSlot = null;
}
highlightedSubInventorySlots.Add(new SlotReference(
parentItem.ParentInventory, parentItem.ParentInventory.visualSlots[i],
i, false, selectedSlot.ParentInventory));
break;
}
}
DraggingItems.Clear();
DraggingSlot = null;
}
}
private static bool IsValidTargetForDragDropGive(Character giver, Character receiver)
{
if (giver == null || receiver == null) { return false; }
if (receiver == giver) { return false; }
return receiver.IsInventoryAccessibleTo(giver, IsDragAndDropGiveAllowed ? CharacterInventory.AccessLevel.Allowed : CharacterInventory.AccessLevel.Limited);
}
private static bool CanSelectSlot(SlotReference selectedSlot)
@@ -1504,6 +1542,31 @@ namespace Barotrauma
}
if (DraggingItems.Any())
{
DrawDragRelated();
}
if (selectedSlot != null && selectedSlot.Item != null)
{
Rectangle slotRect = selectedSlot.Slot.Rect;
slotRect.Location += selectedSlot.Slot.DrawOffset.ToPoint();
if (selectedSlot.TooltipNeedsRefresh())
{
selectedSlot.RefreshTooltip();
}
if (!slotIconTooltip.IsNullOrEmpty())
{
DrawToolTip(spriteBatch, slotIconTooltip, slotRect);
}
else
{
DrawToolTip(spriteBatch, selectedSlot.Tooltip, slotRect);
}
slotIconTooltip = string.Empty;
}
void DrawDragRelated()
{
if (DraggingSlot == null || (!DraggingSlot.MouseOn()))
{
@@ -1521,10 +1584,8 @@ namespace Barotrauma
if ((GUI.MouseOn == null || mouseOnHealthInterface) && selectedSlot == null)
{
var shadowSprite = GUIStyle.GetComponentStyle("OuterGlow").Sprites[GUIComponent.ComponentState.None][0];
LocalizedString toolTip = mouseOnHealthInterface ? TextManager.Get("QuickUseAction.UseTreatment") :
Character.Controlled.FocusedItem != null ?
TextManager.GetWithVariable("PutItemIn", "[itemname]", Character.Controlled.FocusedItem.Name, FormatCapitals.Yes) :
TextManager.Get(Screen.Selected is SubEditorScreen editor && editor.EntityMenu.Rect.Contains(PlayerInput.MousePosition) ? "Delete" : "DropItem");
(LocalizedString toolTip, Color toolTipColor) = GetDragLabelTextAndColor(mouseOnHealthInterface);
Vector2 nameSize = GUIStyle.Font.MeasureString(DraggingItems.First().Name);
Vector2 toolTipSize = GUIStyle.SmallFont.MeasureString(toolTip);
@@ -1544,7 +1605,7 @@ namespace Barotrauma
GUI.DrawString(spriteBatch, textPos + new Vector2(nameSize.X * textOffset, -iconSize / 2), DraggingItems.First().Name, Color.White);
GUI.DrawString(spriteBatch, textPos + new Vector2(toolTipSize.X * textOffset, 0), toolTip,
color: Character.Controlled.FocusedItem == null && !mouseOnHealthInterface ? GUIStyle.Red : Color.LightGreen,
color: toolTipColor,
font: GUIStyle.SmallFont);
}
@@ -1587,24 +1648,31 @@ namespace Barotrauma
}
}
if (selectedSlot != null && selectedSlot.Item != null)
(LocalizedString, Color) GetDragLabelTextAndColor(bool mouseOnHealthInterface)
{
Rectangle slotRect = selectedSlot.Slot.Rect;
slotRect.Location += selectedSlot.Slot.DrawOffset.ToPoint();
if (selectedSlot.TooltipNeedsRefresh())
bool useDragDropGive = IsValidTargetForDragDropGive(Character.Controlled, Character.Controlled.FocusedCharacter);
Color toolTipColor = Color.LightGreen;
LocalizedString toolTip;
if (mouseOnHealthInterface)
{
selectedSlot.RefreshTooltip();
toolTip = TextManager.Get("QuickUseAction.UseTreatment");
}
if (!slotIconTooltip.IsNullOrEmpty())
else if (Character.Controlled.FocusedItem != null)
{
DrawToolTip(spriteBatch, slotIconTooltip, slotRect);
toolTip = TextManager.GetWithVariable("PutItemIn", "[itemname]", Character.Controlled.FocusedItem.Name, FormatCapitals.Yes);
}
else if (useDragDropGive)
{
toolTip = TextManager.GetWithVariable("GiveItemTo", "[character]", Character.Controlled.FocusedCharacter.Name, FormatCapitals.Yes);
}
else
{
DrawToolTip(spriteBatch, selectedSlot.Tooltip, slotRect);
toolTipColor = GUIStyle.Red;
toolTip = TextManager.Get(Screen.Selected is SubEditorScreen editor && editor.EntityMenu.Rect.Contains(PlayerInput.MousePosition) ? "Delete" : "DropItem");
}
slotIconTooltip = string.Empty;
return (toolTip, toolTipColor);
}
}
@@ -1801,7 +1869,7 @@ namespace Barotrauma
DrawSideIcon(deconstructOrder.SymbolSprite, Direction.Right, TextManager.Get("tooltip.markedfordeconstruction"), GUIStyle.Red, out bool mouseOn);
if (mouseOn) { availableContextualOrder = (item, Tags.DontDeconstructThis); }
}
else if (((item.SpawnedInCurrentOutpost && !item.AllowStealing) || (inventory != null && inventory.slots[slotIndex].Items.Any(it => it.SpawnedInCurrentOutpost && !it.AllowStealing))) && CharacterInventory.LimbSlotIcons.ContainsKey(InvSlotType.LeftHand))
else if ((item.Illegitimate || (inventory != null && inventory.slots[slotIndex].Items.Any(it => it.Illegitimate))) && CharacterInventory.LimbSlotIcons.ContainsKey(InvSlotType.LeftHand))
{
DrawSideIcon(CharacterInventory.LimbSlotIcons[InvSlotType.LeftHand], Direction.Left, TextManager.Get("tooltip.stolenitem"), GUIStyle.Red, out _);
}
@@ -326,7 +326,7 @@ namespace Barotrauma
public void Draw(SpriteBatch spriteBatch, bool editing, bool back = true, Color? overrideColor = null)
{
if (!Visible || (!editing && HiddenInGame) || !SubEditorScreen.IsLayerVisible(this)) { return; }
if (!Visible || (!editing && IsHidden) || !SubEditorScreen.IsLayerVisible(this)) { return; }
if (editing)
{
@@ -424,7 +424,7 @@ namespace Barotrauma
textureScale: Vector2.One * Scale,
depth: d);
}
DrawDecorativeSprites(spriteBatch, DrawPosition, flippedX && Prefab.CanSpriteFlipX, flippedY && Prefab.CanSpriteFlipY, rotation: 0, depth);
DrawDecorativeSprites(spriteBatch, DrawPosition, flippedX && Prefab.CanSpriteFlipX, flippedY && Prefab.CanSpriteFlipY, rotation: 0, depth, overrideColor);
}
}
else
@@ -445,7 +445,7 @@ namespace Barotrauma
Prefab.DamagedInfectedSprite?.Draw(spriteBatch, new Vector2(DrawPosition.X, -DrawPosition.Y) + drawOffset, Infector.HealthColor, Prefab.DamagedInfectedSprite.Origin, RotationRad, Scale, activeSprite.effects, depth - 0.002f);
}
DrawDecorativeSprites(spriteBatch, DrawPosition, flippedX && Prefab.CanSpriteFlipX, flippedY && Prefab.CanSpriteFlipY, -RotationRad, depth);
DrawDecorativeSprites(spriteBatch, DrawPosition, flippedX && Prefab.CanSpriteFlipX, flippedY && Prefab.CanSpriteFlipY, -RotationRad, depth, overrideColor);
}
}
else if (body.Enabled)
@@ -456,30 +456,49 @@ namespace Barotrauma
//don't draw the item on hands if it's also being worn
if (GetComponent<Wearable>() is { IsActive: true }) { return; }
if (!back) { return; }
float depthStep = 0.000001f;
if (holdable.Picker.Inventory?.GetItemInLimbSlot(InvSlotType.RightHand) == this)
{
Limb holdLimb = holdable.Picker.AnimController.GetLimb(LimbType.RightArm);
if (holdLimb?.ActiveSprite != null)
{
depth = holdLimb.ActiveSprite.Depth + holdable.Picker.AnimController.GetDepthOffset() + depthStep * 2;
foreach (WearableSprite wearableSprite in holdLimb.WearingItems)
{
if (!wearableSprite.InheritLimbDepth && wearableSprite.Sprite != null) { depth = Math.Max(wearableSprite.Sprite.Depth + depthStep, depth); }
}
}
depth = GetHeldItemDepth(LimbType.RightHand, depth);
}
else if (holdable.Picker.Inventory?.GetItemInLimbSlot(InvSlotType.LeftHand) == this)
{
Limb holdLimb = holdable.Picker.AnimController.GetLimb(LimbType.LeftArm);
depth = GetHeldItemDepth(LimbType.LeftHand, depth);
}
float GetHeldItemDepth(LimbType limb, float depth)
{
//offset used to make sure the item draws just slightly behind the right hand, or slightly in front of the left hand
float limbDepthOffset = 0.000001f;
float depthOffset = holdable.Picker.AnimController.GetDepthOffset();
//use the upper arm as a reference, to ensure the item gets drawn behind / in front of the whole arm (not just the forearm)
Limb holdLimb = holdable.Picker.AnimController.GetLimb(limb == LimbType.RightHand ? LimbType.RightArm : LimbType.LeftArm);
if (holdLimb?.ActiveSprite != null)
{
depth = holdLimb.ActiveSprite.Depth + holdable.Picker.AnimController.GetDepthOffset() - depthStep * 2;
depth =
holdLimb.ActiveSprite.Depth
+ depthOffset
+ limbDepthOffset * 2 * (limb == LimbType.RightHand ? 1 : -1);
foreach (WearableSprite wearableSprite in holdLimb.WearingItems)
{
if (!wearableSprite.InheritLimbDepth && wearableSprite.Sprite != null) { depth = Math.Min(wearableSprite.Sprite.Depth - depthStep, depth); }
if (!wearableSprite.InheritLimbDepth && wearableSprite.Sprite != null)
{
depth =
limb == LimbType.RightHand ?
Math.Max(wearableSprite.Sprite.Depth + limbDepthOffset, depth) :
Math.Min(wearableSprite.Sprite.Depth - limbDepthOffset, depth);
}
}
var head = holdable.Picker.AnimController.GetLimb(LimbType.Head);
if (head != null)
{
//ensure the holdable item is always drawn in front of the head no matter what the wearables or whatnot do with the sprite depths
depth =
limb == LimbType.RightHand ?
Math.Min(head.Sprite.Depth + depthOffset - limbDepthOffset, depth) :
Math.Max(head.Sprite.Depth + depthOffset + limbDepthOffset, depth);
}
}
return depth;
}
}
Vector2 origin = GetSpriteOrigin(activeSprite);
@@ -489,7 +508,7 @@ namespace Barotrauma
float d = Math.Min(depth + (fadeInBrokenSprite.Sprite.Depth - activeSprite.Depth - 0.000001f), 0.999f);
body.Draw(spriteBatch, fadeInBrokenSprite.Sprite, color * fadeInBrokenSpriteAlpha, d, Scale);
}
DrawDecorativeSprites(spriteBatch, body.DrawPosition, flipX: body.Dir < 0, flipY: false, rotation: body.Rotation, depth: depth);
DrawDecorativeSprites(spriteBatch, body.DrawPosition, flipX: body.Dir < 0, flipY: false, rotation: body.Rotation, depth, overrideColor);
}
foreach (var upgrade in Upgrades)
@@ -617,11 +636,11 @@ namespace Barotrauma
}
}
public void DrawDecorativeSprites(SpriteBatch spriteBatch, Vector2 drawPos, bool flipX, bool flipY, float rotation, float depth)
public void DrawDecorativeSprites(SpriteBatch spriteBatch, Vector2 drawPos, bool flipX, bool flipY, float rotation, float depth, Color? overrideColor = null)
{
foreach (var decorativeSprite in Prefab.DecorativeSprites)
{
Color decorativeSpriteColor = GetSpriteColor(decorativeSprite.Color).Multiply(GetSpriteColor(spriteColor));
Color decorativeSpriteColor = overrideColor ?? GetSpriteColor(decorativeSprite.Color).Multiply(GetSpriteColor(spriteColor));
if (!spriteAnimState[decorativeSprite].IsActive) { continue; }
Vector2 offset = decorativeSprite.GetOffset(ref spriteAnimState[decorativeSprite].OffsetState, spriteAnimState[decorativeSprite].RandomOffsetMultiplier,