Unstable 1.8.4.0
This commit is contained in:
@@ -184,6 +184,13 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
shakePos = Vector2.Zero;
|
||||
}
|
||||
if (Character.Controlled is Character character && character.FocusedItem == item)
|
||||
{
|
||||
if ((IsFullyOpen || IsFullyClosed) && MathF.Abs(openState - lastOpenState) > 0)
|
||||
{
|
||||
CharacterHUD.RecreateHudTexts = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Draw(SpriteBatch spriteBatch, bool editing, float itemDepth = -1, Color? overrideColor = null)
|
||||
|
||||
@@ -14,6 +14,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public override void AddTooltipInfo(ref LocalizedString name, ref LocalizedString description)
|
||||
{
|
||||
bool mergedMaterialTainted = false;
|
||||
if (!materialName.IsNullOrEmpty() && item.ContainedItems.Count() > 0)
|
||||
{
|
||||
LocalizedString mergedMaterialName = materialName;
|
||||
@@ -22,11 +23,15 @@ namespace Barotrauma.Items.Components
|
||||
var containedMaterial = containedItem.GetComponent<GeneticMaterial>();
|
||||
if (containedMaterial == null) { continue; }
|
||||
mergedMaterialName += ", " + containedMaterial.materialName;
|
||||
if (containedMaterial.Tainted)
|
||||
{
|
||||
mergedMaterialTainted = true;
|
||||
}
|
||||
}
|
||||
name = name.Replace(materialName, mergedMaterialName);
|
||||
}
|
||||
|
||||
if (Tainted)
|
||||
if (Tainted || mergedMaterialTainted)
|
||||
{
|
||||
name = TextManager.GetWithVariable("entityname.taintedgeneticmaterial", "[geneticmaterialname]", name);
|
||||
}
|
||||
@@ -48,25 +53,46 @@ namespace Barotrauma.Items.Components
|
||||
description += '\n' + containedDescription;
|
||||
}
|
||||
}
|
||||
|
||||
if (GameMain.DevMode && Tainted && selectedTaintedEffect != null)
|
||||
{
|
||||
description = $"{description}\n{selectedTaintedEffect.Name}: {selectedTaintedEffect.GetDescription(0f, AfflictionPrefab.Description.TargetType.OtherCharacter)}";
|
||||
}
|
||||
}
|
||||
|
||||
public void ModifyDeconstructInfo(Deconstructor deconstructor, ref LocalizedString buttonText, ref LocalizedString infoText)
|
||||
{
|
||||
if (deconstructor.InputContainer.Inventory.AllItems.Count() == 2)
|
||||
{
|
||||
var otherGeneticMaterial =
|
||||
deconstructor.InputContainer.Inventory.AllItems.FirstOrDefault(it => it != item && it.Prefab == item.Prefab)?.GetComponent<GeneticMaterial>();
|
||||
var otherItem = deconstructor.InputContainer.Inventory.AllItems.FirstOrDefault(it => it != item);
|
||||
if (otherItem == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var otherGeneticMaterial = otherItem.GetComponent<GeneticMaterial>();
|
||||
if (otherGeneticMaterial == null)
|
||||
{
|
||||
buttonText = TextManager.Get("researchstation.combine");
|
||||
infoText = TextManager.Get("researchstation.combine.infotext");
|
||||
return;
|
||||
}
|
||||
else
|
||||
|
||||
var combineRefineResult = GetCombineRefineResult(otherGeneticMaterial);
|
||||
|
||||
if (combineRefineResult == CombineResult.None)
|
||||
{
|
||||
infoText = TextManager.Get("researchstation.novalidcombination");
|
||||
}
|
||||
else if (combineRefineResult == CombineResult.Refined)
|
||||
{
|
||||
buttonText = TextManager.Get("researchstation.refine");
|
||||
int taintedProbability = (int)(GetTaintedProbabilityOnRefine(otherGeneticMaterial, Character.Controlled) * 100);
|
||||
infoText = TextManager.GetWithVariable("researchstation.refine.infotext", "[taintedprobability]", taintedProbability.ToString());
|
||||
}
|
||||
else
|
||||
{
|
||||
buttonText = TextManager.Get("researchstation.combine");
|
||||
infoText = TextManager.Get("researchstation.combine.infotext");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -71,13 +71,13 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
|
||||
public override bool ValidateEventData(NetEntityEvent.IData data)
|
||||
=> TryExtractEventData<EventData>(data, out _);
|
||||
=> TryExtractEventData<AttachEventData>(data, out _);
|
||||
|
||||
public void ClientEventWrite(IWriteMessage msg, NetEntityEvent.IData extraData = null)
|
||||
{
|
||||
if (!attachable || body == null) { return; }
|
||||
|
||||
var eventData = ExtractEventData<EventData>(extraData);
|
||||
var eventData = ExtractEventData<AttachEventData>(extraData);
|
||||
|
||||
Vector2 attachPos = eventData.AttachPos;
|
||||
msg.WriteSingle(attachPos.X);
|
||||
@@ -94,7 +94,9 @@ namespace Barotrauma.Items.Components
|
||||
bool shouldBeAttached = msg.ReadBoolean();
|
||||
Vector2 simPosition = new Vector2(msg.ReadSingle(), msg.ReadSingle());
|
||||
UInt16 submarineID = msg.ReadUInt16();
|
||||
UInt16 attacherID = msg.ReadUInt16();
|
||||
Submarine sub = Entity.FindEntityByID(submarineID) as Submarine;
|
||||
Character attacher = Entity.FindEntityByID(attacherID) as Character;
|
||||
|
||||
if (shouldBeAttached)
|
||||
{
|
||||
@@ -104,6 +106,8 @@ namespace Barotrauma.Items.Components
|
||||
item.SetTransform(simPosition, 0.0f);
|
||||
item.Submarine = sub;
|
||||
AttachToWall();
|
||||
PlaySound(ActionType.OnUse, attacher);
|
||||
ApplyStatusEffects(ActionType.OnUse, (float)Timing.Step, character: attacher, user: attacher);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
+15
-20
@@ -34,6 +34,8 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
private Vector2 _chargeSoundWindupPitchSlide;
|
||||
|
||||
public Vector2 BarrelScreenPos => Screen.Selected.Cam.WorldToScreen(item.DrawPosition + ConvertUnits.ToDisplayUnits(TransformedBarrelPos));
|
||||
|
||||
private readonly List<ParticleEmitter> particleEmitters = new List<ParticleEmitter>();
|
||||
private readonly List<ParticleEmitter> particleEmitterCharges = new List<ParticleEmitter>();
|
||||
|
||||
@@ -86,28 +88,19 @@ namespace Barotrauma.Items.Components
|
||||
currentCrossHairScale = currentCrossHairPointerScale = cam == null ? 1.0f : cam.Zoom;
|
||||
if (crosshairSprite != null)
|
||||
{
|
||||
Vector2 aimRefWorldPos = character.AimRefPosition;
|
||||
if (character.Submarine != null) { aimRefWorldPos += character.Submarine.Position; }
|
||||
Vector2 itemPos = cam.WorldToScreen(aimRefWorldPos);
|
||||
float rotation = (item.body.Dir == 1.0f) ? item.body.Rotation : item.body.Rotation - MathHelper.Pi;
|
||||
Vector2 barrelDir = new Vector2((float)Math.Cos(rotation), -(float)Math.Sin(rotation));
|
||||
|
||||
Vector2 mouseDiff = itemPos - PlayerInput.MousePosition;
|
||||
crosshairPos = new Vector2(
|
||||
MathHelper.Clamp(itemPos.X + barrelDir.X * mouseDiff.Length(), 0, GameMain.GraphicsWidth),
|
||||
MathHelper.Clamp(itemPos.Y + barrelDir.Y * mouseDiff.Length(), 0, GameMain.GraphicsHeight));
|
||||
// Set position based on in-world aim
|
||||
Vector2 barrelDir = (MathF.Cos(item.body.TransformedRotation), -MathF.Sin(item.body.TransformedRotation));
|
||||
float mouseDist = Vector2.Distance(BarrelScreenPos, PlayerInput.MousePosition);
|
||||
crosshairPos = Vector2.Clamp(BarrelScreenPos + barrelDir * mouseDist, Vector2.Zero, (GameMain.GraphicsWidth, GameMain.GraphicsHeight));
|
||||
|
||||
// Resize pointer based on current spread
|
||||
float spread = GetSpread(character);
|
||||
Projectile projectile = FindProjectile();
|
||||
if (projectile != null)
|
||||
{
|
||||
spread += MathHelper.ToRadians(projectile.Spread);
|
||||
if (FindProjectile() is Projectile projectile)
|
||||
{
|
||||
spread += MathHelper.ToRadians(projectile.Spread);
|
||||
}
|
||||
|
||||
float crossHairDist = Vector2.Distance(item.WorldPosition, cam.ScreenToWorld(crosshairPos));
|
||||
float spreadDist = (float)Math.Sin(spread) * crossHairDist;
|
||||
|
||||
currentCrossHairPointerScale = MathHelper.Clamp(spreadDist / Math.Min(crosshairSprite.size.X, crosshairSprite.size.Y), 0.1f, 10.0f);
|
||||
float spreadAtRange = MathF.Sin(spread) * Vector2.Distance(BarrelScreenPos, crosshairPos);
|
||||
currentCrossHairPointerScale = MathHelper.Clamp(spreadAtRange / Math.Min(crosshairSprite.size.X, crosshairSprite.size.Y), 0.1f, 10f);
|
||||
}
|
||||
currentCrossHairScale *= CrossHairScale;
|
||||
crosshairPointerPos = PlayerInput.MousePosition;
|
||||
@@ -141,7 +134,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
if (chargeSound != null)
|
||||
{
|
||||
chargeSoundChannel = SoundPlayer.PlaySound(chargeSound.Sound, item.WorldPosition, chargeSound.Volume, chargeSound.Range, ignoreMuffling: chargeSound.IgnoreMuffling, freqMult: chargeSound.GetRandomFrequencyMultiplier());
|
||||
chargeSoundChannel = SoundPlayer.PlaySound(chargeSound, item.WorldPosition, hullGuess: item.CurrentHull);
|
||||
if (chargeSoundChannel != null) { chargeSoundChannel.Looping = true; }
|
||||
}
|
||||
}
|
||||
@@ -177,6 +170,8 @@ namespace Barotrauma.Items.Components
|
||||
//don't draw the crosshair if the item is in some other type of equip slot than hands (e.g. assault rifle in the bag slot)
|
||||
if (!character.HeldItems.Contains(item)) { return; }
|
||||
|
||||
base.DrawHUD(spriteBatch, character);
|
||||
|
||||
GUI.HideCursor = (crosshairSprite != null || crosshairPointerSprite != null) &&
|
||||
GUI.MouseOn == null && !Inventory.IsMouseOnInventory && !GameMain.Instance.Paused;
|
||||
|
||||
|
||||
@@ -216,6 +216,7 @@ namespace Barotrauma.Items.Components
|
||||
public override void DrawHUD(SpriteBatch spriteBatch, Character character)
|
||||
{
|
||||
if (character == null || !character.IsKeyDown(InputType.Aim)) { return; }
|
||||
base.DrawHUD(spriteBatch, character);
|
||||
GUI.HideCursor = targetSections.Count > 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -62,6 +62,10 @@ namespace Barotrauma.Items.Components
|
||||
private readonly Dictionary<ActionType, List<ItemSound>> sounds;
|
||||
private Dictionary<ActionType, SoundSelectionMode> soundSelectionModes;
|
||||
|
||||
/// <summary>
|
||||
/// Starts the timer for delayed client-side corrections (<see cref="StartDelayedCorrection(IReadMessage, float, bool)"/>) - in other words,
|
||||
/// the client will not attempt to read server updates for this component until the timer elapses.
|
||||
/// </summary>
|
||||
protected float correctionTimer;
|
||||
|
||||
public float IsActiveTimer;
|
||||
@@ -150,6 +154,17 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public GUIFrame GuiFrame { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Overlay (just a non-interactable sprite) drawn when the item is selected, equipped or focused to via Controllers (e.g. when operating a turret via a periscope or a camera via a monitor).
|
||||
/// </summary>
|
||||
public Sprite HUDOverlay { get; set; }
|
||||
|
||||
public float HUDOverlayAnimSpeed
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
private GUIDragHandle guiFrameDragHandle;
|
||||
|
||||
private bool guiFrameUpdatePending;
|
||||
@@ -161,6 +176,13 @@ namespace Barotrauma.Items.Components
|
||||
set;
|
||||
}
|
||||
|
||||
[Serialize(true, IsPropertySaveable.No)]
|
||||
public bool CloseByClickingOutsideGUIFrame
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
private ItemComponent linkToUIComponent;
|
||||
[Serialize("", IsPropertySaveable.No)]
|
||||
public string LinkUIToComponent
|
||||
@@ -261,7 +283,7 @@ namespace Barotrauma.Items.Components
|
||||
if (GameMain.Client?.MidRoundSyncing ?? false) { return; }
|
||||
|
||||
//above the top boundary of the level (in an inactive respawn shuttle?)
|
||||
if (item.Submarine != null && Level.Loaded != null && item.Submarine.WorldPosition.Y > Level.Loaded.Size.Y)
|
||||
if (item.Submarine != null && item.Submarine.IsAboveLevel)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -294,11 +316,13 @@ namespace Barotrauma.Items.Components
|
||||
0.01f,
|
||||
loopingSound.RoundSound.GetRandomFrequencyMultiplier(),
|
||||
SoundPlayer.ShouldMuffleSound(Character.Controlled, item.WorldPosition, loopingSound.Range, Character.Controlled?.CurrentHull));
|
||||
loopingSoundChannel.Looping = true;
|
||||
item.CheckNeedsSoundUpdate(this);
|
||||
//TODO: tweak
|
||||
loopingSoundChannel.Near = loopingSound.Range * 0.4f;
|
||||
loopingSoundChannel.Far = loopingSound.Range;
|
||||
if (loopingSoundChannel != null)
|
||||
{
|
||||
loopingSoundChannel.Looping = true;
|
||||
item.CheckNeedsSoundUpdate(this);
|
||||
loopingSoundChannel.Near = loopingSound.Range * 0.4f;
|
||||
loopingSoundChannel.Far = loopingSound.Range;
|
||||
}
|
||||
}
|
||||
|
||||
// Looping sound with manual selection mode should be changed if value of ManuallySelectedSound has changed
|
||||
@@ -340,7 +364,7 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
else if (soundSelectionMode == SoundSelectionMode.Manual)
|
||||
{
|
||||
index = Math.Clamp(ManuallySelectedSound, 0, matchingSounds.Count);
|
||||
index = Math.Clamp(ManuallySelectedSound, 0, matchingSounds.Count - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -374,22 +398,20 @@ namespace Barotrauma.Items.Components
|
||||
float volume = GetSoundVolume(itemSound);
|
||||
if (volume <= 0.0001f) { return; }
|
||||
loopingSound = itemSound;
|
||||
loopingSoundChannel = loopingSound.RoundSound.Sound.Play(
|
||||
new Vector3(position.X, position.Y, 0.0f),
|
||||
0.01f,
|
||||
freqMult: itemSound.RoundSound.GetRandomFrequencyMultiplier(),
|
||||
muffle: SoundPlayer.ShouldMuffleSound(Character.Controlled, position, loopingSound.Range, Character.Controlled?.CurrentHull));
|
||||
loopingSoundChannel.Looping = true;
|
||||
//TODO: tweak
|
||||
loopingSoundChannel.Near = loopingSound.Range * 0.4f;
|
||||
loopingSoundChannel.Far = loopingSound.Range;
|
||||
loopingSoundChannel = SoundPlayer.PlaySound(loopingSound.RoundSound, position, volume: 0.01f, hullGuess: item.CurrentHull);
|
||||
if (loopingSoundChannel != null)
|
||||
{
|
||||
loopingSoundChannel.Looping = true;
|
||||
loopingSoundChannel.Near = loopingSound.Range * 0.4f;
|
||||
loopingSoundChannel.Far = loopingSound.Range;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
float volume = GetSoundVolume(itemSound);
|
||||
if (volume <= 0.0001f) { return; }
|
||||
var channel = SoundPlayer.PlaySound(itemSound.RoundSound.Sound, position, volume, itemSound.Range, itemSound.RoundSound.GetRandomFrequencyMultiplier(), item.CurrentHull, ignoreMuffling: itemSound.RoundSound.IgnoreMuffling);
|
||||
var channel = SoundPlayer.PlaySound(itemSound.RoundSound, position, volume, hullGuess: item.CurrentHull);
|
||||
if (channel != null) { playingOneshotSoundChannels.Add(channel); }
|
||||
}
|
||||
}
|
||||
@@ -416,12 +438,23 @@ namespace Barotrauma.Items.Components
|
||||
if (sound == null) { return 0.0f; }
|
||||
if (sound.VolumeProperty == "") { return sound.VolumeMultiplier; }
|
||||
|
||||
if (SerializableProperties.TryGetValue(sound.VolumeProperty, out SerializableProperty property))
|
||||
SerializableProperty property = null;
|
||||
ISerializableEntity targetEntity = null;
|
||||
if (SerializableProperties.TryGetValue(sound.VolumeProperty, out property))
|
||||
{
|
||||
targetEntity = this;
|
||||
}
|
||||
else if (Item.SerializableProperties.TryGetValue(sound.VolumeProperty, out property))
|
||||
{
|
||||
targetEntity = Item;
|
||||
}
|
||||
|
||||
if (property != null)
|
||||
{
|
||||
float newVolume;
|
||||
try
|
||||
{
|
||||
newVolume = property.GetFloatValue(this);
|
||||
newVolume = property.GetFloatValue(targetEntity);
|
||||
}
|
||||
catch
|
||||
{
|
||||
@@ -470,7 +503,24 @@ namespace Barotrauma.Items.Components
|
||||
return linkToUIComponent;
|
||||
}
|
||||
|
||||
public virtual void DrawHUD(SpriteBatch spriteBatch, Character character) { }
|
||||
public virtual void DrawHUD(SpriteBatch spriteBatch, Character character)
|
||||
{
|
||||
if (HUDOverlay != null)
|
||||
{
|
||||
Vector2 screenSize = new Vector2(GameMain.GraphicsWidth, GameMain.GraphicsHeight);
|
||||
if (HUDOverlay is SpriteSheet spriteSheet)
|
||||
{
|
||||
spriteSheet.Draw(spriteBatch,
|
||||
spriteIndex: (int)(Math.Floor(Timing.TotalTimeUnpaused * HUDOverlayAnimSpeed) % spriteSheet.FrameCount),
|
||||
pos: screenSize / 2, color: Color.White, origin: HUDOverlay.Origin, rotate: 0, scale: screenSize / spriteSheet.FrameSize.ToVector2());
|
||||
}
|
||||
else
|
||||
{
|
||||
HUDOverlay.Draw(spriteBatch,
|
||||
pos: screenSize / 2, color: Color.White, origin: HUDOverlay.Origin, rotate: 0, scale: screenSize / HUDOverlay.size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void AddToGUIUpdateList(int order = 0)
|
||||
{
|
||||
@@ -513,6 +563,13 @@ namespace Barotrauma.Items.Components
|
||||
GuiFrameSource = subElement;
|
||||
ReloadGuiFrame();
|
||||
break;
|
||||
case "hudoverlayanimated":
|
||||
HUDOverlay = new SpriteSheet(subElement);
|
||||
HUDOverlayAnimSpeed = subElement.GetAttributeFloat("animspeed", 1.0f);
|
||||
break;
|
||||
case "hudoverlay":
|
||||
HUDOverlay = new Sprite(subElement);
|
||||
break;
|
||||
case "alternativelayout":
|
||||
AlternativeLayout = GUILayoutSettings.Load(subElement);
|
||||
break;
|
||||
@@ -687,6 +744,9 @@ namespace Barotrauma.Items.Components
|
||||
}),
|
||||
new ContextMenuOption(TextManager.Get(LockGuiFramePosition ? "item.unlockuiposition" : "item.lockuiposition"), isEnabled: true, onSelected: () =>
|
||||
{
|
||||
//ensure the offset is set to where the frame is now
|
||||
//(it may have been repositioned by the overlap prevention logic, which doesn't set this offset)
|
||||
GuiFrameOffset = GuiFrame.RectTransform.ScreenSpaceOffset;
|
||||
LockGuiFramePosition = !LockGuiFramePosition;
|
||||
guiFrameDragHandle.Enabled = !LockGuiFramePosition;
|
||||
if (SerializableProperties.TryGetValue(nameof(LockGuiFramePosition).ToIdentifier(), out var property))
|
||||
@@ -711,7 +771,11 @@ namespace Barotrauma.Items.Components
|
||||
/// </summary>
|
||||
protected virtual void CreateGUI() { }
|
||||
|
||||
//Starts a coroutine that will read the correct state of the component from the NetBuffer when correctionTimer reaches zero.
|
||||
/// <summary>
|
||||
/// Starts a coroutine that will read the correct state of the component from the NetBuffer when correctionTimer reaches zero.
|
||||
/// Useful in cases where we a client is constantly adjusting some value, and we don't want state updates from the server to interfere with it
|
||||
/// (e.g. setting the value back to what a client just set it to, when the client has already modified the value further).
|
||||
/// </summary>
|
||||
protected void StartDelayedCorrection(IReadMessage buffer, float sendingTime, bool waitForMidRoundSync = false)
|
||||
{
|
||||
if (delayedCorrectionCoroutine != null) { CoroutineManager.StopCoroutines(delayedCorrectionCoroutine); }
|
||||
|
||||
@@ -458,54 +458,14 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public void DrawContainedItems(SpriteBatch spriteBatch, float itemDepth, Color? overrideColor = null)
|
||||
{
|
||||
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);
|
||||
var rootBody = item.RootContainer?.body ?? item.body;
|
||||
|
||||
if (item.body == null)
|
||||
{
|
||||
if (item.FlippedX)
|
||||
{
|
||||
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.RotationRad) > 0.01f)
|
||||
{
|
||||
Matrix transform = Matrix.CreateRotationZ(-item.RotationRad);
|
||||
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
|
||||
{
|
||||
Matrix transform = Matrix.CreateRotationZ(item.body.DrawRotation);
|
||||
if (item.body.Dir == -1.0f)
|
||||
{
|
||||
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.body.DrawPosition;
|
||||
}
|
||||
Vector2 transformedItemPos = GetContainedPosition(
|
||||
drawPosition: true,
|
||||
out Vector2 transformedItemIntervalHorizontal,
|
||||
out Vector2 transformedItemIntervalVertical,
|
||||
out bool flippedX,
|
||||
out bool flippedY);
|
||||
|
||||
Vector2 currentItemPos = transformedItemPos;
|
||||
|
||||
@@ -514,30 +474,41 @@ namespace Barotrauma.Items.Components
|
||||
int i = 0;
|
||||
foreach (ContainedItem contained in containedItems)
|
||||
{
|
||||
Vector2 itemPos = currentItemPos;
|
||||
|
||||
if (contained.Item?.Sprite == null) { continue; }
|
||||
|
||||
if (contained.Hide) { continue; }
|
||||
|
||||
Vector2 itemPos = transformedItemPos;
|
||||
int targetSlotIndex = ItemsUseInventoryPlacement ? Inventory.FindIndex(contained.Item) : i;
|
||||
//interval set on both axes -> use a grid layout
|
||||
if (Math.Abs(ItemInterval.X) > 0.001f && Math.Abs(ItemInterval.Y) > 0.001f)
|
||||
{
|
||||
itemPos += transformedItemIntervalHorizontal * (targetSlotIndex % ItemsPerRow);
|
||||
itemPos += transformedItemIntervalVertical * (targetSlotIndex / ItemsPerRow);
|
||||
}
|
||||
else
|
||||
{
|
||||
itemPos += (transformedItemIntervalHorizontal + transformedItemIntervalVertical) * targetSlotIndex;
|
||||
}
|
||||
|
||||
if (contained.ItemPos.HasValue)
|
||||
{
|
||||
Vector2 pos = contained.ItemPos.Value;
|
||||
if (item.body != null)
|
||||
{
|
||||
Matrix transform = Matrix.CreateRotationZ(item.body.DrawRotation);
|
||||
pos.X *= item.body.Dir;
|
||||
pos.X *= rootBody.Dir;
|
||||
itemPos = Vector2.Transform(pos, transform) + item.body.DrawPosition;
|
||||
}
|
||||
else
|
||||
{
|
||||
itemPos = pos;
|
||||
// This code is aped based on above. Not tested.
|
||||
if (item.FlippedX)
|
||||
if (flippedX)
|
||||
{
|
||||
itemPos.X = -itemPos.X;
|
||||
itemPos.X += item.Rect.Width;
|
||||
}
|
||||
if (item.FlippedY)
|
||||
if (flippedY)
|
||||
{
|
||||
itemPos.Y = -itemPos.Y;
|
||||
itemPos.Y -= item.Rect.Height;
|
||||
@@ -555,15 +526,15 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
if (AutoInteractWithContained)
|
||||
if (CanAutoInteractWithContained(contained.Item) && Screen.Selected is not { IsEditor: true })
|
||||
{
|
||||
contained.Item.IsHighlighted = item.IsHighlighted;
|
||||
item.IsHighlighted = false;
|
||||
}
|
||||
|
||||
Vector2 origin = contained.Item.Sprite.Origin;
|
||||
if (item.FlippedX) { origin.X = contained.Item.Sprite.SourceRect.Width - origin.X; }
|
||||
if (item.FlippedY) { origin.Y = contained.Item.Sprite.SourceRect.Height - origin.Y; }
|
||||
if (flippedX) { origin.X = contained.Item.Sprite.SourceRect.Width - origin.X; }
|
||||
if (flippedY) { origin.Y = contained.Item.Sprite.SourceRect.Height - origin.Y; }
|
||||
|
||||
float containedSpriteDepth = ContainedSpriteDepth < 0.0f ? contained.Item.Sprite.Depth : ContainedSpriteDepth;
|
||||
if (i < containedSpriteDepths.Length)
|
||||
@@ -571,19 +542,20 @@ namespace Barotrauma.Items.Components
|
||||
containedSpriteDepth = containedSpriteDepths[i];
|
||||
}
|
||||
containedSpriteDepth = itemDepth + (containedSpriteDepth - (item.Sprite?.Depth ?? item.SpriteDepth)) / 10000.0f;
|
||||
|
||||
|
||||
SpriteEffects spriteEffects = SpriteEffects.None;
|
||||
float spriteRotation = ItemRotation;
|
||||
if (contained.Rotation != 0)
|
||||
{
|
||||
spriteRotation = contained.Rotation;
|
||||
}
|
||||
bool flipX = (item.body != null && item.body.Dir == -1) || item.FlippedX;
|
||||
|
||||
bool flipX = rootBody is { Dir: -1 } || flippedX;
|
||||
if (flipX)
|
||||
{
|
||||
spriteEffects |= MathUtils.NearlyEqual(spriteRotation % 180, 90.0f) ? SpriteEffects.FlipVertically : SpriteEffects.FlipHorizontally;
|
||||
}
|
||||
bool flipY = item.FlippedY;
|
||||
bool flipY = flippedY;
|
||||
if (flipY)
|
||||
{
|
||||
spriteEffects |= MathUtils.NearlyEqual(spriteRotation % 180, 90.0f) ? SpriteEffects.FlipHorizontally : SpriteEffects.FlipVertically;
|
||||
@@ -598,7 +570,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),
|
||||
|
||||
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>())
|
||||
@@ -608,20 +581,6 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
|
||||
i++;
|
||||
if (Math.Abs(ItemInterval.X) > 0.001f && Math.Abs(ItemInterval.Y) > 0.001f)
|
||||
{
|
||||
//interval set on both axes -> use a grid layout
|
||||
currentItemPos += transformedItemIntervalHorizontal;
|
||||
if (i % ItemsPerRow == 0)
|
||||
{
|
||||
currentItemPos = transformedItemPos;
|
||||
currentItemPos += transformedItemIntervalVertical * (i / ItemsPerRow);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
currentItemPos += transformedItemInterval;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
|
||||
private string text;
|
||||
[Serialize("", IsPropertySaveable.Yes, translationTextTag: "Label.", description: "The text displayed in the label.", alwaysUseInstanceValues: true), Editable(100)]
|
||||
[Serialize("", IsPropertySaveable.Yes, translationTextTag: "Label.", description: "The text displayed in the label.", alwaysUseInstanceValues: true), Editable(MaxLength = 100)]
|
||||
public string Text
|
||||
{
|
||||
get { return text; }
|
||||
|
||||
@@ -35,6 +35,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
Light.SpriteScale = Vector2.One * item.Scale;
|
||||
Light.Position = ParentBody != null ? ParentBody.Position : item.Position;
|
||||
SetLightSourceTransformProjSpecific();
|
||||
}
|
||||
|
||||
partial void SetLightSourceState(bool enabled, float brightness)
|
||||
@@ -51,27 +52,42 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
partial void SetLightSourceTransformProjSpecific()
|
||||
{
|
||||
Vector2 offset = Vector2.Zero;
|
||||
if (LightOffset != Vector2.Zero)
|
||||
{
|
||||
offset = Vector2.Transform(LightOffset, Matrix.CreateRotationZ(item.FlippedY ? -item.RotationRad - MathHelper.Pi : -item.RotationRad)) * item.Scale;
|
||||
}
|
||||
|
||||
if (ParentBody != null)
|
||||
{
|
||||
Light.ParentBody = ParentBody;
|
||||
Light.OffsetFromBody = offset;
|
||||
}
|
||||
else if (turret != null)
|
||||
{
|
||||
Light.Position = new Vector2(item.Rect.X + turret.TransformedBarrelPos.X, item.Rect.Y - turret.TransformedBarrelPos.Y);
|
||||
Light.Position = new Vector2(item.Rect.X + turret.TransformedBarrelPos.X, item.Rect.Y - turret.TransformedBarrelPos.Y) + offset;
|
||||
}
|
||||
else if (item.body != null)
|
||||
{
|
||||
Light.ParentBody = item.body;
|
||||
Light.OffsetFromBody = offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
Light.Position = item.Position;
|
||||
Light.Position = item.Position + offset;
|
||||
}
|
||||
PhysicsBody body = Light.ParentBody;
|
||||
if (body != null && body.Enabled)
|
||||
if (body != null)
|
||||
{
|
||||
Light.Rotation = body.Dir > 0.0f ? body.DrawRotation : body.DrawRotation - MathHelper.Pi;
|
||||
Light.LightSpriteEffect = (body.Dir > 0.0f) ? SpriteEffects.None : SpriteEffects.FlipVertically;
|
||||
if (body.Enabled)
|
||||
{
|
||||
Light.LightSpriteEffect = (body.Dir > 0.0f) ? SpriteEffects.None : SpriteEffects.FlipVertically;
|
||||
}
|
||||
else
|
||||
{
|
||||
Light.LightSpriteEffect = item.SpriteEffects;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -85,11 +101,13 @@ namespace Barotrauma.Items.Components
|
||||
if (Light?.LightSprite == null) { return; }
|
||||
if ((item.body == null || item.body.Enabled) && lightBrightness > 0.0f && IsOn && Light.Enabled)
|
||||
{
|
||||
Vector2 offset = Vector2.Transform(LightOffset, Matrix.CreateRotationZ(item.FlippedY ? -item.RotationRad - MathHelper.Pi : -item.RotationRad)) * item.Scale;
|
||||
|
||||
Vector2 origin = Light.LightSprite.Origin;
|
||||
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; }
|
||||
|
||||
Vector2 drawPos = item.body?.DrawPosition ?? item.DrawPosition;
|
||||
Vector2 drawPos = item.body?.DrawPosition ?? item.DrawPosition + offset;
|
||||
|
||||
Color color = lightColor;
|
||||
if (Light.OverrideLightSpriteAlpha.HasValue)
|
||||
|
||||
@@ -6,11 +6,11 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
partial class Controller : ItemComponent
|
||||
{
|
||||
private bool chatBoxOriginalState;
|
||||
private bool isHUDsHidden;
|
||||
|
||||
public override void DrawHUD(SpriteBatch spriteBatch, Character character)
|
||||
{
|
||||
base.DrawHUD(spriteBatch, character);
|
||||
if (focusTarget != null && character.ViewTarget == focusTarget)
|
||||
{
|
||||
foreach (ItemComponent ic in focusTarget.Components)
|
||||
@@ -23,48 +23,31 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
public override void AddToGUIUpdateList(int order = 0)
|
||||
{
|
||||
base.AddToGUIUpdateList(order);
|
||||
if (focusTarget != null && Character.Controlled.ViewTarget == focusTarget)
|
||||
{
|
||||
focusTarget.AddToGUIUpdateList(order);
|
||||
}
|
||||
}
|
||||
|
||||
partial void HideHUDs(bool value)
|
||||
{
|
||||
if (isHUDsHidden == value) { return; }
|
||||
if (value == true)
|
||||
if (value)
|
||||
{
|
||||
GameMain.GameSession?.CrewManager?.AutoHideCrewList();
|
||||
ToggleChatBox(false, storeOriginalState: true);
|
||||
ChatBox.AutoHideChatBox();
|
||||
}
|
||||
else
|
||||
{
|
||||
GameMain.GameSession?.CrewManager?.ResetCrewList();
|
||||
ToggleChatBox(chatBoxOriginalState, storeOriginalState: false);
|
||||
GameMain.GameSession?.CrewManager?.ResetCrewListOpenState();
|
||||
ChatBox.ResetChatBoxOpenState();
|
||||
}
|
||||
isHUDsHidden = value;
|
||||
}
|
||||
|
||||
private void ToggleChatBox(bool value, bool storeOriginalState)
|
||||
{
|
||||
var crewManager = GameMain.GameSession?.CrewManager;
|
||||
if (crewManager == null) { return; }
|
||||
|
||||
if (crewManager.IsSinglePlayer)
|
||||
{
|
||||
if (crewManager.ChatBox != null)
|
||||
{
|
||||
if (storeOriginalState)
|
||||
{
|
||||
chatBoxOriginalState = crewManager.ChatBox.ToggleOpen;
|
||||
}
|
||||
crewManager.ChatBox.ToggleOpen = value;
|
||||
}
|
||||
}
|
||||
else if (GameMain.Client != null)
|
||||
{
|
||||
if (storeOriginalState)
|
||||
{
|
||||
chatBoxOriginalState = GameMain.Client.ChatBox.ToggleOpen;
|
||||
}
|
||||
GameMain.Client.ChatBox.ToggleOpen = value;
|
||||
}
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
public override void CreateEditingHUD(SerializableEntityEditor editor)
|
||||
{
|
||||
|
||||
+17
-8
@@ -154,12 +154,14 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
infoArea.Text = TextManager.Get(InfoText).Fallback(InfoText);
|
||||
}
|
||||
|
||||
if (IsActive)
|
||||
{
|
||||
activateButton.Text = TextManager.Get("DeconstructorCancel");
|
||||
infoArea.Text = string.Empty;
|
||||
return;
|
||||
}
|
||||
|
||||
bool outputsFound = false;
|
||||
foreach (var (inputItem, deconstructItem) in GetAvailableOutputs(checkRequiredOtherItems: true))
|
||||
{
|
||||
@@ -174,27 +176,34 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
inputItem.GetComponent<GeneticMaterial>()?.ModifyDeconstructInfo(this, ref buttonText, ref infoText);
|
||||
activateButton.Text = buttonText;
|
||||
if (infoArea != null)
|
||||
{
|
||||
infoArea.Text = infoText;
|
||||
}
|
||||
infoArea.Text = infoText;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
LocalizedString activateButtonText = TextManager.Get(ActivateButtonText);
|
||||
activateButton.Enabled = outputsFound || !InputContainer.Inventory.IsEmpty();
|
||||
activateButton.Text = activateButtonText;
|
||||
|
||||
//no valid outputs found: check if we're missing some required items from the input slots and display a message about it if possible
|
||||
if (!outputsFound && infoArea != null)
|
||||
{
|
||||
foreach (var (inputItem, deconstructItem) in GetAvailableOutputs(checkRequiredOtherItems: false))
|
||||
{
|
||||
LocalizedString infoText = string.Empty;
|
||||
if (deconstructItem.RequiredOtherItem.Any() && !string.IsNullOrEmpty(deconstructItem.InfoTextOnOtherItemMissing))
|
||||
{
|
||||
LocalizedString missingItemName = TextManager.Get("entityname." + deconstructItem.RequiredOtherItem.First());
|
||||
infoArea.Text = TextManager.GetWithVariable(deconstructItem.InfoTextOnOtherItemMissing, "[itemname]", missingItemName);
|
||||
infoText = TextManager.GetWithVariable(deconstructItem.InfoTextOnOtherItemMissing, "[itemname]", missingItemName);
|
||||
}
|
||||
|
||||
inputItem.GetComponent<GeneticMaterial>()?.ModifyDeconstructInfo(this, ref activateButtonText, ref infoText);
|
||||
|
||||
activateButton.Text = activateButtonText;
|
||||
infoArea.Text = infoText;
|
||||
}
|
||||
}
|
||||
activateButton.Enabled = outputsFound || !InputContainer.Inventory.IsEmpty();
|
||||
activateButton.Text = TextManager.Get(ActivateButtonText);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -415,7 +424,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public override void UpdateHUDComponentSpecific(Character character, float deltaTime, Camera cam)
|
||||
{
|
||||
inSufficientPowerWarning.Visible = IsActive && !hasPower;
|
||||
inSufficientPowerWarning.Visible = IsActive && !HasPower;
|
||||
}
|
||||
|
||||
private bool OnActivateButtonClicked(GUIButton button, object obj)
|
||||
|
||||
+327
-130
@@ -11,11 +11,21 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
partial class Fabricator : Powered, IServerSerializable, IClientSerializable
|
||||
{
|
||||
private enum SortBy
|
||||
{
|
||||
Category,
|
||||
Alphabetical,
|
||||
SkillRequirement,
|
||||
Price
|
||||
}
|
||||
|
||||
private GUIListBox itemList;
|
||||
|
||||
private GUIFrame selectedItemFrame;
|
||||
private GUIFrame selectedItemReqsFrame;
|
||||
|
||||
private GUILayoutGroup outputTopArea, paddedOutputArea;
|
||||
|
||||
private GUITextBlock amountTextMax;
|
||||
private GUIScrollBar amountInput;
|
||||
|
||||
@@ -26,6 +36,8 @@ namespace Barotrauma.Items.Components
|
||||
private GUIButton activateButton;
|
||||
|
||||
private GUITextBox itemFilterBox;
|
||||
private GUITickBox availableOnlyTickBox;
|
||||
private GUIDropDown sortByDropdown;
|
||||
|
||||
private GUIComponent outputSlot;
|
||||
private GUIComponent inputInventoryHolder, outputInventoryHolder;
|
||||
@@ -33,6 +45,9 @@ namespace Barotrauma.Items.Components
|
||||
private readonly List<GUIButton> itemCategoryButtons = new List<GUIButton>();
|
||||
private MapEntityCategory? selectedItemCategory;
|
||||
|
||||
private GUITextBlock requiresRecipeText;
|
||||
private GUITextBlock nothingToShowText;
|
||||
|
||||
public FabricationRecipe SelectedItem
|
||||
{
|
||||
get { return selectedItem; }
|
||||
@@ -65,6 +80,12 @@ namespace Barotrauma.Items.Components
|
||||
[Serialize("vendingmachine.outofstock", IsPropertySaveable.Yes)]
|
||||
public string FabricationLimitReachedText { get; set; }
|
||||
|
||||
[Serialize(true, IsPropertySaveable.No)]
|
||||
public bool ShowSortByDropdown { get; set; }
|
||||
|
||||
[Serialize(true, IsPropertySaveable.No)]
|
||||
public bool ShowAvailableOnlyTickBox { get; set; }
|
||||
|
||||
public override bool RecreateGUIOnResolutionChange => true;
|
||||
|
||||
protected override void OnResolutionChanged()
|
||||
@@ -154,24 +175,24 @@ namespace Barotrauma.Items.Components
|
||||
};
|
||||
|
||||
// === TOP AREA ===
|
||||
var topFrame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.65f), mainFrame.RectTransform), style: "InnerFrameDark");
|
||||
var topFrame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.8f), mainFrame.RectTransform), style: "InnerFrameDark");
|
||||
|
||||
// === ITEM LIST ===
|
||||
var itemListFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.5f, 1.0f), topFrame.RectTransform), childAnchor: Anchor.Center);
|
||||
var paddedItemFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.9f), itemListFrame.RectTransform))
|
||||
var paddedItemFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.95f), itemListFrame.RectTransform), isHorizontal: false)
|
||||
{
|
||||
Stretch = true,
|
||||
RelativeSpacing = 0.03f
|
||||
Stretch = true
|
||||
};
|
||||
var filterArea = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.15f), paddedItemFrame.RectTransform), isHorizontal: true)
|
||||
{
|
||||
Stretch = true,
|
||||
RelativeSpacing = 0.03f,
|
||||
Stretch = true,
|
||||
RelativeSpacing = 0.03f,
|
||||
UserData = "filterarea"
|
||||
};
|
||||
new GUITextBlock(new RectTransform(new Vector2(0.2f, 1f), filterArea.RectTransform), TextManager.Get("serverlog.filter"), font: GUIStyle.SubHeadingFont)
|
||||
new GUITextBlock(new RectTransform(new Vector2(0.4f, 1f), filterArea.RectTransform), TextManager.Get("serverlog.filter"),
|
||||
font: GUIStyle.SubHeadingFont, textAlignment: Alignment.CenterLeft)
|
||||
{
|
||||
Padding = Vector4.Zero,
|
||||
Padding = Vector4.Zero,
|
||||
AutoScaleVertical = true
|
||||
};
|
||||
itemFilterBox = new GUITextBox(new RectTransform(new Vector2(0.8f, 1.0f), filterArea.RectTransform), createClearButton: true)
|
||||
@@ -183,29 +204,91 @@ namespace Barotrauma.Items.Components
|
||||
FilterEntities(selectedItemCategory, text);
|
||||
return true;
|
||||
};
|
||||
filterArea.RectTransform.MinSize = new Point(0, itemFilterBox.Rect.Height);
|
||||
filterArea.RectTransform.MaxSize = new Point(int.MaxValue, itemFilterBox.Rect.Height);
|
||||
|
||||
itemList = new GUIListBox(new RectTransform(new Vector2(1f, 0.9f), paddedItemFrame.RectTransform), style: null)
|
||||
var sortByArea = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.15f), paddedItemFrame.RectTransform), isHorizontal: true)
|
||||
{
|
||||
Stretch = true,
|
||||
RelativeSpacing = 0.03f,
|
||||
Visible = ShowSortByDropdown,
|
||||
IgnoreLayoutGroups = !ShowSortByDropdown
|
||||
};
|
||||
new GUITextBlock(new RectTransform(new Vector2(0.4f, 1f), sortByArea.RectTransform), TextManager.Get("campaignstore.sortby"),
|
||||
font: GUIStyle.SubHeadingFont, textAlignment: Alignment.CenterLeft)
|
||||
{
|
||||
Padding = Vector4.Zero,
|
||||
AutoScaleVertical = true
|
||||
};
|
||||
sortByDropdown = new GUIDropDown(new RectTransform(new Vector2(0.8f, 1.0f), sortByArea.RectTransform));
|
||||
foreach (SortBy sortBy in Enum.GetValues<SortBy>())
|
||||
{
|
||||
sortByDropdown.AddItem(TextManager.Get("fabricator.sortby." + sortBy), userData: sortBy);
|
||||
}
|
||||
sortByDropdown.Select(index: 0);
|
||||
sortByDropdown.AfterSelected += (GUIComponent selected, object userdata) =>
|
||||
{
|
||||
FilterEntities(selectedItemCategory, itemFilterBox.Text);
|
||||
SortItems(character: Character.Controlled);
|
||||
return true;
|
||||
};
|
||||
sortByArea.RectTransform.MinSize = new Point(0, sortByDropdown.Rect.Height);
|
||||
sortByArea.RectTransform.MaxSize = new Point(int.MaxValue, sortByDropdown.Rect.Height);
|
||||
|
||||
var availableOnlyTickBoxArea = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.15f), paddedItemFrame.RectTransform), isHorizontal: true)
|
||||
{
|
||||
Stretch = true,
|
||||
Visible = ShowAvailableOnlyTickBox,
|
||||
IgnoreLayoutGroups = !ShowAvailableOnlyTickBox
|
||||
};
|
||||
new GUITextBlock(new RectTransform(new Vector2(0.4f, 1f), availableOnlyTickBoxArea.RectTransform), TextManager.Get("fabricator.onlyshowavailable"),
|
||||
font: GUIStyle.SubHeadingFont, textAlignment: Alignment.CenterLeft)
|
||||
{
|
||||
Padding = Vector4.Zero,
|
||||
AutoScaleVertical = true
|
||||
};
|
||||
availableOnlyTickBox = new GUITickBox(new RectTransform(new Vector2(1.0f), availableOnlyTickBoxArea.RectTransform, scaleBasis: ScaleBasis.BothHeight), label: string.Empty)
|
||||
{
|
||||
ToolTip = TextManager.Get("fabricator.onlyshowavailable.tooltip")
|
||||
};
|
||||
availableOnlyTickBox.OnSelected += (tickbox) =>
|
||||
{
|
||||
FilterEntities(selectedItemCategory, itemFilterBox.Text);
|
||||
return true;
|
||||
};
|
||||
availableOnlyTickBox.RectTransform.MinSize = new Point(availableOnlyTickBox.Rect.Height);
|
||||
availableOnlyTickBox.RectTransform.IsFixedSize = true;
|
||||
availableOnlyTickBoxArea.RectTransform.MinSize = new Point(0, availableOnlyTickBox.Rect.Height);
|
||||
availableOnlyTickBoxArea.RectTransform.MaxSize = new Point(int.MaxValue, availableOnlyTickBox.Rect.Height);
|
||||
|
||||
itemList = new GUIListBox(new RectTransform(new Vector2(1f, 0.8f), paddedItemFrame.RectTransform), style: null)
|
||||
{
|
||||
PlaySoundOnSelect = true,
|
||||
OnSelected = (component, userdata) =>
|
||||
{
|
||||
selectedItem = userdata as FabricationRecipe;
|
||||
if (selectedItem != null) { SelectItem(Character.Controlled, selectedItem); }
|
||||
return true;
|
||||
if (userdata is FabricationRecipe fabricationRecipe)
|
||||
{
|
||||
selectedItem = fabricationRecipe;
|
||||
SelectItem(Character.Controlled, selectedItem);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// === SEPARATOR === //
|
||||
new GUIFrame(new RectTransform(new Vector2(0.01f, 0.9f), topFrame.RectTransform, Anchor.Center), style: "VerticalLine");
|
||||
// === SEPARATOR === //
|
||||
new GUIFrame(new RectTransform(new Vector2(0.01f, 0.9f), topFrame.RectTransform, Anchor.Center), style: "VerticalLine");
|
||||
|
||||
// === OUTPUT AREA === //
|
||||
var outputArea = new GUILayoutGroup(new RectTransform(new Vector2(0.5f, 1f), topFrame.RectTransform, Anchor.TopRight), childAnchor: Anchor.Center);
|
||||
var paddedOutputArea = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.9f), outputArea.RectTransform));
|
||||
var outputTopArea = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.5F), paddedOutputArea.RectTransform, Anchor.Center), isHorizontal: true);
|
||||
paddedOutputArea = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.95f), outputArea.RectTransform)) { Stretch = true };
|
||||
outputTopArea = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.5f), paddedOutputArea.RectTransform, Anchor.Center), isHorizontal: true);
|
||||
// === OUTPUT SLOT === //
|
||||
outputSlot = new GUIFrame(new RectTransform(new Vector2(0.4f, 1f), outputTopArea.RectTransform), style: null);
|
||||
outputInventoryHolder = new GUIFrame(new RectTransform(new Vector2(1f, 1.2f), outputSlot.RectTransform, Anchor.BottomCenter), style: null);
|
||||
outputSlot = new GUIFrame(new RectTransform(new Vector2(0.4f, 0.4f), outputTopArea.RectTransform, scaleBasis: ScaleBasis.BothWidth), style: null);
|
||||
outputInventoryHolder = new GUIFrame(new RectTransform(new Vector2(1f, 1.0f), outputSlot.RectTransform, Anchor.BottomCenter), style: null);
|
||||
new GUICustomComponent(new RectTransform(Vector2.One, outputInventoryHolder.RectTransform), DrawOutputOverLay) { CanBeFocused = false };
|
||||
// === DESCRIPTION === //
|
||||
selectedItemFrame = new GUIFrame(new RectTransform(new Vector2(0.6f, 1f), outputTopArea.RectTransform), style: null);
|
||||
@@ -213,7 +296,7 @@ namespace Barotrauma.Items.Components
|
||||
selectedItemReqsFrame = new GUIFrame(new RectTransform(new Vector2(1f, 0.5f), paddedOutputArea.RectTransform), style: null);
|
||||
|
||||
// === BOTTOM AREA === //
|
||||
var bottomFrame = new GUIFrame(new RectTransform(new Vector2(1f, 0.3f), mainFrame.RectTransform), style: null);
|
||||
var bottomFrame = new GUIFrame(new RectTransform(new Vector2(1f, 0.2f), mainFrame.RectTransform), style: null);
|
||||
|
||||
if (inputContainer.Capacity > 0)
|
||||
{
|
||||
@@ -298,6 +381,33 @@ namespace Barotrauma.Items.Components
|
||||
CanBeFocused = false
|
||||
};
|
||||
CreateRecipes();
|
||||
|
||||
foreach (MapEntityCategory category in itemCategories)
|
||||
{
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.15f), itemList.Content.RectTransform),
|
||||
TextManager.Get("MapEntityCategory." + category), textColor: GUIStyle.TextColorBright)
|
||||
{
|
||||
CanBeFocused = false,
|
||||
UserData = category,
|
||||
Visible = false
|
||||
};
|
||||
}
|
||||
|
||||
requiresRecipeText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.15f), itemList.Content.RectTransform),
|
||||
TextManager.Get("fabricatorrequiresrecipe"), textColor: Color.Red, font: GUIStyle.SubHeadingFont)
|
||||
{
|
||||
AutoScaleHorizontal = true,
|
||||
CanBeFocused = false
|
||||
};
|
||||
|
||||
nothingToShowText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.8f), itemList.Content.RectTransform), TextManager.Get("noitemsheader"),
|
||||
textAlignment: Alignment.Center, textColor: GUIStyle.TextColorDim)
|
||||
{
|
||||
CanBeFocused = false,
|
||||
Visible = false
|
||||
};
|
||||
|
||||
SortItems(character: Character.Controlled);
|
||||
}
|
||||
|
||||
private void RefreshActivateButtonText()
|
||||
@@ -343,7 +453,8 @@ namespace Barotrauma.Items.Components
|
||||
};
|
||||
}
|
||||
|
||||
new GUITextBlock(new RectTransform(new Vector2(0.85f, 1f), container.RectTransform), GetRecipeNameAndAmount(fi))
|
||||
new GUITextBlock(new RectTransform(new Vector2(0.85f, 1f), container.RectTransform),
|
||||
RichString.Rich(GetRecipeNameAndAmount(fi)), font: GUIStyle.SmallFont)
|
||||
{
|
||||
Padding = Vector4.Zero,
|
||||
AutoScaleVertical = true,
|
||||
@@ -372,17 +483,17 @@ namespace Barotrauma.Items.Components
|
||||
outputContainer.Inventory.RectTransform = outputInventoryHolder.RectTransform;
|
||||
}
|
||||
|
||||
private static LocalizedString GetRecipeNameAndAmount(FabricationRecipe fabricationRecipe)
|
||||
private static RichString GetRecipeNameAndAmount(FabricationRecipe fabricationRecipe)
|
||||
{
|
||||
if (fabricationRecipe == null) { return ""; }
|
||||
if (fabricationRecipe.Amount > 1)
|
||||
{
|
||||
return TextManager.GetWithVariables("fabricationrecipenamewithamount",
|
||||
("[name]", fabricationRecipe.DisplayName), ("[amount]", fabricationRecipe.Amount.ToString()));
|
||||
("[name]", RichString.Rich(fabricationRecipe.DisplayName)), ("[amount]", fabricationRecipe.Amount.ToString()));
|
||||
}
|
||||
else
|
||||
{
|
||||
return fabricationRecipe.DisplayName;
|
||||
return RichString.Rich(fabricationRecipe.DisplayName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -397,73 +508,106 @@ namespace Barotrauma.Items.Components
|
||||
if (character != Character.Controlled) { return; }
|
||||
|
||||
var nonItems = itemList.Content.Children.Where(c => c.UserData is not FabricationRecipe).ToList();
|
||||
nonItems.ForEach(i => itemList.Content.RemoveChild(i));
|
||||
nonItems.ForEach(i => i.Visible = false);
|
||||
|
||||
SortItems(character: null);
|
||||
FilterEntities(selectedItemCategory, itemFilterBox?.Text ?? string.Empty);
|
||||
HideEmptyItemListCategories();
|
||||
}
|
||||
|
||||
private void SortItems(Character character)
|
||||
{
|
||||
SortBy sortBy = (SortBy)sortByDropdown.SelectedData;
|
||||
|
||||
itemList.Content.RectTransform.SortChildren((c1, c2) =>
|
||||
{
|
||||
var item1 = c1.GUIComponent.UserData as FabricationRecipe;
|
||||
var item2 = c2.GUIComponent.UserData as FabricationRecipe;
|
||||
|
||||
int itemPlacement1 = calculatePlacement(item1);
|
||||
int itemPlacement2 = calculatePlacement(item2);
|
||||
if (itemPlacement1 != itemPlacement2)
|
||||
if (item1 == null && item2 == null)
|
||||
{
|
||||
return itemPlacement1 > itemPlacement2 ? -1 : 1;
|
||||
return 0;
|
||||
}
|
||||
else if (item1 == null)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else if (item2 == null)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int calculatePlacement(FabricationRecipe recipe)
|
||||
bool missingRecipe1 = MissingRequiredRecipe(item1, character);
|
||||
bool missingRecipe2 = MissingRequiredRecipe(item2, character);
|
||||
if (missingRecipe1 != missingRecipe2)
|
||||
{
|
||||
if (recipe.RequiresRecipe && !AnyOneHasRecipeForItem(character, recipe.TargetItem))
|
||||
{
|
||||
return -2;
|
||||
}
|
||||
int placement = FabricationDegreeOfSuccess(character, recipe.RequiredSkills) >= 0.5f ? 0 : -1;
|
||||
return placement;
|
||||
return missingRecipe1.CompareTo(missingRecipe2);
|
||||
}
|
||||
|
||||
return string.Compare(item1.DisplayName.Value, item2.DisplayName.Value);
|
||||
switch (sortBy)
|
||||
{
|
||||
case SortBy.Alphabetical:
|
||||
return string.Compare(item1.DisplayName.Value, item2.DisplayName.Value);
|
||||
case SortBy.Category:
|
||||
var category1 = EnumExtensions.GetIndividualFlags(item1.TargetItem.Category).FirstOrDefault();
|
||||
var category2 = EnumExtensions.GetIndividualFlags(item2.TargetItem.Category).FirstOrDefault();
|
||||
if (category1 == category2)
|
||||
{
|
||||
return string.Compare(item1.DisplayName.Value, item2.DisplayName.Value);
|
||||
}
|
||||
return category1.CompareTo(category2);
|
||||
case SortBy.SkillRequirement:
|
||||
float skillRequirement1 = item1.RequiredSkills.Sum(skill => skill.Level);
|
||||
float skillRequirement2 = item2.RequiredSkills.Sum(skill => skill.Level);
|
||||
if (MathUtils.NearlyEqual(skillRequirement1, skillRequirement2))
|
||||
{
|
||||
return string.Compare(item1.DisplayName.Value, item2.DisplayName.Value);
|
||||
}
|
||||
return skillRequirement1.CompareTo(skillRequirement2);
|
||||
case SortBy.Price:
|
||||
float itemValue1 = item1.TargetItem.DefaultPrice?.Price ?? 0;
|
||||
float itemValue2 = item2.TargetItem.DefaultPrice?.Price ?? 0;
|
||||
if (MathUtils.NearlyEqual(itemValue1, itemValue2))
|
||||
{
|
||||
return string.Compare(item1.DisplayName.Value, item2.DisplayName.Value);
|
||||
}
|
||||
return itemValue2.CompareTo(itemValue1);
|
||||
default:
|
||||
throw new NotImplementedException($"Sorting by {sortBy} has not been implemented.");
|
||||
}
|
||||
});
|
||||
|
||||
var sufficientSkillsText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.15f), itemList.Content.RectTransform),
|
||||
TextManager.Get("fabricatorsufficientskills"), textColor: GUIStyle.Green, font: GUIStyle.SubHeadingFont)
|
||||
if (sortBy == SortBy.Category)
|
||||
{
|
||||
AutoScaleHorizontal = true,
|
||||
CanBeFocused = false
|
||||
};
|
||||
sufficientSkillsText.RectTransform.SetAsFirstChild();
|
||||
foreach (var categoryText in itemList.Content.Children.Where(c => c.UserData?.GetType() == typeof(MapEntityCategory)).ToList())
|
||||
{
|
||||
categoryText.RectTransform.SetAsLastChild();
|
||||
var category = (MapEntityCategory)categoryText.UserData;
|
||||
var firstChildWithMatchingCategory = itemList.Content.Children.FirstOrDefault(c => c.UserData is FabricationRecipe recipe && EnumExtensions.GetIndividualFlags(recipe.TargetItem.Category).FirstOrDefault() == category);
|
||||
if (firstChildWithMatchingCategory != null)
|
||||
{
|
||||
categoryText.RectTransform.RepositionChildInHierarchy(itemList.Content.GetChildIndex(firstChildWithMatchingCategory));
|
||||
categoryText.Visible = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
categoryText.Visible = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var insufficientSkillsText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.15f), itemList.Content.RectTransform),
|
||||
TextManager.Get("fabricatorinsufficientskills"), textColor: Color.Orange, font: GUIStyle.SubHeadingFont)
|
||||
requiresRecipeText.RectTransform.SetAsLastChild();
|
||||
var firstMissingRecipe = itemList.Content.Children.FirstOrDefault(c => c.UserData is FabricationRecipe recipe && MissingRequiredRecipe(recipe, character));
|
||||
if (firstMissingRecipe != null)
|
||||
{
|
||||
AutoScaleHorizontal = true,
|
||||
CanBeFocused = false
|
||||
};
|
||||
var firstinSufficient = itemList.Content.Children.FirstOrDefault(c => c.UserData is FabricationRecipe fabricableItem && FabricationDegreeOfSuccess(character, fabricableItem.RequiredSkills) < 0.5f);
|
||||
if (firstinSufficient != null)
|
||||
{
|
||||
insufficientSkillsText.RectTransform.RepositionChildInHierarchy(itemList.Content.RectTransform.GetChildIndex(firstinSufficient.RectTransform));
|
||||
requiresRecipeText.RectTransform.RepositionChildInHierarchy(itemList.Content.GetChildIndex(firstMissingRecipe));
|
||||
requiresRecipeText.Visible = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
sufficientSkillsText.Visible = insufficientSkillsText.Visible = false;
|
||||
sufficientSkillsText.Enabled = insufficientSkillsText.Enabled = false;
|
||||
requiresRecipeText.Visible = false;
|
||||
}
|
||||
|
||||
var requiresRecipeText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.15f), itemList.Content.RectTransform),
|
||||
TextManager.Get("fabricatorrequiresrecipe"), textColor: Color.Red, font: GUIStyle.SubHeadingFont)
|
||||
{
|
||||
AutoScaleHorizontal = true,
|
||||
CanBeFocused = false
|
||||
};
|
||||
var firstRequiresRecipe = itemList.Content.Children.FirstOrDefault(c =>
|
||||
c.UserData is FabricationRecipe fabricableItem &&
|
||||
fabricableItem.RequiresRecipe && !AnyOneHasRecipeForItem(character, fabricableItem.TargetItem));
|
||||
if (firstRequiresRecipe != null)
|
||||
{
|
||||
requiresRecipeText.RectTransform.RepositionChildInHierarchy(itemList.Content.RectTransform.GetChildIndex(firstRequiresRecipe.RectTransform));
|
||||
}
|
||||
|
||||
FilterEntities(selectedItemCategory, itemFilterBox?.Text ?? string.Empty);
|
||||
HideEmptyItemListCategories();
|
||||
}
|
||||
|
||||
@@ -757,6 +901,9 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
private bool FilterEntities(MapEntityCategory? category, string filter)
|
||||
{
|
||||
bool onlyShowAvailable = availableOnlyTickBox is { Selected: true };
|
||||
|
||||
bool anyVisible = false;
|
||||
foreach (GUIComponent child in itemList.Content.Children)
|
||||
{
|
||||
FabricationRecipe recipe = child.UserData as FabricationRecipe;
|
||||
@@ -771,16 +918,35 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
if (recipe.RequiresRecipe && recipe.HideIfNoRecipe)
|
||||
{
|
||||
if (Character.Controlled != null)
|
||||
{
|
||||
if (!AnyOneHasRecipeForItem(Character.Controlled, recipe.TargetItem))
|
||||
{
|
||||
child.Visible = false;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
child.Visible =
|
||||
(string.IsNullOrWhiteSpace(filter) || recipe.DisplayName.Contains(filter, StringComparison.OrdinalIgnoreCase)) &&
|
||||
(!category.HasValue || recipe.TargetItem.Category.HasFlag(category.Value));
|
||||
}
|
||||
(!category.HasValue || recipe.TargetItem.Category.HasFlag(category.Value)) &&
|
||||
(!onlyShowAvailable || CanBeFabricated(recipe, availableIngredients, Character.Controlled));
|
||||
if (child.Visible)
|
||||
{
|
||||
anyVisible = true;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (GUIButton btn in itemCategoryButtons)
|
||||
{
|
||||
btn.Selected = (MapEntityCategory?)btn.UserData == selectedItemCategory;
|
||||
}
|
||||
HideEmptyItemListCategories();
|
||||
nothingToShowText.Visible = !anyVisible;
|
||||
itemList.UserData = "itemlist";
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -788,7 +954,7 @@ namespace Barotrauma.Items.Components
|
||||
private void HideEmptyItemListCategories()
|
||||
{
|
||||
bool visibleElementsChanged = false;
|
||||
//go through the elements backwards, and disable the labels ("insufficient skills to fabricate", "recipe required...") if there's no items below them
|
||||
//go through the elements backwards, and disable the labels if there's no items below them
|
||||
bool recipeVisible = false;
|
||||
foreach (GUIComponent child in itemList.Content.Children.Reverse())
|
||||
{
|
||||
@@ -810,6 +976,12 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
SortBy sortBy = (SortBy)sortByDropdown.SelectedData;
|
||||
if (sortBy != SortBy.Category)
|
||||
{
|
||||
itemList.Content.Children.Where(c => c.UserData?.GetType() == typeof(MapEntityCategory)).ForEach(c => c.Visible = false);
|
||||
}
|
||||
|
||||
if (visibleElementsChanged)
|
||||
{
|
||||
itemList.UpdateScrollBarSize();
|
||||
@@ -841,8 +1013,8 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
private void CreateSelectedItemUI(SelectedRecipe recipe)
|
||||
{
|
||||
var (user, selectedItem, overrideRequiredTime) = recipe;
|
||||
int max = Math.Max(selectedItem.TargetItem.GetMaxStackSize(outputContainer.Inventory) / selectedItem.Amount, 1);
|
||||
var (user, selectedRecipe, overrideRequiredTime) = recipe;
|
||||
int max = Math.Max(selectedRecipe.TargetItem.GetMaxStackSize(outputContainer.Inventory) / selectedRecipe.Amount, 1);
|
||||
|
||||
if (amountInput != null)
|
||||
{
|
||||
@@ -859,18 +1031,59 @@ namespace Barotrauma.Items.Components
|
||||
selectedItemFrame.ClearChildren();
|
||||
selectedItemReqsFrame.ClearChildren();
|
||||
|
||||
var paddedFrame = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.9f), selectedItemFrame.RectTransform, Anchor.Center)) { RelativeSpacing = 0.03f };
|
||||
var paddedFrame = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.9f), selectedItemFrame.RectTransform, Anchor.Center)) { RelativeSpacing = 0.03f, CanBeFocused = true };
|
||||
var paddedReqFrame = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.9f), selectedItemReqsFrame.RectTransform, Anchor.Center)) { RelativeSpacing = 0.03f };
|
||||
|
||||
LocalizedString itemName = GetRecipeNameAndAmount(selectedItem);
|
||||
LocalizedString itemName = GetRecipeNameAndAmount(selectedRecipe);
|
||||
LocalizedString name = itemName;
|
||||
|
||||
QualityResult result = GetFabricatedItemQuality(selectedItem, user);
|
||||
QualityResult result = GetFabricatedItemQuality(selectedRecipe, user);
|
||||
|
||||
float quality = selectedItem.Quality ?? result.Quality;
|
||||
if (quality > 0 || result.HasRandomQualityRollChance)
|
||||
float minimumQuality = selectedRecipe.Quality ?? result.Quality;
|
||||
|
||||
LocalizedString qualityTooltip = string.Empty;
|
||||
if (result.HasRandomQualityRollChance)
|
||||
{
|
||||
name = TextManager.GetWithVariable("itemname.quality" + (int)quality, "[itemname]", itemName + '\n')
|
||||
float plusOnePercentage = result.TotalPlusOnePercentage;
|
||||
float plusTwoPercentage = result.TotalPlusTwoPercentage;
|
||||
|
||||
string plusOnePercentageText = plusOnePercentage.ToString("F1", CultureInfo.InvariantCulture);
|
||||
string plusTwoPercentageText = plusTwoPercentage.ToString("F1", CultureInfo.InvariantCulture);
|
||||
|
||||
int plusOneQuality = Math.Clamp(result.Quality + 1, min: 0, max: 3);
|
||||
int plusTwoQuality = Math.Clamp(result.Quality + 2, min: 0, max: 3);
|
||||
|
||||
LocalizedString plusOneQualityText = TextManager.Get($"quality{plusOneQuality}");
|
||||
LocalizedString plusTwoQualityText = TextManager.Get($"quality{plusTwoQuality}");
|
||||
|
||||
string localizationTag = plusTwoPercentage > 0f && plusOnePercentage > 0 && plusOneQuality != plusTwoQuality ? "meetsbonusrequirementtwice" : "meetsbonusrequirement";
|
||||
|
||||
var variables = new (string Key, LocalizedString Value)[]
|
||||
{
|
||||
("[chance]", plusOnePercentageText), ("[quality]", plusOneQualityText),
|
||||
("[chance2]", plusTwoPercentageText), ("[quality2]", plusTwoQualityText)
|
||||
};
|
||||
|
||||
if (MathUtils.NearlyEqual(plusOnePercentage, 0))
|
||||
{
|
||||
variables = new[] { ("[chance]", plusTwoPercentageText), ("[quality]", plusTwoQualityText) };
|
||||
}
|
||||
|
||||
if (plusOneQuality == plusTwoQuality)
|
||||
{
|
||||
LocalizedString rawPercentage = result.PlusOnePercentage.ToString("F1", CultureInfo.InvariantCulture);
|
||||
variables = new[] { ("[chance]", rawPercentage), ("[quality]", plusOneQualityText) };
|
||||
}
|
||||
|
||||
if (plusOnePercentage >= 100.0f) { minimumQuality = plusOneQuality; }
|
||||
if (plusTwoPercentage >= 100.0f) { minimumQuality = plusTwoQuality; }
|
||||
|
||||
qualityTooltip = TextManager.GetWithVariables(localizationTag, variables);
|
||||
}
|
||||
|
||||
if (minimumQuality > 0 || result.HasRandomQualityRollChance)
|
||||
{
|
||||
name = TextManager.GetWithVariable("itemname.quality" + (int)minimumQuality, "[itemname]", itemName + '\n')
|
||||
.Fallback(TextManager.GetWithVariable("itemname.quality3", "[itemname]", itemName + '\n'));
|
||||
}
|
||||
|
||||
@@ -884,44 +1097,13 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
var iconLayout = new GUIFrame(new RectTransform(new Vector2(0.4f, 1f), selectedItemFrame.RectTransform, anchor: Anchor.TopRight), style: null);
|
||||
var icon = GameSession.CreateNotificationIcon(iconLayout, offset: true);
|
||||
|
||||
float percentage1 = result.TotalPlusOnePercentage;
|
||||
float percentage2 = result.TotalPlusTwoPercentage;
|
||||
|
||||
string chance1text = percentage1.ToString("F1", CultureInfo.InvariantCulture);
|
||||
string chance2text = percentage2.ToString("F1", CultureInfo.InvariantCulture);
|
||||
|
||||
int quality1 = Math.Clamp(result.Quality + 1, min: 0, max: 3);
|
||||
int quality2 = Math.Clamp(result.Quality + 2, min: 0, max: 3);
|
||||
|
||||
LocalizedString quality1Text = TextManager.Get($"quality{quality1}");
|
||||
LocalizedString quality2Text = TextManager.Get($"quality{quality2}");
|
||||
|
||||
string localizationTag = percentage2 > 0f && percentage1 > 0 && quality1 != quality2 ? "meetsbonusrequirementtwice" : "meetsbonusrequirement";
|
||||
|
||||
var variables = new (string Key, LocalizedString Value)[]
|
||||
{
|
||||
("[chance]", chance1text), ("[quality]", quality1Text),
|
||||
("[chance2]", chance2text), ("[quality2]", quality2Text)
|
||||
};
|
||||
|
||||
if (MathUtils.NearlyEqual(percentage1, 0))
|
||||
{
|
||||
variables = new[] { ("[chance]", chance2text), ("[quality]", quality2Text) };
|
||||
}
|
||||
|
||||
if (quality1 == quality2)
|
||||
{
|
||||
LocalizedString rawPercentage = result.PlusOnePercentage.ToString("F1", CultureInfo.InvariantCulture);
|
||||
variables = new[] { ("[chance]", rawPercentage), ("[quality]", quality1Text) };
|
||||
}
|
||||
|
||||
LocalizedString qualityTooltip = TextManager.GetWithVariables(localizationTag, variables);
|
||||
|
||||
icon.ToolTip = RichString.Rich(qualityTooltip);
|
||||
icon.Visible = icon.CanBeFocused = true;
|
||||
}
|
||||
|
||||
outputTopArea.RectTransform.MaxSize = new Point(int.MaxValue, outputInventoryHolder.Rect.Height);
|
||||
paddedOutputArea.Recalculate();
|
||||
|
||||
nameBlock.Padding = new Vector4(0, nameBlock.Padding.Y, GUI.IntScale(5), nameBlock.Padding.W);
|
||||
if (nameBlock.TextScale < 0.7f)
|
||||
{
|
||||
@@ -932,31 +1114,41 @@ namespace Barotrauma.Items.Components
|
||||
nameBlock.RectTransform.MinSize = new Point(0, (int)(nameBlock.TextSize.Y * nameBlock.TextScale));
|
||||
}
|
||||
|
||||
if (!selectedItem.TargetItem.Description.IsNullOrEmpty())
|
||||
bool largeUI = GuiFrame.Rect.Height > GUI.IntScale(500);
|
||||
if (largeUI)
|
||||
{
|
||||
var description = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedFrame.RectTransform),
|
||||
RichString.Rich(selectedItem.TargetItem.Description),
|
||||
font: GUIStyle.SmallFont, wrap: true);
|
||||
description.Padding = new Vector4(0, description.Padding.Y, description.Padding.Z, description.Padding.W);
|
||||
paddedFrame.ChildAnchor = Anchor.CenterLeft;
|
||||
}
|
||||
|
||||
while (description.Rect.Height + nameBlock.Rect.Height > paddedFrame.Rect.Height)
|
||||
if (!selectedRecipe.TargetItem.Description.IsNullOrEmpty())
|
||||
{
|
||||
var descriptionParent = largeUI ? paddedReqFrame : paddedFrame;
|
||||
var description = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), descriptionParent.RectTransform),
|
||||
RichString.Rich(selectedRecipe.TargetItem.Description),
|
||||
font: GUIStyle.SmallFont, wrap: true);
|
||||
if (!largeUI)
|
||||
{
|
||||
description.Padding = new Vector4(0, description.Padding.Y, description.Padding.Z, description.Padding.W);
|
||||
}
|
||||
|
||||
while (description.Rect.Height + nameBlock.Rect.Height > descriptionParent.Rect.Height)
|
||||
{
|
||||
var lines = description.WrappedText.Split('\n');
|
||||
if (lines.Count <= 1) { break; }
|
||||
var newString = string.Join('\n', lines.Take(lines.Count - 1));
|
||||
description.Text = newString.Substring(0, newString.Length - 4) + "...";
|
||||
description.CalculateHeightFromText();
|
||||
description.ToolTip = selectedItem.TargetItem.Description;
|
||||
description.ToolTip = selectedRecipe.TargetItem.Description;
|
||||
}
|
||||
}
|
||||
|
||||
IEnumerable<Skill> inadequateSkills = Enumerable.Empty<Skill>();
|
||||
if (user != null)
|
||||
{
|
||||
inadequateSkills = selectedItem.RequiredSkills.Where(skill => user.GetSkillLevel(skill.Identifier) < Math.Round(skill.Level * SkillRequirementMultiplier));
|
||||
inadequateSkills = selectedRecipe.RequiredSkills.Where(skill => user.GetSkillLevel(skill.Identifier) < Math.Round(skill.Level * SkillRequirementMultiplier));
|
||||
}
|
||||
|
||||
if (selectedItem.RequiredSkills.Any())
|
||||
if (selectedRecipe.RequiredSkills.Any())
|
||||
{
|
||||
LocalizedString text = "";
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedReqFrame.RectTransform),
|
||||
@@ -965,20 +1157,20 @@ namespace Barotrauma.Items.Components
|
||||
AutoScaleHorizontal = true,
|
||||
ToolTip = TextManager.Get("fabricatorrequiredskills.tooltip")
|
||||
};
|
||||
foreach (Skill skill in selectedItem.RequiredSkills)
|
||||
foreach (Skill skill in selectedRecipe.RequiredSkills)
|
||||
{
|
||||
text += TextManager.Get("SkillName." + skill.Identifier) + " " + TextManager.Get("Lvl").ToLower() + " " + Math.Round(skill.Level * SkillRequirementMultiplier);
|
||||
if (skill != selectedItem.RequiredSkills.Last()) { text += "\n"; }
|
||||
if (skill != selectedRecipe.RequiredSkills.Last()) { text += "\n"; }
|
||||
}
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedReqFrame.RectTransform), text, font: GUIStyle.SmallFont);
|
||||
}
|
||||
|
||||
float degreeOfSuccess = user == null ? 0.0f : FabricationDegreeOfSuccess(user, selectedItem.RequiredSkills);
|
||||
float degreeOfSuccess = user == null ? 0.0f : FabricationDegreeOfSuccess(user, selectedRecipe.RequiredSkills);
|
||||
if (degreeOfSuccess > 0.5f) { degreeOfSuccess = 1.0f; }
|
||||
|
||||
float requiredTime = overrideRequiredTime.TryUnwrap(out var time)
|
||||
? time
|
||||
: (user == null ? selectedItem.RequiredTime : GetRequiredTime(selectedItem, user));
|
||||
: (user == null ? selectedRecipe.RequiredTime : GetRequiredTime(selectedRecipe, user));
|
||||
|
||||
if ((int)requiredTime > 0)
|
||||
{
|
||||
@@ -991,7 +1183,7 @@ namespace Barotrauma.Items.Components
|
||||
font: GUIStyle.SmallFont);
|
||||
}
|
||||
|
||||
if (SelectedItem.RequiredMoney > 0)
|
||||
if (selectedRecipe.RequiredMoney > 0)
|
||||
{
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedReqFrame.RectTransform),
|
||||
TextManager.Get("subeditor.price"), textColor: ToolBox.GradientLerp(degreeOfSuccess, GUIStyle.Red, Color.Yellow, GUIStyle.Green), font: GUIStyle.SubHeadingFont)
|
||||
@@ -1000,7 +1192,6 @@ namespace Barotrauma.Items.Components
|
||||
};
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedReqFrame.RectTransform), TextManager.FormatCurrency(SelectedItem.RequiredMoney),
|
||||
font: GUIStyle.SmallFont);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1031,7 +1222,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
if (selectedItem == null) { return false; }
|
||||
if (fabricatedItem == null &&
|
||||
!outputContainer.Inventory.CanBePut(selectedItem.TargetItem, selectedItem.OutCondition * selectedItem.TargetItem.Health))
|
||||
!outputContainer.Inventory.CanProbablyBePut(selectedItem.TargetItem, selectedItem.OutCondition * selectedItem.TargetItem.Health))
|
||||
{
|
||||
outputSlot.Flash(GUIStyle.Red);
|
||||
return false;
|
||||
@@ -1101,8 +1292,14 @@ namespace Barotrauma.Items.Components
|
||||
activateButton.Enabled = canBeFabricated;
|
||||
}
|
||||
|
||||
bool sufficientSkills = FabricationDegreeOfSuccess(character, recipe.RequiredSkills) >= 0.5f;
|
||||
|
||||
Color baseColor = MissingRequiredRecipe(recipe, character) ?
|
||||
GUIStyle.Red :
|
||||
(sufficientSkills ? GUIStyle.TextColorNormal : GUIStyle.Orange);
|
||||
|
||||
var childContainer = child.GetChild<GUILayoutGroup>();
|
||||
childContainer.GetChild<GUITextBlock>().TextColor = Color.White * (canBeFabricated ? 1.0f : 0.5f);
|
||||
childContainer.GetChild<GUITextBlock>().TextColor = baseColor * (canBeFabricated ? 1.0f : 0.5f);
|
||||
childContainer.GetChild<GUIImage>().Color = recipe.TargetItem.InventoryIconColor * (canBeFabricated ? 1.0f : 0.5f);
|
||||
|
||||
var limitReachedText = child.FindChild(nameof(FabricationLimitReachedText));
|
||||
|
||||
@@ -10,45 +10,27 @@ using Microsoft.Xna.Framework.Input;
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
{
|
||||
internal readonly struct MiniMapGUIComponent
|
||||
internal readonly record struct MiniMapGUIComponent(GUIComponent RectComponent, GUIComponent BorderComponent)
|
||||
{
|
||||
public readonly GUIComponent RectComponent;
|
||||
public readonly GUIComponent BorderComponent;
|
||||
|
||||
public MiniMapGUIComponent(GUIComponent rectComponent)
|
||||
public MiniMapGUIComponent(GUIComponent rectComponent) : this(rectComponent, rectComponent)
|
||||
{
|
||||
RectComponent = rectComponent;
|
||||
BorderComponent = rectComponent;
|
||||
}
|
||||
|
||||
public MiniMapGUIComponent(GUIComponent frame, GUIComponent linkedHullComponent)
|
||||
{
|
||||
RectComponent = frame;
|
||||
BorderComponent = linkedHullComponent;
|
||||
}
|
||||
|
||||
|
||||
public void Deconstruct(out GUIComponent component, out GUIComponent borderComponent)
|
||||
{
|
||||
component = RectComponent;
|
||||
borderComponent = BorderComponent;
|
||||
}
|
||||
}
|
||||
|
||||
internal readonly struct MiniMapSprite
|
||||
|
||||
internal readonly record struct MiniMapSprite(Sprite? Sprite, Color Color)
|
||||
{
|
||||
public readonly Sprite? Sprite;
|
||||
public readonly Color Color;
|
||||
|
||||
public MiniMapSprite(JobPrefab prefab)
|
||||
public MiniMapSprite(JobPrefab prefab) : this(prefab.IconSmall, prefab.UIColor)
|
||||
{
|
||||
Sprite = prefab.IconSmall;
|
||||
Color = prefab.UIColor;
|
||||
}
|
||||
|
||||
public MiniMapSprite(Order order)
|
||||
|
||||
public MiniMapSprite(Order order) : this(order.SymbolSprite, order.Color)
|
||||
{
|
||||
Sprite = order.SymbolSprite;
|
||||
Color = order.Color;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -223,7 +205,27 @@ namespace Barotrauma.Items.Components
|
||||
NoPowerColor = MiniMapBaseColor * 0.1f,
|
||||
ElectricalBaseColor = GUIStyle.Orange,
|
||||
NoPowerElectricalColor = ElectricalBaseColor * 0.1f;
|
||||
|
||||
|
||||
// If this is portable, only allow displaying data in the player sub (not enemy subs, ruins, wrecks or other unknown places)
|
||||
private bool IsPortableItemAllowed
|
||||
{
|
||||
get
|
||||
{
|
||||
if (IsUsableOutsidePlayerSub) { return true; }
|
||||
if (item.Submarine == null) { return false; }
|
||||
if (item.GetComponent<Pickable>() is not Pickable handheldItem) { return true; }
|
||||
// This will effectively make sure wherever we are, it belongs to the player
|
||||
return handheldItem.Picker?.TeamID == item.Submarine.TeamID;
|
||||
}
|
||||
}
|
||||
|
||||
[Serialize(false, IsPropertySaveable.No, description: "If this item is portable, should it be usable outside the player submarine?")]
|
||||
public bool IsUsableOutsidePlayerSub
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
partial void InitProjSpecific()
|
||||
{
|
||||
hullDatas = new Dictionary<Hull, HullData>();
|
||||
@@ -425,22 +427,25 @@ namespace Barotrauma.Items.Components
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool VisibleOnItemFinder(Item it)
|
||||
private bool VisibleOnItemFinder(Item targetItem)
|
||||
{
|
||||
if (it?.Submarine == null) { return false; }
|
||||
if (item.Submarine == null || !item.Submarine.IsEntityFoundOnThisSub(it, includingConnectedSubs: true)) { return false; }
|
||||
if (it.NonInteractable || it.IsHidden) { return false; }
|
||||
if (it.GetComponent<Pickable>() == null) { return false; }
|
||||
if (targetItem?.Submarine == null || item.Submarine == null) { return false; }
|
||||
|
||||
var holdable = it.GetComponent<Holdable>();
|
||||
if (!IsPortableItemAllowed) { return false; }
|
||||
|
||||
if (!item.Submarine.IsEntityFoundOnThisSub(targetItem, includingConnectedSubs: true)) { return false; }
|
||||
if (targetItem.NonInteractable || targetItem.IsHidden) { return false; }
|
||||
if (targetItem.GetComponent<Pickable>() == null) { return false; }
|
||||
|
||||
var holdable = targetItem.GetComponent<Holdable>();
|
||||
if (holdable != null && holdable.Attached) { return false; }
|
||||
|
||||
var wire = it.GetComponent<Wire>();
|
||||
var wire = targetItem.GetComponent<Wire>();
|
||||
if (wire != null && wire.Connections.Any(c => c != null)) { return false; }
|
||||
|
||||
if (it.Container?.GetComponent<ItemContainer>() is { DrawInventory: false } or { AllowAccess: false }) { return false; }
|
||||
if (targetItem.Container?.GetComponent<ItemContainer>() is { DrawInventory: false } or { AllowAccess: false }) { return false; }
|
||||
|
||||
if (it.HasTag(Tags.TraitorMissionItem)) { return false; }
|
||||
if (targetItem.HasTag(Tags.TraitorMissionItem)) { return false; }
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -454,18 +459,24 @@ namespace Barotrauma.Items.Components
|
||||
searchAutoComplete?.AddToGUIUpdateList(order: order + 1);
|
||||
}
|
||||
}
|
||||
|
||||
private void CreateHUD()
|
||||
|
||||
private void ClearHUD()
|
||||
{
|
||||
subEntities.Clear();
|
||||
prevResolution = new Point(GameMain.GraphicsWidth, GameMain.GraphicsHeight);
|
||||
submarineContainer.ClearChildren();
|
||||
displayedSubs.Clear();
|
||||
}
|
||||
|
||||
if (item.Submarine is null)
|
||||
private void RefreshHUD()
|
||||
{
|
||||
ClearHUD();
|
||||
|
||||
if (item.Submarine is null || !IsPortableItemAllowed)
|
||||
{
|
||||
displayedSubs.Clear();
|
||||
return;
|
||||
}
|
||||
|
||||
prevResolution = new Point(GameMain.GraphicsWidth, GameMain.GraphicsHeight);
|
||||
|
||||
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 };
|
||||
@@ -574,18 +585,25 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public override void UpdateHUDComponentSpecific(Character character, float deltaTime, Camera cam)
|
||||
{
|
||||
//recreate HUD if the subs we should display have changed
|
||||
if (item.Submarine == null && displayedSubs.Count > 0 || // item not inside a sub anymore, but display is still showing subs
|
||||
// Refresh HUD (including possibly just clearing it away) if the subs we should display have changed
|
||||
if (item.Submarine == null && displayedSubs.Count > 0 || // item not inside a sub anymore, but display is still showing subs
|
||||
item.Submarine is { } itemSub &&
|
||||
(
|
||||
!displayedSubs.Contains(itemSub) || // current sub not displayed
|
||||
itemSub.DockedTo.Where(s => s.TeamID == item.Submarine.TeamID).Any(s => !displayedSubs.Contains(s) && itemSub.ConnectedDockingPorts[s].IsLocked) || // some of the docked subs not displayed
|
||||
displayedSubs.Any(s => s != itemSub && !itemSub.DockedTo.Contains(s)) // displaying a sub that shouldn't be displayed
|
||||
// current sub not displayed
|
||||
!displayedSubs.Contains(itemSub) ||
|
||||
// some of the docked subs not displayed
|
||||
itemSub.DockedTo.Where(s => s.TeamID == item.Submarine.TeamID).Any(s => !displayedSubs.Contains(s) && itemSub.ConnectedDockingPorts[s].IsLocked) ||
|
||||
// displaying a sub that shouldn't be displayed
|
||||
displayedSubs.Any(s => s != itemSub && !itemSub.DockedTo.Contains(s))
|
||||
) ||
|
||||
prevResolution.X != GameMain.GraphicsWidth || prevResolution.Y != GameMain.GraphicsHeight || // resolution changed
|
||||
!submarineContainer.Children.Any()) // We lack a GUI
|
||||
// If this item is portable and not in a player sub and using it otherwise is disallowed
|
||||
!IsPortableItemAllowed ||
|
||||
// resolution changed
|
||||
prevResolution.X != GameMain.GraphicsWidth || prevResolution.Y != GameMain.GraphicsHeight ||
|
||||
// We lack a GUI
|
||||
!submarineContainer.Children.Any())
|
||||
{
|
||||
CreateHUD();
|
||||
RefreshHUD();
|
||||
}
|
||||
|
||||
//reset data if we haven't received anything in a while
|
||||
@@ -737,7 +755,7 @@ namespace Barotrauma.Items.Components
|
||||
return;
|
||||
}
|
||||
|
||||
if (Voltage < MinVoltage)
|
||||
if (!HasPower)
|
||||
{
|
||||
Vector2 textSize = GUIStyle.Font.MeasureString(noPowerTip);
|
||||
Vector2 textPos = GuiFrame.Rect.Center.ToVector2();
|
||||
@@ -747,7 +765,7 @@ namespace Barotrauma.Items.Components
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentMode == MiniMapMode.HullStatus && item.Submarine != null)
|
||||
if (currentMode == MiniMapMode.HullStatus && item.Submarine != null && IsPortableItemAllowed)
|
||||
{
|
||||
Rectangle prevScissorRect = spriteBatch.GraphicsDevice.ScissorRectangle;
|
||||
spriteBatch.End();
|
||||
@@ -958,19 +976,19 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
MiniMapBlips = positions.ToImmutableHashSet();
|
||||
|
||||
if (searchAutoComplete is null) { return; }
|
||||
searchAutoComplete.Visible = false;
|
||||
HideGUIComponent(searchAutoComplete);
|
||||
}
|
||||
|
||||
private void UpdateHUDBack()
|
||||
{
|
||||
if (item.Submarine == null) { return; }
|
||||
|
||||
if (hullInfoFrame != null) { hullInfoFrame.Visible = false; }
|
||||
reportFrame.Visible = false;
|
||||
searchBarFrame.Visible = false;
|
||||
electricalFrame.Visible = false;
|
||||
miniMapFrame.Visible = false;
|
||||
// Clear up mode-specific elements before checking if drawing should continue, so they'll be gone if not
|
||||
HideModeSpecificFrames();
|
||||
|
||||
if (item.Submarine == null || !IsPortableItemAllowed)
|
||||
{
|
||||
ClearHUD();
|
||||
return;
|
||||
}
|
||||
|
||||
switch (currentMode)
|
||||
{
|
||||
@@ -988,7 +1006,24 @@ namespace Barotrauma.Items.Components
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void HideModeSpecificFrames()
|
||||
{
|
||||
HideGUIComponent(hullInfoFrame);
|
||||
HideGUIComponent(reportFrame);
|
||||
HideGUIComponent(searchBarFrame);
|
||||
HideGUIComponent(electricalFrame);
|
||||
HideGUIComponent(miniMapFrame);
|
||||
}
|
||||
|
||||
private static void HideGUIComponent(GUIComponent? component)
|
||||
{
|
||||
if (component != null)
|
||||
{
|
||||
component.Visible = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateHullStatus()
|
||||
{
|
||||
bool canHoverOverHull = true;
|
||||
@@ -1007,7 +1042,7 @@ namespace Barotrauma.Items.Components
|
||||
child.Color = child.OutlineColor = NoPowerDoorColor;
|
||||
}
|
||||
|
||||
if (Voltage < MinVoltage) { continue; }
|
||||
if (!HasPower) { continue; }
|
||||
|
||||
child.Color = child.OutlineColor = DoorIndicatorColor;
|
||||
if (GUI.MouseOn == child)
|
||||
@@ -1037,7 +1072,7 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
if (Voltage < MinVoltage) { continue; }
|
||||
if (!HasPower) { continue; }
|
||||
|
||||
hullDatas.TryGetValue(hull, out HullData? hullData);
|
||||
if (hullData is null)
|
||||
@@ -1187,7 +1222,7 @@ namespace Barotrauma.Items.Components
|
||||
component.Color = component.OutlineColor = NoPowerElectricalColor;
|
||||
}
|
||||
|
||||
if (Voltage < MinVoltage || !miniMapGuiComponent.RectComponent.Visible) { continue; }
|
||||
if (!HasPower || !miniMapGuiComponent.RectComponent.Visible) { continue; }
|
||||
|
||||
int durability = (int)(it.Condition / (it.MaxCondition / it.MaxRepairConditionMultiplier) * 100f);
|
||||
Color color = ToolBox.GradientLerp(durability / 100f, GUIStyle.Red, GUIStyle.Orange, GUIStyle.Green, GUIStyle.Green);
|
||||
@@ -1229,11 +1264,11 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
private void DrawHUDBack(SpriteBatch spriteBatch, GUICustomComponent container)
|
||||
{
|
||||
if (item.Submarine == null) { return; }
|
||||
if (item.Submarine == null || !IsPortableItemAllowed) { return; }
|
||||
|
||||
DrawSubmarine(spriteBatch);
|
||||
DrawSubmarine(spriteBatch);
|
||||
|
||||
if (Voltage < MinVoltage) { return; }
|
||||
if (!HasPower) { return; }
|
||||
Rectangle prevScissorRect = spriteBatch.GraphicsDevice.ScissorRectangle;
|
||||
spriteBatch.End();
|
||||
spriteBatch.Begin(SpriteSortMode.Deferred, samplerState: GUI.SamplerState, rasterizerState: GameMain.ScissorTestEnable);
|
||||
|
||||
@@ -475,11 +475,8 @@ namespace Barotrauma.Items.Components
|
||||
if (sound != null)
|
||||
{
|
||||
SoundPlayer.PlaySound(
|
||||
sound.Sound,
|
||||
sound,
|
||||
item.WorldPosition,
|
||||
sound.Volume,
|
||||
sound.Range,
|
||||
freqMult: sound.GetRandomFrequencyMultiplier(),
|
||||
hullGuess: item.CurrentHull);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,6 +144,7 @@ namespace Barotrauma.Items.Components
|
||||
private bool isConnectedToSteering;
|
||||
|
||||
private static LocalizedString caveLabel;
|
||||
private static LocalizedString enemyLabel;
|
||||
|
||||
|
||||
[Serialize(false, IsPropertySaveable.Yes)]
|
||||
@@ -164,6 +165,8 @@ namespace Barotrauma.Items.Components
|
||||
TextManager.Get("cave").Fallback(
|
||||
TextManager.Get("missiontype.nest"));
|
||||
|
||||
enemyLabel = TextManager.Get("enemysubmarine");
|
||||
|
||||
foreach (var subElement in element.Elements())
|
||||
{
|
||||
switch (subElement.Name.ToString().ToLowerInvariant())
|
||||
@@ -216,8 +219,9 @@ namespace Barotrauma.Items.Components
|
||||
Vector2 size = isConnectedToSteering ? controlBoxSize : new Vector2(0.46f, 0.4f);
|
||||
|
||||
controlContainer = new GUIFrame(new RectTransform(size, GuiFrame.RectTransform, Anchor.BottomLeft), "ItemUI");
|
||||
if (!isConnectedToSteering && !GUI.IsFourByThree())
|
||||
if (!isConnectedToSteering && GUI.AspectRatioDifference <= 0)
|
||||
{
|
||||
// In wider than 4:3 aspect ratio, we'll limit the max size.
|
||||
controlContainer.RectTransform.MaxSize = new Point((int)(380 * GUI.xScale), (int)(300 * GUI.yScale));
|
||||
}
|
||||
var paddedControlContainer = new GUIFrame(new RectTransform(controlContainer.Rect.Size - GUIStyle.ItemFrameMargin, controlContainer.RectTransform, Anchor.Center)
|
||||
@@ -1019,6 +1023,38 @@ namespace Barotrauma.Items.Components
|
||||
cave.StartPos.ToVector2(), transducerCenter,
|
||||
DisplayScale, center, DisplayRadius);
|
||||
}
|
||||
|
||||
if (GameMain.NetworkMember is { } networkMember && GameMain.GameSession?.GameMode is PvPMode)
|
||||
{
|
||||
if (networkMember.ServerSettings.TrackOpponentInPvP
|
||||
&& Submarine.MainSubs[0] is { } coalitionSub
|
||||
&& Submarine.MainSubs[1] is { } separatistSub
|
||||
&& Character.Controlled is { } player)
|
||||
{
|
||||
Submarine whichSubToDraw = player.TeamID switch
|
||||
{
|
||||
CharacterTeamType.Team1 => separatistSub,
|
||||
CharacterTeamType.Team2 => coalitionSub,
|
||||
_ => null
|
||||
};
|
||||
|
||||
if (whichSubToDraw != null)
|
||||
{
|
||||
DrawOffsetMarker(spriteBatch,
|
||||
enemyLabel.Value,
|
||||
Tags.Submarine,
|
||||
Tags.Enemy,
|
||||
whichSubToDraw.WorldPosition,
|
||||
transducerCenter,
|
||||
distanceThresholds: new Range<float>(start: MetersToUnits(150), end: MetersToUnits(1600)),
|
||||
offset: new Range<float>(start: MetersToUnits(100), end: MetersToUnits(400)),
|
||||
minOffset: MetersToUnits(10));
|
||||
|
||||
static float MetersToUnits(float m)
|
||||
=> m / Physics.DisplayToRealWorldRatio;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int missionIndex = 0;
|
||||
@@ -1042,7 +1078,8 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
|
||||
if (HasMineralScanner && UseMineralScanner && CurrentMode == Mode.Active && MineralClusters != null &&
|
||||
(item.CurrentHull == null || !DetectSubmarineWalls))
|
||||
(item.CurrentHull == null || !DetectSubmarineWalls) &&
|
||||
HasPower)
|
||||
{
|
||||
foreach (var c in MineralClusters)
|
||||
{
|
||||
@@ -1076,7 +1113,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
if (!sub.ShowSonarMarker) { continue; }
|
||||
if (connectedSubs.Contains(sub)) { continue; }
|
||||
if (Level.Loaded != null && sub.WorldPosition.Y > Level.Loaded.Size.Y) { continue; }
|
||||
if (sub.IsAboveLevel) { continue; }
|
||||
|
||||
if (item.Submarine != null || Character.Controlled != null)
|
||||
{
|
||||
@@ -1185,7 +1222,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.Submarine.IsAboveLevel) { continue; }
|
||||
if (dockingPort.Item.IsHidden) { continue; }
|
||||
if (dockingPort.Item.Submarine == null) { continue; }
|
||||
if (dockingPort.Item.Submarine.Info.IsWreck) { continue; }
|
||||
@@ -1198,8 +1235,8 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
//don't show the docking ports of the opposing team on the sonar
|
||||
if (item.Submarine != null &&
|
||||
item.Submarine != GameMain.NetworkMember?.RespawnManager?.RespawnShuttle &&
|
||||
dockingPort.Item.Submarine != GameMain.NetworkMember?.RespawnManager?.RespawnShuttle &&
|
||||
!item.Submarine.IsRespawnShuttle &&
|
||||
!dockingPort.Item.Submarine.IsRespawnShuttle &&
|
||||
!dockingPort.Item.Submarine.Info.IsOutpost &&
|
||||
!dockingPort.Item.Submarine.Info.IsBeacon)
|
||||
{
|
||||
@@ -1792,8 +1829,47 @@ namespace Barotrauma.Items.Components
|
||||
sonarBlip.Draw(spriteBatch, center + pos, color * 0.5f * blip.Alpha, sonarBlip.Origin, 0, scale, SpriteEffects.None, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used in DrawOffsetMarker to cache the randomized location of the marker
|
||||
/// </summary>
|
||||
private readonly Dictionary<Identifier, CachedLocation> cachedLocations = new Dictionary<Identifier, CachedLocation>();
|
||||
|
||||
private void DrawOffsetMarker(SpriteBatch spriteBatch, string label, Identifier iconIdentifier, Identifier targetIdentifier, Vector2 worldPosition, Vector2 transducerPosition, Range<float> distanceThresholds, Range<float> offset, float minOffset)
|
||||
{
|
||||
Vector2 pos;
|
||||
|
||||
if (!cachedLocations.TryGetValue(targetIdentifier, out CachedLocation cachedLocation))
|
||||
{
|
||||
cachedLocation = CreateCachedLocation();
|
||||
cachedLocations.Add(targetIdentifier, cachedLocation);
|
||||
pos = cachedLocation.Location;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Timing.TotalTime > cachedLocation.RecalculationTime)
|
||||
{
|
||||
cachedLocation = CreateCachedLocation();
|
||||
cachedLocations[targetIdentifier] = cachedLocation;
|
||||
}
|
||||
|
||||
pos = cachedLocation.Location;
|
||||
}
|
||||
|
||||
DrawMarker(spriteBatch, label, iconIdentifier, targetIdentifier, pos, transducerPosition, DisplayScale, center, DisplayRadius);
|
||||
|
||||
CachedLocation CreateCachedLocation()
|
||||
{
|
||||
float distance = Vector2.Distance(worldPosition, transducerPosition);
|
||||
|
||||
float maxOffset = MathHelper.Lerp(offset.Start, offset.End, MathHelper.Clamp((distance - distanceThresholds.Start) / (distanceThresholds.End - distanceThresholds.Start), 0.0f, 1.0f));
|
||||
|
||||
Vector2 randomPos = Rand.Vector(Rand.Range(minOffset, maxOffset));
|
||||
return new CachedLocation(worldPosition + randomPos, Timing.TotalTime + Rand.Range(10.0f, 30.0f));
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawMarker(SpriteBatch spriteBatch, string label, Identifier iconIdentifier, object targetIdentifier, Vector2 worldPosition, Vector2 transducerPosition, float scale, Vector2 center, float radius,
|
||||
bool onlyShowTextOnMouseOver = false)
|
||||
bool onlyShowTextOnMouseOver = false)
|
||||
{
|
||||
float linearDist = Vector2.Distance(worldPosition, transducerPosition);
|
||||
float dist = linearDist;
|
||||
@@ -1903,25 +1979,6 @@ namespace Barotrauma.Items.Components
|
||||
2, GUIStyle.SmallFont);
|
||||
}
|
||||
|
||||
protected override void RemoveComponentSpecific()
|
||||
{
|
||||
base.RemoveComponentSpecific();
|
||||
sonarBlip?.Remove();
|
||||
pingCircle?.Remove();
|
||||
directionalPingCircle?.Remove();
|
||||
screenOverlay?.Remove();
|
||||
screenBackground?.Remove();
|
||||
lineSprite?.Remove();
|
||||
|
||||
foreach (var t in targetIcons.Values)
|
||||
{
|
||||
t.Item1.Remove();
|
||||
}
|
||||
targetIcons.Clear();
|
||||
|
||||
MineralClusters = null;
|
||||
}
|
||||
|
||||
public void ClientEventWrite(IWriteMessage msg, NetEntityEvent.IData extraData = null)
|
||||
{
|
||||
msg.WriteBoolean(currentMode == Mode.Active);
|
||||
|
||||
@@ -57,24 +57,42 @@ namespace Barotrauma.Items.Components
|
||||
private GUIMessageBox enterOutpostPrompt, exitOutpostPrompt;
|
||||
|
||||
private bool levelStartSelected;
|
||||
[Serialize(defaultValue: false, isSaveable: IsPropertySaveable.Yes, AlwaysUseInstanceValues = true)]
|
||||
public bool LevelStartSelected
|
||||
{
|
||||
get { return levelStartTickBox.Selected; }
|
||||
set { levelStartTickBox.Selected = value; }
|
||||
get
|
||||
{
|
||||
return levelStartTickBox?.Selected ?? levelStartSelected;
|
||||
}
|
||||
set
|
||||
{
|
||||
TrySetTickBoxSelected(levelStartTickBox, ref levelStartSelected, value);
|
||||
}
|
||||
}
|
||||
|
||||
private bool levelEndSelected;
|
||||
[Serialize(defaultValue: false, isSaveable: IsPropertySaveable.Yes, AlwaysUseInstanceValues = true)]
|
||||
public bool LevelEndSelected
|
||||
{
|
||||
get { return levelEndTickBox.Selected; }
|
||||
set { levelEndTickBox.Selected = value; }
|
||||
get { return levelEndTickBox?.Selected ?? levelEndSelected; }
|
||||
set
|
||||
{
|
||||
TrySetTickBoxSelected(levelEndTickBox, ref levelEndSelected, value);
|
||||
}
|
||||
}
|
||||
|
||||
private bool maintainPos;
|
||||
[Serialize(defaultValue: false, isSaveable: IsPropertySaveable.Yes, AlwaysUseInstanceValues = true)]
|
||||
public bool MaintainPos
|
||||
{
|
||||
get { return maintainPosTickBox.Selected; }
|
||||
set { maintainPosTickBox.Selected = value; }
|
||||
get
|
||||
{
|
||||
return maintainPosTickBox?.Selected ?? maintainPos;
|
||||
}
|
||||
set
|
||||
{
|
||||
TrySetTickBoxSelected(maintainPosTickBox, ref maintainPos, value);
|
||||
}
|
||||
}
|
||||
|
||||
private float steerRadius;
|
||||
@@ -554,7 +572,7 @@ namespace Barotrauma.Items.Components
|
||||
int x = rect.X;
|
||||
int y = rect.Y;
|
||||
|
||||
if (Voltage < MinVoltage) { return; }
|
||||
if (!HasPower) { return; }
|
||||
|
||||
Rectangle velRect = new Rectangle(x + 20, y + 20, width - 40, height - 40);
|
||||
Vector2 steeringOrigin = steerArea.Rect.Center.ToVector2();
|
||||
@@ -759,7 +777,7 @@ namespace Barotrauma.Items.Components
|
||||
dockingButton.Text = dockText;
|
||||
}
|
||||
|
||||
if (Voltage < MinVoltage)
|
||||
if (!HasPower)
|
||||
{
|
||||
tipContainer.Visible = true;
|
||||
tipContainer.Text = noPowerTip;
|
||||
@@ -829,7 +847,7 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
if (!AutoPilot && Character.DisableControls && GUI.KeyboardDispatcher.Subscriber == null)
|
||||
{
|
||||
steeringAdjustSpeed = character == null ? DefaultSteeringAdjustSpeed : MathHelper.Lerp(0.2f, 1.0f, character.GetSkillLevel("helm") / 100.0f);
|
||||
steeringAdjustSpeed = character == null ? DefaultSteeringAdjustSpeed : MathHelper.Lerp(0.2f, 1.0f, character.GetSkillLevel(Tags.HelmSkill) / 100.0f);
|
||||
Vector2 input = Vector2.Zero;
|
||||
if (PlayerInput.KeyDown(InputType.Left)) { input -= Vector2.UnitX; }
|
||||
if (PlayerInput.KeyDown(InputType.Right)) { input += Vector2.UnitX; }
|
||||
@@ -909,7 +927,7 @@ 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; }
|
||||
if (targetPort.Item.Submarine.IsAboveLevel) { continue; }
|
||||
if (sourceDir == targetPort.GetDir()) { continue; }
|
||||
|
||||
float dist = Vector2.DistanceSquared(sourcePort.Item.WorldPosition, targetPort.Item.WorldPosition);
|
||||
@@ -924,6 +942,21 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the value of the specified tickbox, or if it hasn't been instantiated (yet?), just the value of the backing field.
|
||||
/// </summary>
|
||||
private void TrySetTickBoxSelected(GUITickBox tickBox, ref bool backingValue, bool newValue)
|
||||
{
|
||||
if (tickBox == null)
|
||||
{
|
||||
backingValue = newValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
tickBox.Selected = newValue;
|
||||
}
|
||||
}
|
||||
|
||||
private bool NudgeButtonClicked(GUIButton btn, object userdata)
|
||||
{
|
||||
if (!MaintainPos || !AutoPilot)
|
||||
|
||||
@@ -50,7 +50,7 @@ namespace Barotrauma.Items.Components
|
||||
Hull hull = Entity.FindEntityByID(hullID) as Hull;
|
||||
item.Submarine = submarine;
|
||||
item.CurrentHull = hull;
|
||||
item.body.SetTransform(simPosition, item.body.Rotation);
|
||||
item.body.SetTransformIgnoreContacts(simPosition, item.body.Rotation);
|
||||
|
||||
switch (targetType)
|
||||
{
|
||||
@@ -180,7 +180,11 @@ namespace Barotrauma.Items.Components
|
||||
switch (subElement.Name.ToString().ToLowerInvariant())
|
||||
{
|
||||
case "particleemitter":
|
||||
particleEmitters.Add(new ParticleEmitter(subElement));
|
||||
var emitter = new ParticleEmitter(subElement);
|
||||
//backwards compatibility: previously it was not possible to change if the particles use tracer points, they were always used on projectiles
|
||||
//now emitters don't use them by default, except on projectiles
|
||||
emitter.Prefab.Properties.UseTracerPoints = subElement.GetAttributeBool(nameof(emitter.Prefab.Properties.UseTracerPoints), true);
|
||||
particleEmitters.Add(emitter);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
public override void DrawHUD(SpriteBatch spriteBatch, Character character)
|
||||
{
|
||||
base.DrawHUD(spriteBatch, character);
|
||||
currentTarget?.DrawHUD(spriteBatch, Screen.Selected.Cam, character);
|
||||
}
|
||||
|
||||
|
||||
@@ -58,7 +58,6 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
partial void UseProjSpecific(float deltaTime, Vector2 raystart)
|
||||
{
|
||||
foreach (ParticleEmitter particleEmitter in particleEmitters)
|
||||
@@ -88,25 +87,18 @@ namespace Barotrauma.Items.Components
|
||||
MathUtils.InverseLerp(targetStructure.Prefab.MinHealth, targetStructure.Health, targetStructure.Health - targetStructure.SectionDamage(sectionIndex)),
|
||||
GUIStyle.Red, GUIStyle.Green);
|
||||
|
||||
if (progressBar != null) progressBar.Size = new Vector2(60.0f, 20.0f);
|
||||
|
||||
Vector2 particlePos = ConvertUnits.ToDisplayUnits(pickedPosition);
|
||||
if (targetStructure.Submarine != null) particlePos += targetStructure.Submarine.DrawPosition;
|
||||
if (progressBar != null) { progressBar.Size = new Vector2(60.0f, 20.0f); }
|
||||
foreach (var emitter in particleEmitterHitStructure)
|
||||
{
|
||||
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);
|
||||
EmitParticle(emitter, deltaTime, pickedPosition, targetStructure.Submarine);
|
||||
}
|
||||
}
|
||||
|
||||
partial void FixCharacterProjSpecific(Character user, float deltaTime, Character targetCharacter)
|
||||
{
|
||||
Vector2 particlePos = ConvertUnits.ToDisplayUnits(pickedPosition);
|
||||
if (targetCharacter.Submarine != null) particlePos += targetCharacter.Submarine.DrawPosition;
|
||||
foreach (var emitter in particleEmitterHitCharacter)
|
||||
{
|
||||
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);
|
||||
EmitParticle(emitter, deltaTime, pickedPosition, targetCharacter.Submarine);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -134,15 +126,22 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
Vector2 particlePos = ConvertUnits.ToDisplayUnits(pickedPosition);
|
||||
if (targetItem.Submarine != null) particlePos += targetItem.Submarine.DrawPosition;
|
||||
foreach ((RelatedItem relatedItem, ParticleEmitter emitter) in particleEmitterHitItem)
|
||||
{
|
||||
if (!relatedItem.MatchesItem(targetItem)) { continue; }
|
||||
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);
|
||||
EmitParticle(emitter, deltaTime, pickedPosition, targetItem.Submarine);
|
||||
}
|
||||
}
|
||||
|
||||
private void EmitParticle(ParticleEmitter emitter, float deltaTime, Vector2 simPosition, Submarine targetSub)
|
||||
{
|
||||
Vector2 particlePos = ConvertUnits.ToDisplayUnits(simPosition);
|
||||
if (targetSub != null) { particlePos += targetSub.DrawPosition; }
|
||||
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,
|
||||
tracerPoints: new Tuple<Vector2, Vector2>(item.WorldPosition + TransformedBarrelPos, particlePos));
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
public void Draw(SpriteBatch spriteBatch, bool editing, float itemDepth = -1, Color? overrideColor = null)
|
||||
{
|
||||
|
||||
@@ -299,6 +299,8 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public override void DrawHUD(SpriteBatch spriteBatch, Character character)
|
||||
{
|
||||
base.DrawHUD(spriteBatch, character);
|
||||
|
||||
IsActive = true;
|
||||
|
||||
float defaultMaxCondition = (item.MaxCondition / item.MaxRepairConditionMultiplier);
|
||||
|
||||
@@ -52,9 +52,11 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
Vector2 sourcePos = GetSourcePos();
|
||||
|
||||
//need to double the size because this is essentially just the radius, we need the diameter
|
||||
// + some extra margin to be on the safe side
|
||||
return new Vector2(
|
||||
Math.Abs(target.DrawPosition.X - sourcePos.X),
|
||||
Math.Abs(target.DrawPosition.Y - sourcePos.Y)) * 1.5f;
|
||||
Math.Abs(target.DrawPosition.Y - sourcePos.Y)) * 2.2f;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -122,7 +124,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
if (turret.BarrelSprite != null)
|
||||
{
|
||||
startPos += new Vector2((float)Math.Cos(turret.Rotation), (float)Math.Sin(turret.Rotation)) * turret.BarrelSprite.size.Y * turret.BarrelSprite.RelativeOrigin.Y * item.Scale * 0.9f;
|
||||
startPos += new Vector2((float)Math.Cos(turret.Rotation), (float)Math.Sin(turret.Rotation)) * turret.BarrelSprite.size.Y * turret.BarrelSprite.RelativeOrigin.Y * turret.Item.Scale * BarrelLengthMultiplier;
|
||||
}
|
||||
startPos -= turret.GetRecoilOffset();
|
||||
}
|
||||
@@ -227,7 +229,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
if (reelSoundChannel is not { IsPlaying: true })
|
||||
{
|
||||
reelSoundChannel = SoundPlayer.PlaySound(sound.Sound, position, sound.Volume, sound.Range, ignoreMuffling: sound.IgnoreMuffling, freqMult: sound.GetRandomFrequencyMultiplier());
|
||||
reelSoundChannel = SoundPlayer.PlaySound(sound, position);
|
||||
if (reelSoundChannel != null)
|
||||
{
|
||||
reelSoundChannel.Looping = true;
|
||||
@@ -242,7 +244,7 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
else
|
||||
{
|
||||
SoundPlayer.PlaySound(sound.Sound, position, sound.Volume, sound.Range, ignoreMuffling: sound.IgnoreMuffling, freqMult: sound.GetRandomFrequencyMultiplier());
|
||||
SoundPlayer.PlaySound(sound, position);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@ using Barotrauma.Networking;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
{
|
||||
@@ -16,7 +15,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
partial void InitProjSpecific(ContentXElement element)
|
||||
{
|
||||
terminalButtonStyles = new string[RequiredSignalCount];
|
||||
terminalButtonStyles = new string[requiredSignalCount];
|
||||
int i = 0;
|
||||
foreach (var childElement in element.GetChildElements("TerminalButton"))
|
||||
{
|
||||
@@ -38,11 +37,11 @@ namespace Barotrauma.Items.Components
|
||||
};
|
||||
paddedFrame.OnAddedToGUIUpdateList += (component) =>
|
||||
{
|
||||
bool buttonsEnabled = AllowUsingButtons;
|
||||
foreach (var child in component.Children)
|
||||
bool buttonsEnabled = IsActivated;
|
||||
foreach (GUIComponent child in component.Children)
|
||||
{
|
||||
if (!(child is GUIButton)) { continue; }
|
||||
if (!(child.UserData is int)) { continue; }
|
||||
if (child is not GUIButton) { continue; }
|
||||
if (child.UserData is not int) { continue; }
|
||||
child.Enabled = buttonsEnabled;
|
||||
child.Children.ForEach(c => c.Enabled = buttonsEnabled);
|
||||
}
|
||||
@@ -59,7 +58,7 @@ namespace Barotrauma.Items.Components
|
||||
containerIndicator.OverrideState = itemsContained ? GUIComponent.ComponentState.Selected : GUIComponent.ComponentState.None;
|
||||
};
|
||||
|
||||
float x = 1.0f / (1 + RequiredSignalCount);
|
||||
float x = 1.0f / (1 + requiredSignalCount);
|
||||
float y = Math.Min((x * paddedFrame.Rect.Width) / paddedFrame.Rect.Height, 0.5f);
|
||||
Vector2 relativeSize = new Vector2(x, y);
|
||||
|
||||
@@ -69,7 +68,7 @@ namespace Barotrauma.Items.Components
|
||||
containerIndicator = new GUIImage(new RectTransform(new Vector2(0.5f, 0.5f * (1.0f - y)), containerSection.RectTransform, anchor: Anchor.BottomCenter),
|
||||
style: "IndicatorLightRed", scaleToFit: true);
|
||||
|
||||
for (int i = 0; i < RequiredSignalCount; i++)
|
||||
for (int i = 0; i < requiredSignalCount; i++)
|
||||
{
|
||||
var button = new GUIButton(new RectTransform(relativeSize, paddedFrame.RectTransform), style: null)
|
||||
{
|
||||
@@ -111,7 +110,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public void ClientEventRead(IReadMessage msg, float sendingTime)
|
||||
{
|
||||
SendSignal(msg.ReadRangedInteger(0, Signals.Length - 1), sender: null, isServerMessage: true);
|
||||
SendSignal(msg.ReadRangedInteger(0, Signals.Length - 1), sender: null, ignoreState: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
#nullable enable
|
||||
#nullable enable
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@@ -129,7 +129,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public void RemoveComponents(IReadOnlyCollection<CircuitBoxComponent> node)
|
||||
{
|
||||
if (Locked) { return; }
|
||||
if (IsLocked()) { return; }
|
||||
var ids = node.Select(static n => n.ID).ToImmutableArray();
|
||||
|
||||
if (GameMain.NetworkMember is null)
|
||||
@@ -146,7 +146,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public void AddWire(CircuitBoxConnection one, CircuitBoxConnection two)
|
||||
{
|
||||
if (Locked) { return; }
|
||||
if (IsLocked()) { return; }
|
||||
if (GameMain.NetworkMember is null)
|
||||
{
|
||||
Connect(one, two, static delegate { }, CircuitBoxWire.SelectedWirePrefab);
|
||||
@@ -160,7 +160,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public void RemoveWires(IReadOnlyCollection<CircuitBoxWire> wires)
|
||||
{
|
||||
if (Locked) { return; }
|
||||
if (IsLocked()) { return; }
|
||||
var ids = wires.Select(static w => w.ID).ToImmutableArray();
|
||||
if (GameMain.NetworkMember is null)
|
||||
{
|
||||
@@ -230,7 +230,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public void MoveComponent(Vector2 moveAmount, IReadOnlyCollection<CircuitBoxNode> moveables)
|
||||
{
|
||||
if (Locked) { return; }
|
||||
if (IsLocked()) { return; }
|
||||
var ids = ImmutableArray.CreateBuilder<ushort>();
|
||||
var ios = ImmutableArray.CreateBuilder<CircuitBoxInputOutputNode.Type>();
|
||||
var labelIds = ImmutableArray.CreateBuilder<ushort>();
|
||||
@@ -265,7 +265,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public void AddComponent(ItemPrefab prefab, Vector2 pos)
|
||||
{
|
||||
if (Locked) { return; }
|
||||
if (IsLocked()) { return; }
|
||||
if (GameMain.NetworkMember is null)
|
||||
{
|
||||
ItemPrefab resource;
|
||||
@@ -292,7 +292,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public void RenameLabel(CircuitBoxLabelNode label, Color color, NetLimitedString header, NetLimitedString body)
|
||||
{
|
||||
if (Locked) { return; }
|
||||
if (IsLocked()) { return; }
|
||||
if (GameMain.NetworkMember is null)
|
||||
{
|
||||
label.EditText(header, body);
|
||||
@@ -316,7 +316,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public void ResizeNode(CircuitBoxNode node, CircuitBoxResizeDirection dir, Vector2 amount)
|
||||
{
|
||||
if (Locked) { return; }
|
||||
if (IsLocked()) { return; }
|
||||
var resize = node.ResizeBy(dir, amount);
|
||||
if (GameMain.NetworkMember is null)
|
||||
{
|
||||
@@ -341,7 +341,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public void AddLabel(Vector2 pos)
|
||||
{
|
||||
if (Locked) { return; }
|
||||
if (IsLocked()) { return; }
|
||||
if (GameMain.NetworkMember is null)
|
||||
{
|
||||
AddLabelInternal(ICircuitBoxIdentifiable.FindFreeID(Labels), GUIStyle.Blue, pos, CircuitBoxLabelNode.DefaultHeaderText, NetLimitedString.Empty);
|
||||
@@ -353,7 +353,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public void RemoveLabel(IReadOnlyCollection<CircuitBoxLabelNode> labels)
|
||||
{
|
||||
if (Locked) { return; }
|
||||
if (IsLocked()) { return; }
|
||||
if (!labels.Any()) { return; }
|
||||
|
||||
var ids = labels.Select(static n => n.ID).ToImmutableArray();
|
||||
|
||||
+147
-79
@@ -12,7 +12,9 @@ namespace Barotrauma.Items.Components
|
||||
private readonly List<GUIComponent> uiElements = new List<GUIComponent>();
|
||||
private GUILayoutGroup uiElementContainer;
|
||||
|
||||
private bool readingNetworkEvent;
|
||||
private bool suppressNetworkEvents;
|
||||
|
||||
private GUIComponent insufficientPowerWarning;
|
||||
|
||||
private Point ElementMaxSize => new Point(uiElementContainer.Rect.Width, (int)(65 * GUI.yScale));
|
||||
|
||||
@@ -40,7 +42,7 @@ namespace Barotrauma.Items.Components
|
||||
float elementSize = Math.Min(1.0f / visibleElements.Count(), 1);
|
||||
foreach (CustomInterfaceElement ciElement in visibleElements)
|
||||
{
|
||||
if (ciElement.HasPropertyName)
|
||||
if (ciElement.InputType is CustomInterfaceElement.InputTypeOption.Number or CustomInterfaceElement.InputTypeOption.Text)
|
||||
{
|
||||
var layoutGroup = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, elementSize), uiElementContainer.RectTransform), isHorizontal: true)
|
||||
{
|
||||
@@ -49,7 +51,7 @@ namespace Barotrauma.Items.Components
|
||||
};
|
||||
new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), layoutGroup.RectTransform),
|
||||
TextManager.Get(ciElement.Label).Fallback(ciElement.Label));
|
||||
if (!ciElement.IsNumberInput)
|
||||
if (ciElement.InputType is CustomInterfaceElement.InputTypeOption.Text)
|
||||
{
|
||||
var textBox = new GUITextBox(new RectTransform(new Vector2(0.5f, 1.0f), layoutGroup.RectTransform), ciElement.Signal, style: "GUITextBoxNoIcon")
|
||||
{
|
||||
@@ -68,7 +70,7 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
else
|
||||
{
|
||||
item.CreateClientEvent(this);
|
||||
CreateClientEventWithCorrectionDelay();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -98,13 +100,10 @@ namespace Barotrauma.Items.Components
|
||||
ValueStep = numberInputStep,
|
||||
OnValueChanged = (ni) =>
|
||||
{
|
||||
if (GameMain.Client == null)
|
||||
ValueChanged(ni.UserData as CustomInterfaceElement, ni.FloatValue);
|
||||
if (!suppressNetworkEvents && GameMain.Client != null)
|
||||
{
|
||||
ValueChanged(ni.UserData as CustomInterfaceElement, ni.FloatValue);
|
||||
}
|
||||
else if (!readingNetworkEvent)
|
||||
{
|
||||
item.CreateClientEvent(this);
|
||||
CreateClientEventWithCorrectionDelay();
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -124,13 +123,10 @@ namespace Barotrauma.Items.Components
|
||||
ValueStep = numberInputStep,
|
||||
OnValueChanged = (ni) =>
|
||||
{
|
||||
if (GameMain.Client == null)
|
||||
ValueChanged(ni.UserData as CustomInterfaceElement, ni.IntValue);
|
||||
if (!suppressNetworkEvents && GameMain.Client != null)
|
||||
{
|
||||
ValueChanged(ni.UserData as CustomInterfaceElement, ni.IntValue);
|
||||
}
|
||||
else if (!readingNetworkEvent)
|
||||
{
|
||||
item.CreateClientEvent(this);
|
||||
CreateClientEventWithCorrectionDelay();
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -149,7 +145,7 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (ciElement.ContinuousSignal)
|
||||
else if (ciElement.InputType is CustomInterfaceElement.InputTypeOption.TickBox)
|
||||
{
|
||||
var tickBox = new GUITickBox(new RectTransform(new Vector2(1.0f, elementSize), uiElementContainer.RectTransform)
|
||||
{
|
||||
@@ -160,13 +156,10 @@ namespace Barotrauma.Items.Components
|
||||
};
|
||||
tickBox.OnSelected += (tBox) =>
|
||||
{
|
||||
if (GameMain.Client == null)
|
||||
TickBoxToggled(tBox.UserData as CustomInterfaceElement, tBox.Selected);
|
||||
if (!suppressNetworkEvents && GameMain.Client != null)
|
||||
{
|
||||
TickBoxToggled(tBox.UserData as CustomInterfaceElement, tBox.Selected);
|
||||
}
|
||||
else if (!readingNetworkEvent)
|
||||
{
|
||||
item.CreateClientEvent(this);
|
||||
CreateClientEventWithCorrectionDelay();
|
||||
}
|
||||
return true;
|
||||
};
|
||||
@@ -175,7 +168,7 @@ namespace Barotrauma.Items.Components
|
||||
tickBox.RectTransform.MaxSize = new Point(int.MaxValue, int.MaxValue);
|
||||
uiElements.Add(tickBox);
|
||||
}
|
||||
else
|
||||
else if (ciElement.InputType is CustomInterfaceElement.InputTypeOption.Button)
|
||||
{
|
||||
var btn = new GUIButton(new RectTransform(new Vector2(1.0f, elementSize), uiElementContainer.RectTransform),
|
||||
TextManager.Get(ciElement.Label).Fallback(ciElement.Label), style: "DeviceButton")
|
||||
@@ -189,8 +182,10 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
ButtonClicked(btnElement);
|
||||
}
|
||||
else if (!readingNetworkEvent)
|
||||
else if (!suppressNetworkEvents && GameMain.Client != null)
|
||||
{
|
||||
//don't use CreateClientEventWithCorrectionDelay here, because buttons have no state,
|
||||
//which means we don't need to worry about server updates interfering with client-side changes to the values in the interface
|
||||
item.CreateClientEvent(this, new EventData(btnElement));
|
||||
}
|
||||
return true;
|
||||
@@ -203,6 +198,22 @@ namespace Barotrauma.Items.Components
|
||||
uiElements.Add(btn);
|
||||
}
|
||||
}
|
||||
|
||||
if (ShowInsufficientPowerWarning)
|
||||
{
|
||||
insufficientPowerWarning = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.1f), GuiFrame.RectTransform, Anchor.BottomCenter, Pivot.TopCenter) { MinSize = new Point(0, GUI.IntScale(30)) },
|
||||
TextManager.Get("SteeringNoPowerTip"), font: GUIStyle.Font, wrap: true, style: "GUIToolTip", textAlignment: Alignment.Center)
|
||||
{
|
||||
AutoScaleHorizontal = true,
|
||||
Visible = false
|
||||
};
|
||||
}
|
||||
|
||||
void CreateClientEventWithCorrectionDelay()
|
||||
{
|
||||
item.CreateClientEvent(this);
|
||||
correctionTimer = CorrectionDelay;
|
||||
}
|
||||
}
|
||||
|
||||
public override void CreateEditingHUD(SerializableEntityEditor editor)
|
||||
@@ -253,7 +264,20 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
if (uiElement.UserData is not CustomInterfaceElement element) { continue; }
|
||||
bool visible = Screen.Selected == GameMain.SubEditorScreen || element.StatusEffects.Any() || element.HasPropertyName || (element.Connection != null && element.Connection.Wires.Count > 0);
|
||||
if (visible) { visibleElementCount++; }
|
||||
if (visible)
|
||||
{
|
||||
visibleElementCount++;
|
||||
if (element.GetValueInterval > 0.0f && correctionTimer <= 0.0f)
|
||||
{
|
||||
element.GetValueTimer -= deltaTime;
|
||||
if (element.GetValueTimer <= 0.0f)
|
||||
{
|
||||
SetSignalToPropertyValue(element);
|
||||
UpdateSignalProjSpecific(uiElement);
|
||||
element.GetValueTimer = element.GetValueInterval;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (uiElement.Visible != visible)
|
||||
{
|
||||
uiElement.Visible = visible;
|
||||
@@ -274,6 +298,11 @@ namespace Barotrauma.Items.Components
|
||||
GuiFrame.Visible = visibleElementCount > 0;
|
||||
uiElementContainer.Recalculate();
|
||||
}
|
||||
|
||||
if (insufficientPowerWarning != null)
|
||||
{
|
||||
insufficientPowerWarning.Visible = item.GetComponents<Powered>().Any(p => p.PowerConsumption > 0.0f && p.Voltage < p.MinVoltage);
|
||||
}
|
||||
}
|
||||
|
||||
partial void UpdateLabelsProjSpecific()
|
||||
@@ -300,7 +329,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
LocalizedString CreateLabelText(int elementIndex)
|
||||
{
|
||||
var label = customInterfaceElementList[elementIndex].Label;
|
||||
string label = customInterfaceElementList[elementIndex].Label;
|
||||
return string.IsNullOrWhiteSpace(label) ?
|
||||
TextManager.GetWithVariable("connection.signaloutx", "[num]", (elementIndex + 1).ToString()) :
|
||||
TextManager.Get(label).Fallback(label);
|
||||
@@ -336,22 +365,43 @@ namespace Barotrauma.Items.Components
|
||||
if (signals == null) { return; }
|
||||
for (int i = 0; i < signals.Length && i < uiElements.Count; i++)
|
||||
{
|
||||
string signal = customInterfaceElementList[i].Signal;
|
||||
if (uiElements[i] is GUITextBox tb)
|
||||
UpdateSignalProjSpecific(uiElements[i]);
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateSignalProjSpecific(GUIComponent uiElement)
|
||||
{
|
||||
if (uiElement.UserData is not CustomInterfaceElement element) { return; }
|
||||
|
||||
suppressNetworkEvents = true;
|
||||
|
||||
string signal = element.Signal;
|
||||
if (uiElement is GUITextBox tb)
|
||||
{
|
||||
tb.Text = Screen.Selected is { IsEditor: true } ?
|
||||
signal :
|
||||
TextManager.Get(signal).Fallback(signal).Value;
|
||||
}
|
||||
else if (uiElement is GUINumberInput ni)
|
||||
{
|
||||
if (ni.InputType == NumberType.Int)
|
||||
{
|
||||
tb.Text = Screen.Selected is { IsEditor: true } ?
|
||||
signal :
|
||||
TextManager.Get(signal).Fallback(signal).Value;
|
||||
}
|
||||
else if (uiElements[i] is GUINumberInput ni)
|
||||
{
|
||||
if (ni.InputType == NumberType.Int)
|
||||
if (int.TryParse(signal, out int value))
|
||||
{
|
||||
int.TryParse(signal, out int value);
|
||||
ni.IntValue = value;
|
||||
}
|
||||
else if (float.TryParse(signal, out float floatValue))
|
||||
{
|
||||
ni.IntValue = (int)MathF.Round(floatValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (uiElement is GUITickBox tickBox)
|
||||
{
|
||||
tickBox.Selected = signal.Equals("true", StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
suppressNetworkEvents = false;
|
||||
}
|
||||
|
||||
public void ClientEventWrite(IWriteMessage msg, NetEntityEvent.IData extraData = null)
|
||||
@@ -360,14 +410,9 @@ namespace Barotrauma.Items.Components
|
||||
for (int i = 0; i < customInterfaceElementList.Count; i++)
|
||||
{
|
||||
var element = customInterfaceElementList[i];
|
||||
if (element.HasPropertyName)
|
||||
switch (element.InputType)
|
||||
{
|
||||
if (!element.IsNumberInput)
|
||||
{
|
||||
msg.WriteString(((GUITextBox)uiElements[i]).Text);
|
||||
}
|
||||
else
|
||||
{
|
||||
case CustomInterfaceElement.InputTypeOption.Number:
|
||||
switch (element.NumberType)
|
||||
{
|
||||
case NumberType.Float:
|
||||
@@ -378,59 +423,82 @@ namespace Barotrauma.Items.Components
|
||||
msg.WriteString(((GUINumberInput)uiElements[i]).IntValue.ToString());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (element.ContinuousSignal)
|
||||
{
|
||||
msg.WriteBoolean(((GUITickBox)uiElements[i]).Selected);
|
||||
}
|
||||
else
|
||||
{
|
||||
msg.WriteBoolean(extraData is Item.ComponentStateEventData { ComponentData: EventData eventData } && eventData.BtnElement == customInterfaceElementList[i]);
|
||||
break;
|
||||
case CustomInterfaceElement.InputTypeOption.Text:
|
||||
msg.WriteString(((GUITextBox)uiElements[i]).Text);
|
||||
break;
|
||||
case CustomInterfaceElement.InputTypeOption.TickBox:
|
||||
msg.WriteBoolean(((GUITickBox)uiElements[i]).Selected);
|
||||
break;
|
||||
case CustomInterfaceElement.InputTypeOption.Button:
|
||||
msg.WriteBoolean(extraData is Item.ComponentStateEventData { ComponentData: EventData eventData } && eventData.BtnElement == customInterfaceElementList[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void ClientEventRead(IReadMessage msg, float sendingTime)
|
||||
{
|
||||
readingNetworkEvent = true;
|
||||
int msgStartPos = msg.BitPosition;
|
||||
suppressNetworkEvents = true;
|
||||
try
|
||||
{
|
||||
string[] stringValues = new string[customInterfaceElementList.Count];
|
||||
bool[] boolValues = new bool[customInterfaceElementList.Count];
|
||||
for (int i = 0; i < customInterfaceElementList.Count; i++)
|
||||
{
|
||||
var element = customInterfaceElementList[i];
|
||||
if (element.HasPropertyName)
|
||||
switch (element.InputType)
|
||||
{
|
||||
string newValue = msg.ReadString();
|
||||
if (!element.IsNumberInput)
|
||||
{
|
||||
TextChanged(element, newValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
case CustomInterfaceElement.InputTypeOption.Number:
|
||||
case CustomInterfaceElement.InputTypeOption.Text:
|
||||
stringValues[i] = msg.ReadString();
|
||||
break;
|
||||
case CustomInterfaceElement.InputTypeOption.TickBox:
|
||||
case CustomInterfaceElement.InputTypeOption.Button:
|
||||
boolValues[i] = msg.ReadBoolean();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (correctionTimer > 0.0f)
|
||||
{
|
||||
int msgLength = msg.BitPosition - msgStartPos;
|
||||
msg.BitPosition = msgStartPos;
|
||||
StartDelayedCorrection(msg.ExtractBits(msgLength), sendingTime);
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < customInterfaceElementList.Count; i++)
|
||||
{
|
||||
var element = customInterfaceElementList[i];
|
||||
switch (element.InputType)
|
||||
{
|
||||
case CustomInterfaceElement.InputTypeOption.Number:
|
||||
switch (element.NumberType)
|
||||
{
|
||||
case NumberType.Int when int.TryParse(newValue, out int value):
|
||||
case NumberType.Int when int.TryParse(stringValues[i], out int value):
|
||||
ValueChanged(element, value);
|
||||
break;
|
||||
case NumberType.Float when TryParseFloatInvariantCulture(newValue, out float value):
|
||||
case NumberType.Float when TryParseFloatInvariantCulture(stringValues[i], out float value):
|
||||
ValueChanged(element, value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bool elementState = msg.ReadBoolean();
|
||||
if (element.ContinuousSignal)
|
||||
{
|
||||
((GUITickBox)uiElements[i]).Selected = elementState;
|
||||
TickBoxToggled(element, elementState);
|
||||
}
|
||||
else if (elementState)
|
||||
{
|
||||
ButtonClicked(element);
|
||||
}
|
||||
break;
|
||||
case CustomInterfaceElement.InputTypeOption.Text:
|
||||
TextChanged(element, stringValues[i]);
|
||||
break;
|
||||
case CustomInterfaceElement.InputTypeOption.TickBox:
|
||||
bool tickBoxState = boolValues[i];
|
||||
((GUITickBox)uiElements[i]).Selected = tickBoxState;
|
||||
TickBoxToggled(element, tickBoxState);
|
||||
break;
|
||||
case CustomInterfaceElement.InputTypeOption.Button:
|
||||
if (boolValues[i])
|
||||
{
|
||||
ButtonClicked(element);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -438,7 +506,7 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
finally
|
||||
{
|
||||
readingNetworkEvent = false;
|
||||
suppressNetworkEvents = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using Barotrauma.Extensions;
|
||||
using Barotrauma.Networking;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
|
||||
@@ -21,13 +22,16 @@ namespace Barotrauma.Items.Components
|
||||
private GUIListBox historyBox;
|
||||
private GUITextBlock fillerBlock;
|
||||
private GUITextBox inputBox;
|
||||
private GUILayoutGroup layoutGroup;
|
||||
private bool shouldSelectInputBox;
|
||||
|
||||
private readonly List<GUIComponent> inputElements = new List<GUIComponent>();
|
||||
|
||||
partial void InitProjSpecific(XElement element)
|
||||
{
|
||||
float marginMultiplier = element.GetAttributeFloat("marginmultiplier", 1.0f);
|
||||
|
||||
var layoutGroup = new GUILayoutGroup(new RectTransform(GuiFrame.Rect.Size - GUIStyle.ItemFrameMargin.Multiply(marginMultiplier), GuiFrame.RectTransform, Anchor.Center) { AbsoluteOffset = GUIStyle.ItemFrameOffset.Multiply(marginMultiplier) })
|
||||
layoutGroup = new GUILayoutGroup(new RectTransform(GuiFrame.Rect.Size - GUIStyle.ItemFrameMargin.Multiply(marginMultiplier), GuiFrame.RectTransform, Anchor.Center) { AbsoluteOffset = GUIStyle.ItemFrameOffset.Multiply(marginMultiplier) })
|
||||
{
|
||||
ChildAnchor = Anchor.TopCenter,
|
||||
RelativeSpacing = 0.02f,
|
||||
@@ -39,43 +43,53 @@ namespace Barotrauma.Items.Components
|
||||
AutoHideScrollBar = this.AutoHideScrollbar
|
||||
};
|
||||
|
||||
if (!Readonly)
|
||||
inputElements.Add(CreateFillerBlock());
|
||||
inputElements.Add(new GUIFrame(new RectTransform(new Vector2(0.9f, 0.01f), layoutGroup.RectTransform), style: "HorizontalLine"));
|
||||
|
||||
inputBox = new GUITextBox(new RectTransform(new Vector2(1, .1f), layoutGroup.RectTransform), textColor: TextColor)
|
||||
{
|
||||
CreateFillerBlock();
|
||||
|
||||
new GUIFrame(new RectTransform(new Vector2(0.9f, 0.01f), layoutGroup.RectTransform), style: "HorizontalLine");
|
||||
|
||||
inputBox = new GUITextBox(new RectTransform(new Vector2(1, .1f), layoutGroup.RectTransform), textColor: TextColor)
|
||||
MaxTextLength = MaxMessageLength,
|
||||
OverflowClip = true,
|
||||
OnEnterPressed = (GUITextBox textBox, string text) =>
|
||||
{
|
||||
MaxTextLength = MaxMessageLength,
|
||||
OverflowClip = true,
|
||||
OnEnterPressed = (GUITextBox textBox, string text) =>
|
||||
if (GameMain.NetworkMember == null)
|
||||
{
|
||||
if (GameMain.NetworkMember == null)
|
||||
{
|
||||
SendOutput(text);
|
||||
}
|
||||
else
|
||||
{
|
||||
item.CreateClientEvent(this, new ClientEventData(text));
|
||||
}
|
||||
textBox.Text = string.Empty;
|
||||
return true;
|
||||
SendOutput(text);
|
||||
}
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
item.CreateClientEvent(this, new ClientEventData(text));
|
||||
}
|
||||
textBox.Text = string.Empty;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
inputElements.Add(inputBox);
|
||||
RefreshInputElements();
|
||||
}
|
||||
|
||||
layoutGroup.Recalculate();
|
||||
/// <summary>
|
||||
/// Refreshes the visibility of the input box and the layout of the UI depending on whether the terminal is readonly or not.
|
||||
/// </summary>
|
||||
private void RefreshInputElements()
|
||||
{
|
||||
foreach (var inputElement in inputElements)
|
||||
{
|
||||
inputElement.Visible = !_readonly;
|
||||
inputElement.IgnoreLayoutGroups = !inputElement.Visible;
|
||||
}
|
||||
layoutGroup?.Recalculate();
|
||||
}
|
||||
|
||||
// Create fillerBlock to cover historyBox so new values appear at the bottom of historyBox
|
||||
// This could be removed if GUIListBox supported aligning its children
|
||||
public void CreateFillerBlock()
|
||||
public GUIComponent CreateFillerBlock()
|
||||
{
|
||||
fillerBlock = new GUITextBlock(new RectTransform(new Vector2(1, 1), historyBox.Content.RectTransform, anchor: Anchor.TopCenter), string.Empty)
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
return fillerBlock;
|
||||
}
|
||||
|
||||
private void SendOutput(string input)
|
||||
|
||||
@@ -21,9 +21,14 @@ namespace Barotrauma.Items.Components
|
||||
ShapeExtensions.DrawCircle(spriteBatch, pos, range, 32, Color.Cyan * 0.5f, 3);
|
||||
}
|
||||
|
||||
public void ClientEventWrite(IWriteMessage msg, NetEntityEvent.IData extraData = null)
|
||||
{
|
||||
SharedEventWrite(msg);
|
||||
}
|
||||
|
||||
public void ClientEventRead(IReadMessage msg, float sendingTime)
|
||||
{
|
||||
Channel = msg.ReadRangedInteger(MinChannel, MaxChannel);
|
||||
SharedEventRead(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,13 +106,6 @@ namespace Barotrauma.Items.Components
|
||||
private static int? selectedNodeIndex;
|
||||
private static int? highlightedNodeIndex;
|
||||
|
||||
[Serialize(0.3f, IsPropertySaveable.No)]
|
||||
public float Width
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public Vector2 DrawSize
|
||||
{
|
||||
get { return sectionExtents; }
|
||||
@@ -199,6 +192,8 @@ namespace Barotrauma.Items.Components
|
||||
return;
|
||||
}
|
||||
|
||||
if (Width * wireSprite.size.Y * Screen.Selected.Cam.Zoom < 1.0f) { return; }
|
||||
|
||||
Vector2 drawOffset = GetDrawOffset() + offset;
|
||||
|
||||
float baseDepth = UseSpriteDepth ? item.SpriteDepth : wireSprite.Depth;
|
||||
|
||||
@@ -175,6 +175,8 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
if (character == null) { return; }
|
||||
|
||||
base.DrawHUD(spriteBatch, character);
|
||||
|
||||
if (OverlayColor.A > 0)
|
||||
{
|
||||
GUIStyle.UIGlow.Draw(spriteBatch, new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight),
|
||||
@@ -206,44 +208,51 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
if (ThermalGoggles)
|
||||
{
|
||||
spriteBatch.End();
|
||||
GameMain.LightManager.SolidColorEffect.Parameters["color"].SetValue(Color.Red.ToVector4() * (0.3f + MathF.Sin(thermalEffectState) * 0.05f));
|
||||
GameMain.LightManager.SolidColorEffect.CurrentTechnique = GameMain.LightManager.SolidColorEffect.Techniques["SolidColorBlur"];
|
||||
GameMain.LightManager.SolidColorEffect.Parameters["blurDistance"].SetValue(0.01f + MathF.Sin(thermalEffectState) * 0.005f);
|
||||
GameMain.LightManager.SolidColorEffect.CurrentTechnique.Passes[0].Apply();
|
||||
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.Additive, transformMatrix: Screen.Selected.Cam.Transform, effect: GameMain.LightManager.SolidColorEffect);
|
||||
|
||||
Entity refEntity = equipper;
|
||||
if (!isEquippable || refEntity == null)
|
||||
{
|
||||
refEntity = item;
|
||||
}
|
||||
DrawThermalOverlay(spriteBatch, refEntity, character, OverlayColor, Range, thermalEffectState, ShowDeadCharacters);
|
||||
|
||||
foreach (Character c in Character.CharacterList)
|
||||
{
|
||||
if (c == character || !c.Enabled || c.Removed || c.Params.HideInThermalGoggles) { continue; }
|
||||
if (!ShowDeadCharacters && c.IsDead) { continue; }
|
||||
|
||||
float dist = Vector2.DistanceSquared(refEntity.WorldPosition, c.WorldPosition);
|
||||
if (dist > Range * Range) { continue; }
|
||||
|
||||
Sprite pingCircle = GUIStyle.UIThermalGlow.Value.Sprite;
|
||||
foreach (Limb limb in c.AnimController.Limbs)
|
||||
{
|
||||
if (limb.Mass < 0.5f && limb != c.AnimController.MainLimb) { continue; }
|
||||
float noise1 = PerlinNoise.GetPerlin((thermalEffectState + limb.Params.ID + c.ID) * 0.01f, (thermalEffectState + limb.Params.ID + c.ID) * 0.02f);
|
||||
float noise2 = PerlinNoise.GetPerlin((thermalEffectState + limb.Params.ID + c.ID) * 0.01f, (thermalEffectState + limb.Params.ID + c.ID) * 0.008f);
|
||||
Vector2 spriteScale = ConvertUnits.ToDisplayUnits(limb.body.GetSize()) / pingCircle.size * (noise1 * 0.5f + 2f);
|
||||
Vector2 drawPos = new Vector2(limb.body.DrawPosition.X + (noise1 - 0.5f) * 100, -limb.body.DrawPosition.Y + (noise2 - 0.5f) * 100);
|
||||
pingCircle.Draw(spriteBatch, drawPos, 0.0f, scale: Math.Max(spriteScale.X, spriteScale.Y));
|
||||
}
|
||||
}
|
||||
|
||||
spriteBatch.End();
|
||||
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied);
|
||||
}
|
||||
}
|
||||
|
||||
public static void DrawThermalOverlay(SpriteBatch spriteBatch, Entity refEntity, Character user, Color overlayColor, float range, float effectState, bool showDeadCharacters)
|
||||
{
|
||||
spriteBatch.End();
|
||||
float colorIntensityBase = 0.5f; //Multiplies the overlay color by this amount, the higher the value, the more bright/vibrant the color.
|
||||
float colorIntensityVariance = 0.05f; //The variance of the pulse effect affecting the color's brightness/vibrance
|
||||
GameMain.LightManager.SolidColorEffect.Parameters["color"].SetValue(overlayColor.ToVector4() * (colorIntensityBase + MathF.Sin(effectState) * colorIntensityVariance));
|
||||
GameMain.LightManager.SolidColorEffect.CurrentTechnique = GameMain.LightManager.SolidColorEffect.Techniques["SolidColorBlur"];
|
||||
GameMain.LightManager.SolidColorEffect.Parameters["blurDistance"].SetValue(0.01f + MathF.Sin(effectState) * 0.005f);
|
||||
GameMain.LightManager.SolidColorEffect.CurrentTechnique.Passes[0].Apply();
|
||||
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.Additive, transformMatrix: Screen.Selected.Cam.Transform, effect: GameMain.LightManager.SolidColorEffect);
|
||||
|
||||
foreach (Character c in Character.CharacterList)
|
||||
{
|
||||
if (c == user || !c.Enabled || c.Removed || c.Params.HideInThermalGoggles) { continue; }
|
||||
if (!showDeadCharacters && c.IsDead) { continue; }
|
||||
|
||||
float dist = Vector2.DistanceSquared(refEntity.WorldPosition, c.WorldPosition);
|
||||
if (dist > range * range) { continue; }
|
||||
|
||||
Sprite pingCircle = GUIStyle.UIThermalGlow.Value.Sprite;
|
||||
foreach (Limb limb in c.AnimController.Limbs)
|
||||
{
|
||||
if (limb.Mass < 0.5f && limb != c.AnimController.MainLimb) { continue; }
|
||||
float noise1 = PerlinNoise.GetPerlin((effectState + limb.Params.ID + c.ID) * 0.01f, (effectState + limb.Params.ID + c.ID) * 0.02f);
|
||||
float noise2 = PerlinNoise.GetPerlin((effectState + limb.Params.ID + c.ID) * 0.01f, (effectState + limb.Params.ID + c.ID) * 0.008f);
|
||||
Vector2 spriteScale = ConvertUnits.ToDisplayUnits(limb.body.GetSize()) / pingCircle.size * (noise1 * 0.5f + 2f);
|
||||
Vector2 drawPos = new Vector2(limb.body.DrawPosition.X + (noise1 - 0.5f) * 100, -limb.body.DrawPosition.Y + (noise2 - 0.5f) * 100);
|
||||
pingCircle.Draw(spriteBatch, drawPos, 0.0f, scale: Math.Max(spriteScale.X, spriteScale.Y));
|
||||
}
|
||||
}
|
||||
|
||||
spriteBatch.End();
|
||||
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied);
|
||||
}
|
||||
|
||||
private void DrawCharacterInfo(SpriteBatch spriteBatch, Character target, float alpha = 1.0f)
|
||||
{
|
||||
Vector2 hudPos = GameMain.GameScreen.Cam.WorldToScreen(target.DrawPosition);
|
||||
@@ -273,7 +282,7 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!target.CustomInteractHUDText.IsNullOrEmpty() && target.AllowCustomInteract)
|
||||
if (target.ShouldShowCustomInteractText)
|
||||
{
|
||||
texts.Add(target.CustomInteractHUDText);
|
||||
textColors.Add(GUIStyle.Green);
|
||||
|
||||
@@ -1,12 +1,28 @@
|
||||
using Barotrauma.Networking;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using System;
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
{
|
||||
partial class TriggerComponent : ItemComponent, IServerSerializable
|
||||
partial class TriggerComponent : ItemComponent, IServerSerializable, IDrawableComponent
|
||||
{
|
||||
public Vector2 DrawSize =>
|
||||
Vector2.One *
|
||||
(Radius > 0.0f ? Radius * 2 : Math.Max(Width, Height));
|
||||
|
||||
public void Draw(SpriteBatch spriteBatch, bool editing, float itemDepth = -1, Color? overrideColor = null)
|
||||
{
|
||||
if (editing)
|
||||
{
|
||||
PhysicsBody.DebugDraw(spriteBatch, Color.LightGray * 0.7f);
|
||||
}
|
||||
}
|
||||
|
||||
public void ClientEventRead(IReadMessage msg, float sendingTime)
|
||||
{
|
||||
CurrentForceFluctuation = msg.ReadRangedSingle(0.0f, 1.0f, 8);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,18 +91,19 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
get
|
||||
{
|
||||
float size = Math.Max(transformedBarrelPos.X, transformedBarrelPos.Y);
|
||||
if (barrelSprite != null)
|
||||
float size = Math.Max(transformedBarrelPos.X, transformedBarrelPos.Y);
|
||||
if (railSprite != null && barrelSprite != null)
|
||||
{
|
||||
if (railSprite != null)
|
||||
{
|
||||
size += Math.Max(Math.Max(barrelSprite.size.X, barrelSprite.size.Y), Math.Max(railSprite.size.X, railSprite.size.Y)) * item.Scale;
|
||||
}
|
||||
else
|
||||
{
|
||||
size += Math.Max(barrelSprite.size.X, barrelSprite.size.Y) * item.Scale;
|
||||
}
|
||||
size += Math.Max(Math.Max(barrelSprite.size.X, barrelSprite.size.Y), Math.Max(railSprite.size.X, railSprite.size.Y)) * item.Scale;
|
||||
}
|
||||
else if (railSprite != null)
|
||||
{
|
||||
size += Math.Max(railSprite.size.X, railSprite.size.Y) * item.Scale;
|
||||
}
|
||||
else if (barrelSprite != null)
|
||||
{
|
||||
size += Math.Max(barrelSprite.size.X, barrelSprite.size.Y) * item.Scale;
|
||||
}
|
||||
return Vector2.One * size * 2;
|
||||
}
|
||||
}
|
||||
@@ -227,14 +228,14 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
if (moveSoundChannel == null && startMoveSound != null)
|
||||
{
|
||||
moveSoundChannel = SoundPlayer.PlaySound(startMoveSound.Sound, item.WorldPosition, startMoveSound.Volume, startMoveSound.Range, ignoreMuffling: startMoveSound.IgnoreMuffling, freqMult: startMoveSound.GetRandomFrequencyMultiplier());
|
||||
moveSoundChannel = SoundPlayer.PlaySound(startMoveSound, item.WorldPosition, hullGuess: item.CurrentHull);
|
||||
}
|
||||
else if (moveSoundChannel == null || !moveSoundChannel.IsPlaying)
|
||||
{
|
||||
if (moveSound != null)
|
||||
{
|
||||
moveSoundChannel?.FadeOutAndDispose();
|
||||
moveSoundChannel = SoundPlayer.PlaySound(moveSound.Sound, item.WorldPosition, moveSound.Volume, moveSound.Range, ignoreMuffling: moveSound.IgnoreMuffling, freqMult: moveSound.GetRandomFrequencyMultiplier());
|
||||
moveSoundChannel = SoundPlayer.PlaySound(moveSound, item.WorldPosition, hullGuess: item.CurrentHull);
|
||||
if (moveSoundChannel != null) { moveSoundChannel.Looping = true;}
|
||||
}
|
||||
}
|
||||
@@ -246,7 +247,7 @@ namespace Barotrauma.Items.Components
|
||||
if (endMoveSound != null && moveSoundChannel.Sound != endMoveSound.Sound)
|
||||
{
|
||||
moveSoundChannel.FadeOutAndDispose();
|
||||
moveSoundChannel = SoundPlayer.PlaySound(endMoveSound.Sound, item.WorldPosition, endMoveSound.Volume, endMoveSound.Range, ignoreMuffling: endMoveSound.IgnoreMuffling, freqMult: endMoveSound.GetRandomFrequencyMultiplier());
|
||||
moveSoundChannel = SoundPlayer.PlaySound(endMoveSound, item.WorldPosition, hullGuess: item.CurrentHull);
|
||||
if (moveSoundChannel != null) { moveSoundChannel.Looping = false; }
|
||||
}
|
||||
else if (!moveSoundChannel.IsPlaying)
|
||||
@@ -275,7 +276,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
if (chargeSound != null)
|
||||
{
|
||||
chargeSoundChannel = SoundPlayer.PlaySound(chargeSound.Sound, item.WorldPosition, chargeSound.Volume, chargeSound.Range, ignoreMuffling: chargeSound.IgnoreMuffling, freqMult: chargeSound.GetRandomFrequencyMultiplier());
|
||||
chargeSoundChannel = SoundPlayer.PlaySound(chargeSound, item.WorldPosition, hullGuess: item.CurrentHull);
|
||||
if (chargeSoundChannel != null) { chargeSoundChannel.Looping = true; }
|
||||
}
|
||||
}
|
||||
@@ -385,17 +386,20 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
if (item.Condition > 0.0f || !HideBarrelWhenBroken)
|
||||
{
|
||||
railSprite?.Draw(spriteBatch,
|
||||
var currentRailSprite = item.Condition <= 0.0f && railSpriteBroken != null ? railSpriteBroken : railSprite;
|
||||
var currentBarrelSprite = item.Condition <= 0.0f && barrelSpriteBroken != null ? barrelSpriteBroken : barrelSprite;
|
||||
|
||||
currentRailSprite?.Draw(spriteBatch,
|
||||
drawPos,
|
||||
overrideColor ?? item.SpriteColor,
|
||||
Rotation + MathHelper.PiOver2, item.Scale,
|
||||
SpriteEffects.None, item.SpriteDepth + (railSprite.Depth - item.Sprite.Depth));
|
||||
SpriteEffects.None, item.SpriteDepth + (currentRailSprite.Depth - item.Sprite.Depth));
|
||||
|
||||
barrelSprite?.Draw(spriteBatch,
|
||||
currentBarrelSprite?.Draw(spriteBatch,
|
||||
drawPos - GetRecoilOffset() * item.Scale,
|
||||
overrideColor ?? item.SpriteColor,
|
||||
Rotation + MathHelper.PiOver2, item.Scale,
|
||||
SpriteEffects.None, item.SpriteDepth + (barrelSprite.Depth - item.Sprite.Depth));
|
||||
SpriteEffects.None, item.SpriteDepth + (currentBarrelSprite.Depth - item.Sprite.Depth));
|
||||
|
||||
float chargeRatio = currentChargeTime / MaxChargeTime;
|
||||
|
||||
@@ -702,12 +706,14 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public override void DrawHUD(SpriteBatch spriteBatch, Character character)
|
||||
{
|
||||
base.DrawHUD(spriteBatch, character);
|
||||
|
||||
if (HudTint.A > 0)
|
||||
{
|
||||
GUI.DrawRectangle(spriteBatch, new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight),
|
||||
new Color(HudTint.R, HudTint.G, HudTint.B) * (HudTint.A / 255.0f), true);
|
||||
}
|
||||
|
||||
|
||||
GetAvailablePower(out float batteryCharge, out float batteryCapacity);
|
||||
|
||||
List<Item> availableAmmo = new List<Item>();
|
||||
|
||||
Reference in New Issue
Block a user