Release v0.15.12.0
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
using System;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
{
|
||||
internal partial class EntitySpawnerComponent
|
||||
{
|
||||
public Vector2 DrawSize => Vector2.Zero;
|
||||
|
||||
public void Draw(SpriteBatch spriteBatch, bool editing, float itemDepth = -1)
|
||||
{
|
||||
if (!editing) { return; }
|
||||
|
||||
switch (SpawnAreaShape)
|
||||
{
|
||||
case AreaShape.Rectangle:
|
||||
{
|
||||
RectangleF rect = GetAreaRectangle(SpawnAreaBounds, SpawnAreaOffset, draw: true);
|
||||
GUI.DrawRectangle(spriteBatch, rect.Location, rect.Size, GUI.Style.Red, isFilled: false, 0f, 4f);
|
||||
|
||||
if (MaximumAmountRangePadding > 0f)
|
||||
{
|
||||
rect.Inflate(MaximumAmountRangePadding, MaximumAmountRangePadding);
|
||||
GUI.DrawRectangle(spriteBatch, rect.Location, rect.Size, GUI.Style.Red, isFilled: false, 0f, 2f);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case AreaShape.Circle:
|
||||
Vector2 center = item.WorldPosition;
|
||||
center.Y = -center.Y;
|
||||
center += SpawnAreaOffset;
|
||||
spriteBatch.DrawCircle(center, SpawnAreaRadius, 32, GUI.Style.Red, thickness: 4f);
|
||||
|
||||
if (MaximumAmountRangePadding > 0f)
|
||||
{
|
||||
spriteBatch.DrawCircle(center, SpawnAreaRadius + MaximumAmountRangePadding, 32, GUI.Style.Red, thickness: 2f);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (!OnlySpawnWhenCrewInRange) { return; }
|
||||
|
||||
switch (CrewAreaShape)
|
||||
{
|
||||
case AreaShape.Rectangle:
|
||||
{
|
||||
RectangleF rect = GetAreaRectangle(CrewAreaBounds, CrewAreaOffset, draw: true);
|
||||
GUI.DrawRectangle(spriteBatch, rect.Location, rect.Size, GUI.Style.Green, isFilled: false, 0f, 4f);
|
||||
break;
|
||||
}
|
||||
case AreaShape.Circle:
|
||||
Vector2 center = item.WorldPosition;
|
||||
center.Y = -center.Y;
|
||||
center += CrewAreaOffset;
|
||||
spriteBatch.DrawCircle(center, CrewAreaRadius, 32, GUI.Style.Green);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
using Barotrauma.Networking;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System.Linq;
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
{
|
||||
partial class GeneticMaterial : ItemComponent
|
||||
{
|
||||
[Serialize(0.0f, false)]
|
||||
public float TooltipValueMin { get; set; }
|
||||
|
||||
[Serialize(0.0f, false)]
|
||||
public float TooltipValueMax { get; set; }
|
||||
|
||||
public override void AddTooltipInfo(ref string name, ref string description)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(materialName) && item.ContainedItems.Count() > 0)
|
||||
{
|
||||
string mergedMaterialName = materialName;
|
||||
foreach (Item containedItem in item.ContainedItems)
|
||||
{
|
||||
var containedMaterial = containedItem.GetComponent<GeneticMaterial>();
|
||||
if (containedMaterial == null) { continue; }
|
||||
mergedMaterialName += ", " + containedMaterial.materialName;
|
||||
}
|
||||
name = name.Replace(materialName, mergedMaterialName);
|
||||
}
|
||||
|
||||
if (Tainted)
|
||||
{
|
||||
name = TextManager.GetWithVariable("entityname.taintedgeneticmaterial", "[geneticmaterialname]", name);
|
||||
}
|
||||
|
||||
if (TextManager.ContainsTag("entitydescription." + Item.prefab.Identifier))
|
||||
{
|
||||
int value = (int)MathHelper.Lerp(TooltipValueMin, TooltipValueMax, item.ConditionPercentage / 100.0f);
|
||||
description = TextManager.GetWithVariable("entitydescription." + Item.prefab.Identifier, "[value]", value.ToString());
|
||||
}
|
||||
foreach (Item containedItem in item.ContainedItems)
|
||||
{
|
||||
var containedGeneticMaterial = containedItem.GetComponent<GeneticMaterial>();
|
||||
if (containedGeneticMaterial == null) { continue; }
|
||||
string _ = string.Empty;
|
||||
string containedDescription = containedItem.Description;
|
||||
containedGeneticMaterial.AddTooltipInfo(ref _, ref containedDescription);
|
||||
if (!string.IsNullOrEmpty(containedDescription))
|
||||
{
|
||||
description += '\n' + containedDescription;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void ModifyDeconstructInfo(Deconstructor deconstructor, ref string buttonText, ref string infoText)
|
||||
{
|
||||
if (deconstructor.InputContainer.Inventory.AllItems.Count() == 2)
|
||||
{
|
||||
if (!deconstructor.InputContainer.Inventory.AllItems.All(it => it.prefab == item.prefab))
|
||||
{
|
||||
buttonText = TextManager.Get("researchstation.combine");
|
||||
infoText = TextManager.Get("researchstation.combine.infotext");
|
||||
}
|
||||
else
|
||||
{
|
||||
buttonText = TextManager.Get("researchstation.refine");
|
||||
int taintedProbability = (int)(GetTaintedProbabilityOnRefine(Character.Controlled) * 100);
|
||||
infoText = TextManager.GetWithVariable("researchstation.refine.infotext", "[taintedprobability]", taintedProbability.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
||||
{
|
||||
Tainted = msg.ReadBoolean();
|
||||
if (Tainted)
|
||||
{
|
||||
uint selectedTaintedEffectId = msg.ReadUInt32();
|
||||
selectedTaintedEffect = AfflictionPrefab.Prefabs.Find(a => a.UIntIdentifier == selectedTaintedEffectId);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint selectedEffectId = msg.ReadUInt32();
|
||||
selectedEffect = AfflictionPrefab.Prefabs.Find(a => a.UIntIdentifier == selectedEffectId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,201 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
using Barotrauma.Extensions;
|
||||
using Barotrauma.IO;
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
{
|
||||
partial class IdCard
|
||||
{
|
||||
public Sprite StoredPortrait;
|
||||
public Vector2 StoredSheetIndex;
|
||||
public JobPrefab StoredJobPrefab;
|
||||
public List<WearableSprite> StoredAttachments;
|
||||
public struct OwnerAppearance
|
||||
{
|
||||
public Sprite Portrait;
|
||||
public Vector2 SheetIndex;
|
||||
public JobPrefab JobPrefab;
|
||||
public List<WearableSprite> Attachments;
|
||||
public Color HairColor;
|
||||
public Color FacialHairColor;
|
||||
public Color SkinColor;
|
||||
|
||||
public void ExtractJobPrefab(string[] tags)
|
||||
{
|
||||
string jobIdTag = tags.FirstOrDefault(s => s.StartsWith("jobid:"));
|
||||
|
||||
if (jobIdTag != null && jobIdTag.Length > 6)
|
||||
{
|
||||
string jobId = jobIdTag.Substring(6);
|
||||
if (jobId != string.Empty)
|
||||
{
|
||||
JobPrefab = JobPrefab.Get(jobId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void ExtractAppearance(CharacterInfo characterInfo, string[] tags)
|
||||
{
|
||||
Gender disguisedGender = Gender.None;
|
||||
Race disguisedRace = Race.None;
|
||||
int disguisedHeadSpriteId = -1;
|
||||
int disguisedHairIndex = -1;
|
||||
int disguisedBeardIndex = -1;
|
||||
int disguisedMoustacheIndex = -1;
|
||||
int disguisedFaceAttachmentIndex = -1;
|
||||
Color hairColor = Color.Black;
|
||||
Color facialHairColor = Color.Black;
|
||||
Color skinColor = Color.Black;
|
||||
|
||||
foreach (string tag in tags)
|
||||
{
|
||||
string[] s = tag.Split(':');
|
||||
|
||||
switch (s[0].ToLowerInvariant())
|
||||
{
|
||||
case "haircolor":
|
||||
hairColor = XMLExtensions.ParseColor(s[1]);
|
||||
break;
|
||||
|
||||
case "facialhaircolor":
|
||||
facialHairColor = XMLExtensions.ParseColor(s[1]);
|
||||
break;
|
||||
|
||||
case "skincolor":
|
||||
skinColor = XMLExtensions.ParseColor(s[1]);
|
||||
break;
|
||||
|
||||
case "gender":
|
||||
Enum.TryParse(s[1], ignoreCase: true, out disguisedGender);
|
||||
break;
|
||||
|
||||
case "race":
|
||||
Enum.TryParse(s[1], ignoreCase: true, out disguisedRace);
|
||||
break;
|
||||
|
||||
case "headspriteid":
|
||||
int.TryParse(s[1], NumberStyles.Any, CultureInfo.InvariantCulture, out disguisedHeadSpriteId);
|
||||
break;
|
||||
|
||||
case "hairindex":
|
||||
disguisedHairIndex = int.Parse(s[1]);
|
||||
break;
|
||||
|
||||
case "beardindex":
|
||||
disguisedBeardIndex = int.Parse(s[1]);
|
||||
break;
|
||||
|
||||
case "moustacheindex":
|
||||
disguisedMoustacheIndex = int.Parse(s[1]);
|
||||
break;
|
||||
|
||||
case "faceattachmentindex":
|
||||
disguisedFaceAttachmentIndex = int.Parse(s[1]);
|
||||
break;
|
||||
|
||||
case "sheetindex":
|
||||
string[] vectorValues = s[1].Split(";");
|
||||
SheetIndex = new Vector2(float.Parse(vectorValues[0]), float.Parse(vectorValues[1]));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ((characterInfo.HasGenders && disguisedGender == Gender.None)
|
||||
|| (characterInfo.HasRaces && disguisedRace == Race.None)
|
||||
|| disguisedHeadSpriteId <= 0)
|
||||
{
|
||||
Portrait = null;
|
||||
Attachments = null;
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (XElement limbElement in characterInfo.Ragdoll.MainElement.Elements())
|
||||
{
|
||||
if (!limbElement.GetAttributeString("type", "").Equals("head", StringComparison.OrdinalIgnoreCase)) { continue; }
|
||||
|
||||
XElement spriteElement = limbElement.Element("sprite");
|
||||
if (spriteElement == null) { continue; }
|
||||
|
||||
string spritePath = spriteElement.Attribute("texture").Value;
|
||||
|
||||
spritePath = spritePath.Replace("[GENDER]", disguisedGender.ToString().ToLowerInvariant());
|
||||
spritePath = spritePath.Replace("[RACE]", disguisedRace.ToString().ToLowerInvariant());
|
||||
spritePath = spritePath.Replace("[HEADID]", disguisedHeadSpriteId.ToString());
|
||||
|
||||
string fileName = Path.GetFileNameWithoutExtension(spritePath);
|
||||
|
||||
//go through the files in the directory to find a matching sprite
|
||||
foreach (string file in Directory.GetFiles(Path.GetDirectoryName(spritePath)))
|
||||
{
|
||||
if (!file.EndsWith(".png", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
string fileWithoutTags = Path.GetFileNameWithoutExtension(file);
|
||||
fileWithoutTags = fileWithoutTags.Split('[', ']').First();
|
||||
if (fileWithoutTags != fileName) { continue; }
|
||||
Portrait = new Sprite(spriteElement, "", file) { RelativeOrigin = Vector2.Zero };
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (characterInfo.Wearables != null)
|
||||
{
|
||||
float baldnessChance = disguisedGender == Gender.Female ? 0.05f : 0.2f;
|
||||
|
||||
List<XElement> createElementList(WearableType wearableType, float emptyCommonness = 1.0f)
|
||||
=> CharacterInfo.AddEmpty(
|
||||
characterInfo.FilterByTypeAndHeadID(
|
||||
characterInfo.FilterElementsByGenderAndRace(characterInfo.Wearables, disguisedGender, disguisedRace),
|
||||
wearableType, disguisedHeadSpriteId),
|
||||
wearableType, emptyCommonness);
|
||||
|
||||
var disguisedHairs = createElementList(WearableType.Hair, baldnessChance);
|
||||
var disguisedBeards = createElementList(WearableType.Beard);
|
||||
var disguisedMoustaches = createElementList(WearableType.Moustache);
|
||||
var disguisedFaceAttachments = createElementList(WearableType.FaceAttachment);
|
||||
|
||||
XElement getElementFromList(List<XElement> list, int index)
|
||||
=> CharacterInfo.IsValidIndex(index, list)
|
||||
? list[index]
|
||||
: characterInfo.GetRandomElement(list);
|
||||
|
||||
var disguisedHairElement = getElementFromList(disguisedHairs, disguisedHairIndex);
|
||||
var disguisedBeardElement = getElementFromList(disguisedBeards, disguisedBeardIndex);
|
||||
var disguisedMoustacheElement = getElementFromList(disguisedMoustaches, disguisedMoustacheIndex);
|
||||
var disguisedFaceAttachmentElement = getElementFromList(disguisedFaceAttachments, disguisedFaceAttachmentIndex);
|
||||
|
||||
Attachments = new List<WearableSprite>();
|
||||
|
||||
void loadAttachments(List<WearableSprite> attachments, XElement element, WearableType wearableType)
|
||||
{
|
||||
foreach (var s in element?.Elements("sprite") ?? Enumerable.Empty<XElement>())
|
||||
{
|
||||
attachments.Add(new WearableSprite(s, wearableType));
|
||||
}
|
||||
}
|
||||
|
||||
loadAttachments(Attachments, disguisedFaceAttachmentElement, WearableType.FaceAttachment);
|
||||
loadAttachments(Attachments, disguisedBeardElement, WearableType.Beard);
|
||||
loadAttachments(Attachments, disguisedMoustacheElement, WearableType.Moustache);
|
||||
loadAttachments(Attachments, disguisedHairElement, WearableType.Hair);
|
||||
|
||||
loadAttachments(Attachments,
|
||||
characterInfo.OmitJobInPortraitClothing
|
||||
? JobPrefab.NoJobElement?.Element("PortraitClothing")
|
||||
: JobPrefab?.ClothingElement,
|
||||
WearableType.JobIndicator);
|
||||
}
|
||||
|
||||
HairColor = hairColor;
|
||||
FacialHairColor = facialHairColor;
|
||||
SkinColor = skinColor;
|
||||
}
|
||||
}
|
||||
|
||||
public OwnerAppearance StoredOwnerAppearance = default;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,8 @@ using System.Collections.Generic;
|
||||
using Barotrauma.IO;
|
||||
using System.Text;
|
||||
using System.Xml.Linq;
|
||||
using Barotrauma.Sounds;
|
||||
using System.Linq;
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
{
|
||||
@@ -18,7 +20,11 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
protected float currentCrossHairScale, currentCrossHairPointerScale;
|
||||
|
||||
private RoundSound chargeSound;
|
||||
private SoundChannel chargeSoundChannel;
|
||||
|
||||
private readonly List<ParticleEmitter> particleEmitters = new List<ParticleEmitter>();
|
||||
private readonly List<ParticleEmitter> particleEmitterCharges = new List<ParticleEmitter>();
|
||||
|
||||
[Serialize(1.0f, false, description: "The scale of the crosshair sprite (if there is one).")]
|
||||
public float CrossHairScale
|
||||
@@ -48,6 +54,12 @@ namespace Barotrauma.Items.Components
|
||||
case "particleemitter":
|
||||
particleEmitters.Add(new ParticleEmitter(subElement));
|
||||
break;
|
||||
case "particleemittercharge":
|
||||
particleEmitterCharges.Add(new ParticleEmitter(subElement));
|
||||
break;
|
||||
case "chargesound":
|
||||
chargeSound = Submarine.LoadRoundSound(subElement, false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -84,15 +96,62 @@ namespace Barotrauma.Items.Components
|
||||
crosshairPointerPos = PlayerInput.MousePosition;
|
||||
}
|
||||
|
||||
partial void UpdateProjSpecific(float deltaTime)
|
||||
{
|
||||
float chargeRatio = currentChargeTime / MaxChargeTime;
|
||||
|
||||
switch (currentChargingState)
|
||||
{
|
||||
case ChargingState.WindingUp:
|
||||
case ChargingState.WindingDown:
|
||||
Vector2 particlePos = item.WorldPosition + ConvertUnits.ToDisplayUnits(TransformedBarrelPos);
|
||||
float sizeMultiplier = Math.Clamp(chargeRatio, 0.1f, 1f);
|
||||
foreach (ParticleEmitter emitter in particleEmitterCharges)
|
||||
{
|
||||
emitter.Emit(deltaTime, particlePos, hullGuess: null, sizeMultiplier: sizeMultiplier, colorMultiplier: emitter.Prefab.Properties.ColorMultiplier);
|
||||
}
|
||||
|
||||
if (chargeSoundChannel == null || !chargeSoundChannel.IsPlaying)
|
||||
{
|
||||
if (chargeSound != null)
|
||||
{
|
||||
chargeSoundChannel = SoundPlayer.PlaySound(chargeSound.Sound, item.WorldPosition, chargeSound.Volume, chargeSound.Range, ignoreMuffling: chargeSound.IgnoreMuffling);
|
||||
if (chargeSoundChannel != null) chargeSoundChannel.Looping = true;
|
||||
}
|
||||
}
|
||||
else if (chargeSoundChannel != null)
|
||||
{
|
||||
chargeSoundChannel.FrequencyMultiplier = MathHelper.Lerp(0.5f, 1.5f, chargeRatio);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (chargeSoundChannel != null)
|
||||
{
|
||||
if (chargeSoundChannel.IsPlaying)
|
||||
{
|
||||
chargeSoundChannel.FadeOutAndDispose();
|
||||
chargeSoundChannel.Looping = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
chargeSoundChannel = null;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public override void DrawHUD(SpriteBatch spriteBatch, Character character)
|
||||
{
|
||||
if (character == null || !character.IsKeyDown(InputType.Aim)) { return; }
|
||||
|
||||
//camera focused on some other item/device, don't draw the crosshair
|
||||
if (character.ViewTarget != null && (character.ViewTarget is Item item) && item.Prefab.FocusOnSelected) { return; }
|
||||
if (character.ViewTarget != null && (character.ViewTarget is Item viewTargetItem) && viewTargetItem.Prefab.FocusOnSelected) { return; }
|
||||
//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; }
|
||||
|
||||
GUI.HideCursor = (crosshairSprite != null || crosshairPointerSprite != null) &&
|
||||
GUI.MouseOn == null && !Inventory.IsMouseOnInventory() && !GameMain.Instance.Paused;
|
||||
GUI.MouseOn == null && !Inventory.IsMouseOnInventory && !GameMain.Instance.Paused;
|
||||
if (GUI.HideCursor)
|
||||
{
|
||||
crosshairSprite?.Draw(spriteBatch, crosshairPos, Color.White, 0, currentCrossHairScale);
|
||||
|
||||
@@ -246,6 +246,7 @@ namespace Barotrauma.Items.Components
|
||||
public void PlaySound(ActionType type, Character user = null)
|
||||
{
|
||||
if (!hasSoundsOfType[(int)type]) { return; }
|
||||
if (GameMain.Client?.MidRoundSyncing ?? false) { return; }
|
||||
|
||||
if (loopingSound != null)
|
||||
{
|
||||
@@ -429,7 +430,7 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
foreach (ItemComponent component in item.Components)
|
||||
{
|
||||
if (component.name.ToLower() == LinkUIToComponent.ToLower())
|
||||
if (component.name.Equals(LinkUIToComponent, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
linkToUIComponent = component;
|
||||
}
|
||||
@@ -443,9 +444,9 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public virtual void DrawHUD(SpriteBatch spriteBatch, Character character) { }
|
||||
|
||||
public virtual void AddToGUIUpdateList()
|
||||
public virtual void AddToGUIUpdateList(int order = 0)
|
||||
{
|
||||
GuiFrame?.AddToGUIUpdateList();
|
||||
GuiFrame?.AddToGUIUpdateList(order: order);
|
||||
}
|
||||
|
||||
public virtual void UpdateHUD(Character character, float deltaTime, Camera cam) { }
|
||||
@@ -620,6 +621,6 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
OnResolutionChanged();
|
||||
}
|
||||
public virtual void AddTooltipInfo(ref string description) { }
|
||||
public virtual void AddTooltipInfo(ref string name, ref string description) { }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,8 @@ namespace Barotrauma.Items.Components
|
||||
/// </summary>
|
||||
private float[] containedSpriteDepths;
|
||||
|
||||
private Sprite[] slotIcons;
|
||||
|
||||
public Sprite InventoryTopSprite
|
||||
{
|
||||
get { return inventoryTopSprite; }
|
||||
@@ -58,6 +60,9 @@ namespace Barotrauma.Items.Components
|
||||
[Serialize(null, false)]
|
||||
public string ContainedStateIndicatorStyle { get; set; }
|
||||
|
||||
[Serialize(-1, false, description: "Can be used to make the contained state indicator display the condition of the item in a specific slot even when the container's capacity is more than 1.")]
|
||||
public int ContainedStateIndicatorSlot { get; set; }
|
||||
|
||||
[Serialize(true, false, description: "Should an indicator displaying the state of the contained items be displayed on this item's inventory slot. "+
|
||||
"If this item can only contain one item, the indicator will display the condition of the contained item, otherwise it will indicate how full the item is.")]
|
||||
public bool ShowContainedStateIndicator { get; set; }
|
||||
@@ -85,6 +90,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
partial void InitProjSpecific(XElement element)
|
||||
{
|
||||
slotIcons = new Sprite[capacity];
|
||||
foreach (XElement subElement in element.Elements())
|
||||
{
|
||||
switch (subElement.Name.ToString().ToLowerInvariant())
|
||||
@@ -104,6 +110,17 @@ namespace Barotrauma.Items.Components
|
||||
case "containedstateindicatorempty":
|
||||
ContainedStateIndicatorEmpty = new Sprite(subElement);
|
||||
break;
|
||||
case "sloticon":
|
||||
int index = subElement.GetAttributeInt("slotindex", -1);
|
||||
Sprite icon = new Sprite(subElement);
|
||||
for (int i = 0; i < capacity; i++)
|
||||
{
|
||||
if (i == index || index == -1)
|
||||
{
|
||||
slotIcons[i] = icon;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -197,7 +214,7 @@ namespace Barotrauma.Items.Components
|
||||
if (UILabel == string.Empty) { return string.Empty; }
|
||||
if (UILabel != null)
|
||||
{
|
||||
return TextManager.Get("UILabel." + UILabel);
|
||||
return TextManager.Get("UILabel." + UILabel, returnNull: true) ?? TextManager.Get(UILabel);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -205,6 +222,12 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
public Sprite GetSlotIcon(int slotIndex)
|
||||
{
|
||||
if (slotIndex < 0 || slotIndex >= slotIcons.Length) { return null; }
|
||||
return slotIcons[slotIndex];
|
||||
}
|
||||
|
||||
public bool KeepOpenWhenEquippedBy(Character character)
|
||||
{
|
||||
if (!character.CanAccessInventory(Inventory) ||
|
||||
@@ -266,7 +289,7 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
else
|
||||
{
|
||||
Matrix transform = Matrix.CreateRotationZ(item.body.Rotation);
|
||||
Matrix transform = Matrix.CreateRotationZ(item.body.DrawRotation);
|
||||
if (item.body.Dir == -1.0f)
|
||||
{
|
||||
transformedItemPos.X = -transformedItemPos.X;
|
||||
@@ -277,7 +300,7 @@ namespace Barotrauma.Items.Components
|
||||
transformedItemPos = Vector2.Transform(transformedItemPos, transform);
|
||||
transformedItemInterval = Vector2.Transform(transformedItemInterval, transform);
|
||||
transformedItemIntervalHorizontal = Vector2.Transform(transformedItemIntervalHorizontal, transform);
|
||||
transformedItemPos += item.DrawPosition;
|
||||
transformedItemPos += item.body.DrawPosition;
|
||||
}
|
||||
|
||||
Vector2 currentItemPos = transformedItemPos;
|
||||
@@ -319,7 +342,7 @@ namespace Barotrauma.Items.Components
|
||||
new Vector2(currentItemPos.X, -currentItemPos.Y),
|
||||
isWiringMode ? containedItem.GetSpriteColor() * 0.15f : containedItem.GetSpriteColor(),
|
||||
origin,
|
||||
-(containedItem.body == null ? 0.0f : containedItem.body.DrawRotation + MathHelper.ToRadians(-item.Rotation)),
|
||||
-(containedItem.body == null ? 0.0f : containedItem.body.DrawRotation ),
|
||||
containedItem.Scale,
|
||||
spriteEffects,
|
||||
depth: containedSpriteDepth);
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public void Draw(SpriteBatch spriteBatch, bool editing = false, float itemDepth = -1)
|
||||
{
|
||||
if (Light.LightSprite != null && (item.body == null || item.body.Enabled) && lightBrightness > 0.0f && IsOn)
|
||||
if (Light.LightSprite != null && (item.body == null || item.body.Enabled) && lightBrightness > 0.0f && IsOn && Light.Enabled)
|
||||
{
|
||||
Vector2 origin = Light.LightSprite.Origin;
|
||||
if ((Light.LightSpriteEffect & SpriteEffects.FlipHorizontally) == SpriteEffects.FlipHorizontally) { origin.X = Light.LightSprite.SourceRect.Width - origin.X; }
|
||||
|
||||
+109
-13
@@ -14,12 +14,22 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
private GUIButton activateButton;
|
||||
private GUIComponent inputInventoryHolder, outputInventoryHolder;
|
||||
private GUICustomComponent inputInventoryOverlay;
|
||||
|
||||
private GUIComponent inSufficientPowerWarning;
|
||||
|
||||
private bool pendingState;
|
||||
|
||||
private GUITextBlock infoArea;
|
||||
|
||||
[Serialize("DeconstructorDeconstruct", true)]
|
||||
public string ActivateButtonText { get; set; }
|
||||
|
||||
[Serialize("", true)]
|
||||
public string InfoText { get; set; }
|
||||
|
||||
[Serialize(0.0f, true)]
|
||||
public float InfoAreaWidth { get; set; }
|
||||
|
||||
partial void InitProjSpecific(XElement element)
|
||||
{
|
||||
CreateGUI();
|
||||
@@ -39,6 +49,12 @@ namespace Barotrauma.Items.Components
|
||||
RelativeSpacing = 0.08f
|
||||
};
|
||||
|
||||
new GUITextBlock(new RectTransform(new Vector2(1f, 0.07f), paddedFrame.RectTransform), item.Name, font: GUI.SubHeadingFont)
|
||||
{
|
||||
TextAlignment = Alignment.Center,
|
||||
AutoScaleHorizontal = true
|
||||
};
|
||||
|
||||
var topFrame = new GUIFrame(new RectTransform(new Vector2(1f, 0.5f), paddedFrame.RectTransform), style: null);
|
||||
|
||||
// === INPUT LABEL === //
|
||||
@@ -55,22 +71,23 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
// === INPUT SLOTS === //
|
||||
inputInventoryHolder = new GUIFrame(new RectTransform(new Vector2(0.7f, 1f), inputArea.RectTransform), style: null);
|
||||
inputInventoryOverlay = new GUICustomComponent(new RectTransform(Vector2.One, inputInventoryHolder.RectTransform), DrawOverLay, null) { CanBeFocused = false };
|
||||
new GUICustomComponent(new RectTransform(Vector2.One, inputInventoryHolder.RectTransform), DrawOverLay, null) { CanBeFocused = false };
|
||||
|
||||
// === ACTIVATE BUTTON === //
|
||||
var buttonContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.4f, 0.7f), inputArea.RectTransform), childAnchor: Anchor.CenterLeft);
|
||||
var buttonContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.4f, 0.8f), inputArea.RectTransform), childAnchor: Anchor.CenterLeft);
|
||||
activateButton = new GUIButton(new RectTransform(new Vector2(0.95f, 0.8f), buttonContainer.RectTransform), TextManager.Get("DeconstructorDeconstruct"), style: "DeviceButton")
|
||||
{
|
||||
TextBlock = { AutoScaleHorizontal = true },
|
||||
OnClicked = ToggleActive
|
||||
};
|
||||
inSufficientPowerWarning = new GUITextBlock(new RectTransform(Vector2.One, activateButton.RectTransform),
|
||||
TextManager.Get("DeconstructorNoPower"), textColor: GUI.Style.Orange, textAlignment: Alignment.Center, color: Color.Black, style: "OuterGlow")
|
||||
TextManager.Get("DeconstructorNoPower"), textColor: GUI.Style.Orange, textAlignment: Alignment.Center, color: Color.Black, style: "OuterGlow", wrap: true)
|
||||
{
|
||||
HoverColor = Color.Black,
|
||||
IgnoreLayoutGroups = true,
|
||||
Visible = false,
|
||||
CanBeFocused = false
|
||||
CanBeFocused = false,
|
||||
AutoScaleHorizontal = true
|
||||
};
|
||||
|
||||
// === OUTPUT AREA === //
|
||||
@@ -86,8 +103,70 @@ namespace Barotrauma.Items.Components
|
||||
outputLabel.RectTransform.Resize(new Point((int) outputLabel.Font.MeasureString(outputLabel.Text).X, outputLabel.RectTransform.Rect.Height));
|
||||
new GUIFrame(new RectTransform(Vector2.One, outputLabelArea.RectTransform), style: "HorizontalLine");
|
||||
|
||||
// === OUTPUT SLOTS === //
|
||||
outputInventoryHolder = new GUIFrame(new RectTransform(new Vector2(1f, 1f), bottomFrame.RectTransform, Anchor.CenterLeft), style: null);
|
||||
var outputArea = new GUILayoutGroup(new RectTransform(new Vector2(1f, 1f), bottomFrame.RectTransform, Anchor.CenterLeft), childAnchor: Anchor.BottomLeft, isHorizontal: true) { Stretch = true, RelativeSpacing = 0.05f };
|
||||
|
||||
// === OUTPUT SLOTS === //
|
||||
outputInventoryHolder = new GUIFrame(new RectTransform(new Vector2(1f - InfoAreaWidth, 1f), outputArea.RectTransform, Anchor.CenterLeft), style: null);
|
||||
|
||||
if (InfoAreaWidth >= 0.0f)
|
||||
{
|
||||
var infoAreaContainer = new GUILayoutGroup(new RectTransform(new Vector2(InfoAreaWidth, 0.8f), outputArea.RectTransform), childAnchor: Anchor.CenterLeft);
|
||||
infoArea = new GUITextBlock(new RectTransform(new Vector2(0.95f, 0.95f), infoAreaContainer.RectTransform), string.Empty, wrap: true);
|
||||
}
|
||||
|
||||
ActivateButton.OnAddedToGUIUpdateList += (GUIComponent component) =>
|
||||
{
|
||||
activateButton.Enabled = true;
|
||||
if (string.IsNullOrEmpty(InfoText))
|
||||
{
|
||||
infoArea.Text = string.Empty;
|
||||
}
|
||||
else
|
||||
{
|
||||
infoArea.Text = TextManager.Get(InfoText, returnNull: true) ?? InfoText;
|
||||
}
|
||||
if (IsActive)
|
||||
{
|
||||
activateButton.Text = TextManager.Get("DeconstructorCancel");
|
||||
infoArea.Text = string.Empty;
|
||||
return;
|
||||
}
|
||||
bool outputsFound = false;
|
||||
foreach (var (inputItem, deconstructItem) in GetAvailableOutputs(checkRequiredOtherItems: true))
|
||||
{
|
||||
outputsFound = true;
|
||||
if (!string.IsNullOrEmpty(deconstructItem.ActivateButtonText))
|
||||
{
|
||||
string buttonText = TextManager.Get(deconstructItem.ActivateButtonText, returnNull: true) ?? deconstructItem.ActivateButtonText;
|
||||
string infoText = string.Empty;
|
||||
if (!string.IsNullOrEmpty(deconstructItem.InfoText))
|
||||
{
|
||||
infoText = TextManager.Get(deconstructItem.InfoText, returnNull: true) ?? deconstructItem.InfoText;
|
||||
}
|
||||
inputItem.GetComponent<GeneticMaterial>()?.ModifyDeconstructInfo(this, ref buttonText, ref infoText);
|
||||
activateButton.Text = buttonText;
|
||||
if (infoArea != null)
|
||||
{
|
||||
infoArea.Text = infoText;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
//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))
|
||||
{
|
||||
if (deconstructItem.RequiredOtherItem.Any() && !string.IsNullOrEmpty(deconstructItem.InfoTextOnOtherItemMissing))
|
||||
{
|
||||
string missingItemName = TextManager.Get("entityname." + deconstructItem.RequiredOtherItem.First(), returnNull: true);
|
||||
infoArea.Text = TextManager.GetWithVariable(deconstructItem.InfoTextOnOtherItemMissing, "[itemname]", missingItemName);
|
||||
}
|
||||
}
|
||||
}
|
||||
activateButton.Enabled = outputsFound;
|
||||
activateButton.Text = TextManager.Get(ActivateButtonText);
|
||||
};
|
||||
}
|
||||
|
||||
public override bool Select(Character character)
|
||||
@@ -126,13 +205,30 @@ namespace Barotrauma.Items.Components
|
||||
private void DrawOverLay(SpriteBatch spriteBatch, GUICustomComponent overlayComponent)
|
||||
{
|
||||
overlayComponent.RectTransform.SetAsLastChild();
|
||||
var lastSlot = inputContainer.Inventory.visualSlots.Last();
|
||||
|
||||
GUI.DrawRectangle(spriteBatch,
|
||||
new Rectangle(
|
||||
lastSlot.Rect.X, lastSlot.Rect.Y + (int)(lastSlot.Rect.Height * (1.0f - progressState)),
|
||||
lastSlot.Rect.Width, (int)(lastSlot.Rect.Height * progressState)),
|
||||
GUI.Style.Green * 0.5f, isFilled: true);
|
||||
if (!(inputContainer?.Inventory?.visualSlots is { } visualSlots)) { return; }
|
||||
|
||||
if (DeconstructItemsSimultaneously)
|
||||
{
|
||||
for (int i = 0; i < InputContainer.Inventory.Capacity; i++)
|
||||
{
|
||||
if (InputContainer.Inventory.GetItemAt(i) == null) { continue; }
|
||||
DrawProgressBar(InputContainer.Inventory.visualSlots[i]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawProgressBar(inputContainer.Inventory.visualSlots.Last());
|
||||
}
|
||||
|
||||
void DrawProgressBar(VisualSlot slot)
|
||||
{
|
||||
GUI.DrawRectangle(spriteBatch,
|
||||
new Rectangle(
|
||||
slot.Rect.X, slot.Rect.Y + (int)(slot.Rect.Height * (1.0f - progressState)),
|
||||
slot.Rect.Width, (int)(slot.Rect.Height * progressState)),
|
||||
GUI.Style.Green * 0.5f, isFilled: true);
|
||||
}
|
||||
}
|
||||
|
||||
public override void UpdateHUD(Character character, float deltaTime, Camera cam)
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
private FabricationRecipe pendingFabricatedItem;
|
||||
|
||||
private Pair<Rectangle, string> tooltip;
|
||||
private (Rectangle area, string text)? tooltip;
|
||||
|
||||
private GUITextBlock requiredTimeBlock;
|
||||
|
||||
@@ -255,19 +255,22 @@ namespace Barotrauma.Items.Components
|
||||
var item1 = c1.GUIComponent.UserData as FabricationRecipe;
|
||||
var item2 = c2.GUIComponent.UserData as FabricationRecipe;
|
||||
|
||||
bool hasSkills1 = FabricationDegreeOfSuccess(character, item1.RequiredSkills) >= 0.5f;
|
||||
bool hasSkills2 = FabricationDegreeOfSuccess(character, item2.RequiredSkills) >= 0.5f;
|
||||
int itemPlacement1 = FabricationDegreeOfSuccess(character, item1.RequiredSkills) >= 0.5f ? 0 : -1;
|
||||
int itemPlacement2 = FabricationDegreeOfSuccess(character, item2.RequiredSkills) >= 0.5f ? 0 : -1;
|
||||
|
||||
if (hasSkills1 != hasSkills2)
|
||||
itemPlacement1 += item1.RequiresRecipe && !character.HasRecipeForItem(item1.TargetItem.Identifier) ? -2 : 0;
|
||||
itemPlacement2 += item2.RequiresRecipe && !character.HasRecipeForItem(item2.TargetItem.Identifier) ? -2 : 0;
|
||||
|
||||
if (itemPlacement1 != itemPlacement2)
|
||||
{
|
||||
return hasSkills1 ? -1 : 1;
|
||||
return itemPlacement1 > itemPlacement2 ? -1 : 1;
|
||||
}
|
||||
|
||||
return string.Compare(item1.DisplayName, item2.DisplayName);
|
||||
});
|
||||
|
||||
var sufficientSkillsText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.15f), itemList.Content.RectTransform),
|
||||
TextManager.Get("fabricatorsufficientskills", returnNull: true) ?? "Sufficient skills to fabricate", textColor: GUI.Style.Green, font: GUI.SubHeadingFont)
|
||||
TextManager.Get("fabricatorsufficientskills"), textColor: GUI.Style.Green, font: GUI.SubHeadingFont)
|
||||
{
|
||||
AutoScaleHorizontal = true,
|
||||
CanBeFocused = false
|
||||
@@ -275,7 +278,7 @@ namespace Barotrauma.Items.Components
|
||||
sufficientSkillsText.RectTransform.SetAsFirstChild();
|
||||
|
||||
var insufficientSkillsText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.15f), itemList.Content.RectTransform),
|
||||
TextManager.Get("fabricatorinsufficientskills", returnNull: true) ?? "Insufficient skills to fabricate", textColor: Color.Orange, font: GUI.SubHeadingFont)
|
||||
TextManager.Get("fabricatorinsufficientskills"), textColor: Color.Orange, font: GUI.SubHeadingFont)
|
||||
{
|
||||
AutoScaleHorizontal = true,
|
||||
CanBeFocused = false
|
||||
@@ -285,6 +288,18 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
insufficientSkillsText.RectTransform.RepositionChildInHierarchy(itemList.Content.RectTransform.GetChildIndex(firstinSufficient.RectTransform));
|
||||
}
|
||||
|
||||
var requiresRecipeText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.15f), itemList.Content.RectTransform),
|
||||
TextManager.Get("fabricatorrequiresrecipe"), textColor: Color.Red, font: GUI.SubHeadingFont)
|
||||
{
|
||||
AutoScaleHorizontal = true,
|
||||
CanBeFocused = false
|
||||
};
|
||||
var firstRequiresRecipe = itemList.Content.Children.FirstOrDefault(c => c.UserData is FabricationRecipe fabricableItem && (fabricableItem.RequiresRecipe && !character.HasRecipeForItem(fabricableItem.TargetItem.Identifier)));
|
||||
if (firstRequiresRecipe != null)
|
||||
{
|
||||
requiresRecipeText.RectTransform.RepositionChildInHierarchy(itemList.Content.RectTransform.GetChildIndex(firstRequiresRecipe.RectTransform));
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawInputOverLay(SpriteBatch spriteBatch, GUICustomComponent overlayComponent)
|
||||
@@ -297,6 +312,7 @@ namespace Barotrauma.Items.Components
|
||||
int slotIndex = 0;
|
||||
|
||||
var missingItems = new List<FabricationRecipe.RequiredItem>();
|
||||
|
||||
foreach (FabricationRecipe.RequiredItem requiredItem in targetItem.RequiredItems)
|
||||
{
|
||||
for (int i = 0; i < requiredItem.Amount; i++)
|
||||
@@ -308,6 +324,8 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
missingItems.Remove(missingItems.FirstOrDefault(mi => mi.ItemPrefabs.Contains(item.prefab)));
|
||||
}
|
||||
var missingCounts = missingItems.GroupBy(missingItem => missingItem).ToDictionary(x => x.Key, x => x.Count());
|
||||
missingItems = missingItems.Distinct().ToList();
|
||||
|
||||
var availableIngredients = GetAvailableIngredients();
|
||||
|
||||
@@ -318,30 +336,30 @@ namespace Barotrauma.Items.Components
|
||||
slotIndex++;
|
||||
}
|
||||
|
||||
//highlight suitable ingredients in linked inventories
|
||||
foreach (Item item in availableIngredients)
|
||||
{
|
||||
if (item.ParentInventory != inputContainer.Inventory && IsItemValidIngredient(item, requiredItem))
|
||||
{
|
||||
int availableSlotIndex = item.ParentInventory.FindIndex(item);
|
||||
//slots are null if the inventory has never been displayed
|
||||
//(linked item, but the UI is not set to be displayed at the same time)
|
||||
if (item.ParentInventory.visualSlots != null)
|
||||
{
|
||||
if (item.ParentInventory.visualSlots[availableSlotIndex].HighlightTimer <= 0.0f)
|
||||
{
|
||||
item.ParentInventory.visualSlots[availableSlotIndex].ShowBorderHighlight(GUI.Style.Green, 0.5f, 0.5f, 0.2f);
|
||||
if (slotIndex < inputContainer.Capacity)
|
||||
requiredItem.ItemPrefabs
|
||||
.Where(requiredPrefab => availableIngredients.ContainsKey(requiredPrefab.Identifier))
|
||||
.ForEach(requiredPrefab => {
|
||||
var availablePrefabs = availableIngredients[requiredPrefab.Identifier];
|
||||
|
||||
availablePrefabs
|
||||
.Where(availablePrefab => availablePrefab.ParentInventory != inputContainer.Inventory)
|
||||
.Where(availablePrefab => availablePrefab.ParentInventory.visualSlots != null) //slots are null if the inventory has never been displayed
|
||||
.ForEach(availablePrefab => { //(linked item, but the UI is not set to be displayed at the same time)
|
||||
int availableSlotIndex = availablePrefab.ParentInventory.FindIndex(availablePrefab);
|
||||
|
||||
if (availablePrefab.ParentInventory.visualSlots[availableSlotIndex].HighlightTimer <= 0.0f)
|
||||
{
|
||||
inputContainer.Inventory.visualSlots[slotIndex].ShowBorderHighlight(GUI.Style.Green, 0.5f, 0.5f, 0.2f);
|
||||
availablePrefab.ParentInventory.visualSlots[availableSlotIndex].ShowBorderHighlight(GUI.Style.Green, 0.5f, 0.5f, 0.2f);
|
||||
if (slotIndex < inputContainer.Capacity)
|
||||
{
|
||||
inputContainer.Inventory.visualSlots[slotIndex].ShowBorderHighlight(GUI.Style.Green, 0.5f, 0.5f, 0.2f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
if (slotIndex >= inputContainer.Capacity) { break; }
|
||||
|
||||
|
||||
var itemIcon = requiredItem.ItemPrefabs.First().InventoryIcon ?? requiredItem.ItemPrefabs.First().sprite;
|
||||
Rectangle slotRect = inputContainer.Inventory.visualSlots[slotIndex].Rect;
|
||||
itemIcon.Draw(
|
||||
@@ -350,11 +368,32 @@ namespace Barotrauma.Items.Components
|
||||
color: requiredItem.ItemPrefabs.First().InventoryIconColor * 0.3f,
|
||||
scale: Math.Min(slotRect.Width / itemIcon.size.X, slotRect.Height / itemIcon.size.Y));
|
||||
|
||||
|
||||
if (missingCounts[requiredItem] > 1)
|
||||
{
|
||||
Vector2 stackCountPos = new Vector2(slotRect.Right, slotRect.Bottom);
|
||||
string stackCountText = "x" + missingCounts[requiredItem];
|
||||
stackCountPos -= GUI.SmallFont.MeasureString(stackCountText) + new Vector2(4, 2);
|
||||
GUI.SmallFont.DrawString(spriteBatch, stackCountText, stackCountPos + Vector2.One, Color.Black);
|
||||
GUI.SmallFont.DrawString(spriteBatch, stackCountText, stackCountPos, Color.White);
|
||||
}
|
||||
|
||||
if (requiredItem.UseCondition && requiredItem.MinCondition < 1.0f)
|
||||
{
|
||||
GUI.DrawRectangle(spriteBatch, new Rectangle(slotRect.X, slotRect.Bottom - 8, slotRect.Width, 8), Color.Black * 0.8f, true);
|
||||
DrawConditionBar(spriteBatch, requiredItem.MinCondition);
|
||||
}
|
||||
else if (requiredItem.MaxCondition < 1.0f)
|
||||
{
|
||||
DrawConditionBar(spriteBatch, requiredItem.MaxCondition);
|
||||
}
|
||||
|
||||
void DrawConditionBar(SpriteBatch sb, float condition)
|
||||
{
|
||||
int spacing = GUI.IntScale(4);
|
||||
int height = GUI.IntScale(10);
|
||||
GUI.DrawRectangle(spriteBatch, new Rectangle(slotRect.X + spacing, slotRect.Bottom - spacing - height, slotRect.Width - spacing * 2, height), Color.Black * 0.8f, true);
|
||||
GUI.DrawRectangle(spriteBatch,
|
||||
new Rectangle(slotRect.X, slotRect.Bottom - 8, (int)(slotRect.Width * requiredItem.MinCondition), 8),
|
||||
new Rectangle(slotRect.X + spacing, slotRect.Bottom - spacing - height, (int)((slotRect.Width - spacing * 2) * condition), height),
|
||||
GUI.Style.Green * 0.8f, true);
|
||||
}
|
||||
|
||||
@@ -367,6 +406,10 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
toolTipText += " " + (int)Math.Round(requiredItem.MinCondition * 100) + "%";
|
||||
}
|
||||
else if(requiredItem.MaxCondition < 1.0f)
|
||||
{
|
||||
toolTipText += " 0-" + (int)Math.Round(requiredItem.MaxCondition * 100) + "%";
|
||||
}
|
||||
else if (requiredItem.MaxCondition <= 0.0f)
|
||||
{
|
||||
toolTipText = TextManager.GetWithVariable("displayname.emptyitem", "[itemname]", toolTipText);
|
||||
@@ -375,7 +418,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
toolTipText += '\n' + requiredItem.ItemPrefabs.First().Description;
|
||||
}
|
||||
tooltip = new Pair<Rectangle, string>(slotRect, toolTipText);
|
||||
tooltip = (slotRect, toolTipText);
|
||||
}
|
||||
|
||||
slotIndex++;
|
||||
@@ -415,7 +458,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
if (tooltip != null)
|
||||
{
|
||||
GUIComponent.DrawToolTip(spriteBatch, tooltip.Second, tooltip.First);
|
||||
GUIComponent.DrawToolTip(spriteBatch, tooltip.Value.text, tooltip.Value.area);
|
||||
tooltip = null;
|
||||
}
|
||||
}
|
||||
@@ -435,6 +478,22 @@ namespace Barotrauma.Items.Components
|
||||
if (recipe?.DisplayName == null) { continue; }
|
||||
child.Visible = recipe.DisplayName.ToLower().Contains(filter);
|
||||
}
|
||||
|
||||
//go through the elements backwards, and disable the labels ("insufficient skills to fabricate", "recipe required...") if there's no items below them
|
||||
bool recipeVisible = false;
|
||||
foreach (GUIComponent child in itemList.Content.Children.Reverse())
|
||||
{
|
||||
if (!(child.UserData is FabricationRecipe recipe))
|
||||
{
|
||||
child.Visible = recipeVisible;
|
||||
recipeVisible = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
recipeVisible = child.Visible;
|
||||
}
|
||||
}
|
||||
|
||||
itemList.UpdateScrollBarSize();
|
||||
itemList.BarScroll = 0.0f;
|
||||
|
||||
@@ -470,14 +529,30 @@ namespace Barotrauma.Items.Components
|
||||
};
|
||||
}*/
|
||||
|
||||
string itemName = GetRecipeNameAndAmount(selectedItem);
|
||||
string name = itemName;
|
||||
|
||||
float quality = GetFabricatedItemQuality(selectedItem, user);
|
||||
if (quality > 0)
|
||||
{
|
||||
name = TextManager.GetWithVariable("itemname.quality" + (int)quality, "[itemname]", itemName + '\n', fallBackTag: "itemname.quality3");
|
||||
}
|
||||
|
||||
var nameBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedFrame.RectTransform),
|
||||
GetRecipeNameAndAmount(selectedItem), textAlignment: Alignment.CenterLeft, textColor: Color.Aqua, font: GUI.SubHeadingFont)
|
||||
name, textAlignment: Alignment.TopLeft, textColor: Color.Aqua, font: GUI.SubHeadingFont, parseRichText: true)
|
||||
{
|
||||
AutoScaleHorizontal = true
|
||||
};
|
||||
|
||||
nameBlock.Padding = new Vector4(0, nameBlock.Padding.Y, nameBlock.Padding.Z, nameBlock.Padding.W);
|
||||
nameBlock.Padding = new Vector4(0, nameBlock.Padding.Y, GUI.IntScale(5), nameBlock.Padding.W);
|
||||
if (nameBlock.TextScale < 0.7f)
|
||||
{
|
||||
nameBlock.SetRichText(TextManager.GetWithVariable("itemname.quality" + (int)quality, "[itemname]", itemName, fallBackTag: "itemname.quality3"));
|
||||
nameBlock.AutoScaleHorizontal = false;
|
||||
nameBlock.TextScale = 0.7f;
|
||||
nameBlock.Wrap = true;
|
||||
nameBlock.SetTextPos();
|
||||
nameBlock.RectTransform.MinSize = new Point(0, (int)(nameBlock.TextSize.Y * nameBlock.TextScale));
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(selectedItem.TargetItem.Description))
|
||||
{
|
||||
@@ -489,6 +564,7 @@ namespace Barotrauma.Items.Components
|
||||
while (description.Rect.Height + nameBlock.Rect.Height > paddedFrame.Rect.Height)
|
||||
{
|
||||
var lines = description.WrappedText.Split('\n');
|
||||
if (lines.Length <= 1) { break; }
|
||||
var newString = string.Join('\n', lines.Take(lines.Length - 1));
|
||||
description.Text = newString.Substring(0, newString.Length - 4) + "...";
|
||||
description.CalculateHeightFromText();
|
||||
@@ -598,10 +674,15 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
foreach (GUIComponent child in itemList.Content.Children)
|
||||
{
|
||||
var itemPrefab = child.UserData as FabricationRecipe;
|
||||
if (itemPrefab == null) continue;
|
||||
if (!(child.UserData is FabricationRecipe itemPrefab)) { continue; }
|
||||
|
||||
bool canBeFabricated = CanBeFabricated(itemPrefab, availableIngredients);
|
||||
if (itemPrefab != selectedItem &&
|
||||
(child.Rect.Y > itemList.Rect.Bottom || child.Rect.Bottom < itemList.Rect.Y))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
bool canBeFabricated = CanBeFabricated(itemPrefab, availableIngredients, character);
|
||||
if (itemPrefab == selectedItem)
|
||||
{
|
||||
activateButton.Enabled = canBeFabricated;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -142,6 +142,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
partial void UpdateProjSpecific(float deltaTime)
|
||||
{
|
||||
float rotationRad = MathHelper.ToRadians(item.Rotation);
|
||||
if (FlowPercentage < 0.0f)
|
||||
{
|
||||
foreach (var (position, emitter) in pumpOutEmitters)
|
||||
@@ -149,12 +150,13 @@ namespace Barotrauma.Items.Components
|
||||
if (item.CurrentHull != null && item.CurrentHull.Surface < item.Rect.Location.Y + position.Y) { continue; }
|
||||
|
||||
//only emit "pump out" particles when underwater
|
||||
Vector2 relativeParticlePos = (item.WorldRect.Location.ToVector2() + position * item.Scale) - item.WorldPosition;
|
||||
float angle = 0.0f;
|
||||
Vector2 relativeParticlePos = (item.WorldRect.Location.ToVector2() + position * item.Scale) - item.WorldPosition;
|
||||
relativeParticlePos = MathUtils.RotatePoint(relativeParticlePos, item.FlippedX ? rotationRad : -rotationRad);
|
||||
float angle = -rotationRad;
|
||||
if (item.FlippedX)
|
||||
{
|
||||
relativeParticlePos.X = -relativeParticlePos.X;
|
||||
angle = MathHelper.Pi;
|
||||
angle += MathHelper.Pi;
|
||||
}
|
||||
if (item.FlippedY)
|
||||
{
|
||||
@@ -170,11 +172,12 @@ namespace Barotrauma.Items.Components
|
||||
foreach (var (position, emitter) in pumpInEmitters)
|
||||
{
|
||||
Vector2 relativeParticlePos = (item.WorldRect.Location.ToVector2() + position * item.Scale) - item.WorldPosition;
|
||||
float angle = 0.0f;
|
||||
relativeParticlePos = MathUtils.RotatePoint(relativeParticlePos, item.FlippedX ? rotationRad : -rotationRad);
|
||||
float angle = -rotationRad;
|
||||
if (item.FlippedX)
|
||||
{
|
||||
relativeParticlePos.X = -relativeParticlePos.X;
|
||||
angle = MathHelper.Pi;
|
||||
angle += MathHelper.Pi;
|
||||
}
|
||||
if (item.FlippedY)
|
||||
{
|
||||
|
||||
@@ -134,6 +134,14 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
private static string caveLabel;
|
||||
|
||||
|
||||
[Serialize(false, false)]
|
||||
public bool RightLayout
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
private bool AllowUsingMineralScanner =>
|
||||
HasMineralScanner && !isConnectedToSteering;
|
||||
|
||||
@@ -316,7 +324,7 @@ namespace Barotrauma.Items.Components
|
||||
"", warningColor, GUI.LargeFont, Alignment.Center);
|
||||
|
||||
// Setup layout for nav terminal
|
||||
if (isConnectedToSteering)
|
||||
if (isConnectedToSteering || RightLayout)
|
||||
{
|
||||
controlContainer.RectTransform.RelativeOffset = controlBoxOffset;
|
||||
controlContainer.RectTransform.SetPosition(Anchor.TopRight);
|
||||
@@ -446,13 +454,8 @@ namespace Barotrauma.Items.Components
|
||||
zoomSlider.BarScroll += PlayerInput.ScrollWheelSpeed / 1000.0f;
|
||||
zoomSlider.OnMoved(zoomSlider, zoomSlider.BarScroll);
|
||||
}
|
||||
|
||||
if (PlayerInput.KeyHit(InputType.Run))
|
||||
{
|
||||
SonarModeSwitch.OnClicked(SonarModeSwitch, null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
float distort = 1.0f - item.Condition / item.MaxCondition;
|
||||
for (int i = sonarBlips.Count - 1; i >= 0; i--)
|
||||
{
|
||||
@@ -885,7 +888,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
foreach (AITarget aiTarget in AITarget.List)
|
||||
{
|
||||
if (!aiTarget.Enabled) { continue; }
|
||||
if (aiTarget.InDetectable) { continue; }
|
||||
if (string.IsNullOrEmpty(aiTarget.SonarLabel) || aiTarget.SoundRange <= 0.0f) { continue; }
|
||||
|
||||
if (Vector2.DistanceSquared(aiTarget.WorldPosition, transducerCenter) < aiTarget.SoundRange * aiTarget.SoundRange)
|
||||
@@ -1239,7 +1242,7 @@ namespace Barotrauma.Items.Components
|
||||
foreach (AITarget aiTarget in AITarget.List)
|
||||
{
|
||||
float disruption = aiTarget.Entity is Character c ? c.Params.SonarDisruption : aiTarget.SonarDisruption;
|
||||
if (disruption <= 0.0f || !aiTarget.Enabled) { continue; }
|
||||
if (disruption <= 0.0f || aiTarget.InDetectable) { continue; }
|
||||
float distSqr = Vector2.DistanceSquared(aiTarget.WorldPosition, pingSource);
|
||||
if (distSqr > worldPingRadiusSqr) { continue; }
|
||||
float disruptionDist = (float)Math.Sqrt(distSqr);
|
||||
@@ -1364,28 +1367,6 @@ namespace Barotrauma.Items.Components
|
||||
blipType : cell.IsDestructible ? BlipType.Destructible : BlipType.Default);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (RuinGeneration.Ruin ruin in Level.Loaded.Ruins)
|
||||
{
|
||||
if (!MathUtils.CircleIntersectsRectangle(pingSource, range, ruin.Area)) continue;
|
||||
|
||||
foreach (var ruinShape in ruin.RuinShapes)
|
||||
{
|
||||
foreach (RuinGeneration.Line wall in ruinShape.Walls)
|
||||
{
|
||||
float cellDot = Vector2.Dot(
|
||||
Vector2.Normalize(ruinShape.Center - pingSource),
|
||||
Vector2.Normalize((wall.A + wall.B) / 2.0f - ruinShape.Center));
|
||||
if (cellDot > 0) continue;
|
||||
|
||||
CreateBlipsForLine(
|
||||
wall.A, wall.B,
|
||||
pingSource, transducerPos,
|
||||
pingRadius, prevPingRadius,
|
||||
100.0f, 1000.0f, range, pingStrength, passive);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (Item item in Item.ItemList)
|
||||
@@ -1634,7 +1615,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
void CalculateDistance()
|
||||
{
|
||||
pathFinder ??= new PathFinder(WayPoint.WayPointList, indoorsSteering: false);
|
||||
pathFinder ??= new PathFinder(WayPoint.WayPointList, false);
|
||||
var path = pathFinder.FindPath(ConvertUnits.ToSimUnits(transducerPosition), ConvertUnits.ToSimUnits(worldPosition));
|
||||
if (!path.Unreachable)
|
||||
{
|
||||
|
||||
@@ -888,6 +888,7 @@ namespace Barotrauma.Items.Components
|
||||
maintainPosOriginIndicator?.Remove();
|
||||
steeringIndicator?.Remove();
|
||||
enterOutpostPrompt?.Close();
|
||||
pathFinder = null;
|
||||
}
|
||||
|
||||
public void ClientWrite(IWriteMessage msg, object[] extraData = null)
|
||||
|
||||
@@ -71,7 +71,7 @@ namespace Barotrauma.Items.Components
|
||||
var chargeText = new GUITextBlock(new RectTransform(new Vector2(0.6f, 1), textArea.RectTransform, Anchor.CenterRight),
|
||||
"", textColor: GUI.Style.TextColor, font: GUI.Font, textAlignment: Alignment.CenterRight)
|
||||
{
|
||||
TextGetter = () => $"{(int)charge}/{(int)capacity} {kWmin} ({((int)MathUtils.Percentage(charge, capacity)).ToString()} %)"
|
||||
TextGetter = () => $"{(int)Math.Round(charge)}/{(int)capacity} {kWmin} ({(int)Math.Round(MathUtils.Percentage(charge, capacity))} %)"
|
||||
};
|
||||
if (chargeText.TextSize.X > chargeText.Rect.Width) { chargeText.Font = GUI.SmallFont; }
|
||||
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
{
|
||||
partial class Quality : ItemComponent
|
||||
{
|
||||
public override void AddTooltipInfo(ref string name, ref string description)
|
||||
{
|
||||
foreach (var statValue in statValues)
|
||||
{
|
||||
int roundedValue = (int)Math.Round(statValue.Value * qualityLevel * 100);
|
||||
if (roundedValue == 0) { return; }
|
||||
string colorStr = XMLExtensions.ColorToString(GUI.Style.Green);
|
||||
description += $"\n ‖color:{colorStr}‖{roundedValue.ToString("+0;-#")}%‖color:end‖ {TextManager.Get("qualitystattypenames." + statValue.Key.ToString(), true) ?? statValue.Key.ToString()}";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
{
|
||||
partial class RemoteController : ItemComponent
|
||||
{
|
||||
public override void DrawHUD(SpriteBatch spriteBatch, Character character)
|
||||
{
|
||||
currentTarget?.DrawHUD(spriteBatch, Screen.Selected.Cam, character);
|
||||
}
|
||||
|
||||
public override void UpdateHUD(Character character, float deltaTime, Camera cam)
|
||||
{
|
||||
currentTarget?.UpdateHUD(cam, character,deltaTime);
|
||||
}
|
||||
|
||||
public override void AddToGUIUpdateList(int order = 0)
|
||||
{
|
||||
currentTarget?.AddToGUIUpdateList(order: -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,16 +15,23 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public GUIButton SabotageButton { get; private set; }
|
||||
|
||||
public GUIButton TinkerButton { get; private set; }
|
||||
|
||||
private GUIProgressBar progressBar;
|
||||
|
||||
private List<ParticleEmitter> particleEmitters = new List<ParticleEmitter>();
|
||||
private GUITextBlock progressBarOverlayText;
|
||||
|
||||
private GUILayoutGroup extraButtonContainer;
|
||||
|
||||
private readonly List<ParticleEmitter> particleEmitters = new List<ParticleEmitter>();
|
||||
//the corresponding particle emitter is active when the condition is within this range
|
||||
private List<Vector2> particleEmitterConditionRanges = new List<Vector2>();
|
||||
private readonly List<Vector2> particleEmitterConditionRanges = new List<Vector2>();
|
||||
|
||||
private SoundChannel repairSoundChannel;
|
||||
|
||||
private string repairButtonText, repairingText;
|
||||
private string sabotageButtonText, sabotagingText;
|
||||
private string tinkerButtonText, tinkeringText;
|
||||
|
||||
private FixActions requestStartFixAction;
|
||||
|
||||
@@ -45,8 +52,24 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public override bool ShouldDrawHUD(Character character)
|
||||
{
|
||||
if (!HasRequiredItems(character, false) || character.SelectedConstruction != item) return false;
|
||||
return item.ConditionPercentage < RepairThreshold || character.IsTraitor && item.ConditionPercentage > MinSabotageCondition || (CurrentFixer == character && (!item.IsFullCondition || (character.IsTraitor && item.ConditionPercentage > MinSabotageCondition)));
|
||||
if (!HasRequiredItems(character, false) || character.SelectedConstruction != item) { return false; }
|
||||
if (character.IsTraitor && item.ConditionPercentage > MinSabotageCondition) { return true; }
|
||||
|
||||
float maxRepairConditionMultiplier = GetMaxRepairConditionMultiplier(character);
|
||||
if (item.Condition / maxRepairConditionMultiplier < RepairThreshold) { return true; }
|
||||
|
||||
if (CurrentFixer == character)
|
||||
{
|
||||
float condition = item.Condition / item.MaxRepairConditionMultiplier;
|
||||
float maxCondition = item.MaxCondition / item.MaxRepairConditionMultiplier;
|
||||
if (condition < maxCondition * maxRepairConditionMultiplier)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (IsTinkerable(character)) { return true; }
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
partial void InitProjSpecific(XElement element)
|
||||
@@ -85,7 +108,7 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
private void CreateGUI()
|
||||
protected override void CreateGUI()
|
||||
{
|
||||
var paddedFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.8f, 0.75f), GuiFrame.RectTransform, Anchor.Center), childAnchor: Anchor.TopCenter)
|
||||
{
|
||||
@@ -120,6 +143,11 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
progressBar = new GUIProgressBar(new RectTransform(new Vector2(0.6f, 1.0f), progressBarHolder.RectTransform),
|
||||
color: GUI.Style.Green, barSize: 0.0f, style: "DeviceProgressBar");
|
||||
progressBarOverlayText = new GUITextBlock(new RectTransform(Vector2.One, progressBar.RectTransform), string.Empty, font: GUI.SubHeadingFont, textAlignment: Alignment.Center)
|
||||
{
|
||||
IgnoreLayoutGroups = true
|
||||
};
|
||||
|
||||
repairButtonText = TextManager.Get("RepairButton");
|
||||
repairingText = TextManager.Get("Repairing");
|
||||
RepairButton = new GUIButton(new RectTransform(new Vector2(0.4f, 1.0f), progressBarHolder.RectTransform, Anchor.TopCenter), repairButtonText)
|
||||
@@ -135,9 +163,16 @@ namespace Barotrauma.Items.Components
|
||||
progressBarHolder.RectTransform.MinSize = RepairButton.RectTransform.MinSize;
|
||||
RepairButton.RectTransform.MinSize = new Point((int)(RepairButton.TextBlock.TextSize.X * 1.2f), RepairButton.RectTransform.MinSize.Y);
|
||||
|
||||
extraButtonContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.15f), paddedFrame.RectTransform), isHorizontal: true)
|
||||
{
|
||||
IgnoreLayoutGroups = true,
|
||||
Stretch = true,
|
||||
AbsoluteSpacing = GUI.IntScale(5)
|
||||
};
|
||||
|
||||
sabotageButtonText = TextManager.Get("SabotageButton");
|
||||
sabotagingText = TextManager.Get("Sabotaging");
|
||||
SabotageButton = new GUIButton(new RectTransform(new Vector2(0.8f, 0.15f), paddedFrame.RectTransform, Anchor.BottomCenter), sabotageButtonText, style: "GUIButtonSmall")
|
||||
SabotageButton = new GUIButton(new RectTransform(Vector2.One, extraButtonContainer.RectTransform), sabotageButtonText, style: "GUIButtonSmall")
|
||||
{
|
||||
IgnoreLayoutGroups = true,
|
||||
Visible = false,
|
||||
@@ -148,6 +183,22 @@ namespace Barotrauma.Items.Components
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
tinkerButtonText = TextManager.Get("TinkerButton", returnNull: true) ?? "Tinker";
|
||||
tinkeringText = TextManager.Get("Tinkering", returnNull: true) ?? "Tinkering";
|
||||
TinkerButton = new GUIButton(new RectTransform(Vector2.One, extraButtonContainer.RectTransform), tinkerButtonText, style: "GUIButtonSmall")
|
||||
{
|
||||
IgnoreLayoutGroups = true,
|
||||
Visible = false,
|
||||
OnClicked = (btn, obj) =>
|
||||
{
|
||||
requestStartFixAction = FixActions.Tinker;
|
||||
item.CreateClientEvent(this);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
extraButtonContainer.RectTransform.MinSize = new Point(0, SabotageButton.RectTransform.MinSize.Y);
|
||||
}
|
||||
|
||||
partial void UpdateProjSpecific(float deltaTime)
|
||||
@@ -176,6 +227,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
case FixActions.Repair:
|
||||
case FixActions.Sabotage:
|
||||
case FixActions.Tinker:
|
||||
StartRepairing(Character.Controlled, requestStartFixAction);
|
||||
requestStartFixAction = FixActions.None;
|
||||
break;
|
||||
@@ -211,10 +263,24 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
IsActive = true;
|
||||
|
||||
progressBar.BarSize = item.Condition / item.MaxCondition;
|
||||
float defaultMaxCondition = (item.MaxCondition / item.MaxRepairConditionMultiplier);
|
||||
|
||||
progressBar.BarSize = item.Condition / defaultMaxCondition;
|
||||
progressBar.Color = ToolBox.GradientLerp(progressBar.BarSize, GUI.Style.Red, GUI.Style.Orange, GUI.Style.Green);
|
||||
|
||||
RepairButton.Enabled = (currentFixerAction == FixActions.None || (CurrentFixer == character && currentFixerAction != FixActions.Repair)) && !item.IsFullCondition;
|
||||
if (item.Condition > defaultMaxCondition)
|
||||
{
|
||||
float extraCondition = item.MaxCondition * (item.MaxRepairConditionMultiplier - 1.0f);
|
||||
progressBar.Color = ToolBox.GradientLerp((item.Condition - defaultMaxCondition) / extraCondition, GUI.Style.ColorReputationHigh, GUI.Style.ColorReputationVeryHigh);
|
||||
progressBarOverlayText.Visible = true;
|
||||
progressBarOverlayText.Text = $"{(int)Math.Round((item.Condition / defaultMaxCondition) * 100)}%";
|
||||
}
|
||||
else
|
||||
{
|
||||
progressBarOverlayText.Visible = false;
|
||||
}
|
||||
|
||||
RepairButton.Enabled = (currentFixerAction == FixActions.None || (CurrentFixer == character && currentFixerAction != FixActions.Repair)) && !item.IsFullCondition && item.ConditionPercentage < RepairThreshold;
|
||||
RepairButton.Text = (currentFixerAction == FixActions.None || CurrentFixer != character || currentFixerAction != FixActions.Repair) ?
|
||||
repairButtonText :
|
||||
repairingText + new string('.', ((int)(Timing.TotalTime * 2.0f) % 3) + 1);
|
||||
@@ -226,7 +292,18 @@ namespace Barotrauma.Items.Components
|
||||
sabotageButtonText :
|
||||
sabotagingText + new string('.', ((int)(Timing.TotalTime * 2.0f) % 3) + 1);
|
||||
|
||||
TinkerButton.Visible = IsTinkerable(character);
|
||||
TinkerButton.IgnoreLayoutGroups = !TinkerButton.Visible;
|
||||
TinkerButton.Enabled = (currentFixerAction == FixActions.None || (CurrentFixer == character && currentFixerAction != FixActions.Tinker)) && CanTinker(character);
|
||||
TinkerButton.Text = (currentFixerAction == FixActions.None || CurrentFixer != character || currentFixerAction != FixActions.Tinker) ?
|
||||
tinkerButtonText :
|
||||
tinkeringText + new string('.', ((int)(Timing.TotalTime * 2.0f) % 3) + 1);
|
||||
|
||||
System.Diagnostics.Debug.Assert(GuiFrame.GetChild(0) is GUILayoutGroup, "Repair UI hierarchy has changed, could not find skill texts");
|
||||
|
||||
extraButtonContainer.Visible = SabotageButton.Visible || TinkerButton.Visible;
|
||||
extraButtonContainer.IgnoreLayoutGroups = !extraButtonContainer.Visible;
|
||||
|
||||
foreach (GUIComponent c in GuiFrame.GetChild(0).Children)
|
||||
{
|
||||
if (!(c.UserData is Skill skill)) continue;
|
||||
@@ -278,9 +355,12 @@ namespace Barotrauma.Items.Components
|
||||
deteriorationTimer = msg.ReadSingle();
|
||||
deteriorateAlwaysResetTimer = msg.ReadSingle();
|
||||
DeteriorateAlways = msg.ReadBoolean();
|
||||
tinkeringDuration = msg.ReadSingle();
|
||||
tinkeringStrength = msg.ReadSingle();
|
||||
ushort currentFixerID = msg.ReadUInt16();
|
||||
currentFixerAction = (FixActions)msg.ReadRangedInteger(0, 2);
|
||||
CurrentFixer = currentFixerID != 0 ? Entity.FindEntityByID(currentFixerID) as Character : null;
|
||||
item.MaxRepairConditionMultiplier = GetMaxRepairConditionMultiplier(CurrentFixer);
|
||||
}
|
||||
|
||||
public void ClientWrite(IWriteMessage msg, object[] extraData = null)
|
||||
|
||||
@@ -31,6 +31,9 @@ namespace Barotrauma.Items.Components
|
||||
set;
|
||||
}
|
||||
|
||||
[Serialize("0.5,0.5)", false)]
|
||||
public Vector2 Origin { get; set; } = new Vector2(0.5f, 0.5f);
|
||||
|
||||
public Vector2 DrawSize
|
||||
{
|
||||
get
|
||||
@@ -57,7 +60,6 @@ namespace Barotrauma.Items.Components
|
||||
sourcePos = sourceLimb.body.DrawPosition;
|
||||
}
|
||||
return sourcePos;
|
||||
|
||||
}
|
||||
|
||||
partial void InitProjSpecific(XElement element)
|
||||
@@ -81,13 +83,15 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public void Draw(SpriteBatch spriteBatch, bool editing, float itemDepth = -1)
|
||||
{
|
||||
if (target == null) { return; }
|
||||
if (target == null || target.Removed) { return; }
|
||||
if (target.ParentInventory != null) { return; }
|
||||
|
||||
Vector2 startPos = GetSourcePos();
|
||||
startPos.Y = -startPos.Y;
|
||||
if (source is Item sourceItem)
|
||||
{
|
||||
var turret = sourceItem?.GetComponent<Turret>();
|
||||
var turret = sourceItem.GetComponent<Turret>();
|
||||
var weapon = sourceItem.GetComponent<RangedWeapon>();
|
||||
if (turret != null)
|
||||
{
|
||||
startPos = new Vector2(sourceItem.WorldRect.X + turret.TransformedBarrelPos.X, -(sourceItem.WorldRect.Y - turret.TransformedBarrelPos.Y));
|
||||
@@ -96,8 +100,21 @@ namespace Barotrauma.Items.Components
|
||||
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;
|
||||
}
|
||||
}
|
||||
else if (weapon != null)
|
||||
{
|
||||
Vector2 barrelPos = FarseerPhysics.ConvertUnits.ToDisplayUnits(weapon.TransformedBarrelPos);
|
||||
barrelPos.Y = -barrelPos.Y;
|
||||
startPos += barrelPos;
|
||||
}
|
||||
}
|
||||
Vector2 endPos = new Vector2(target.DrawPosition.X, -target.DrawPosition.Y);
|
||||
Vector2 endPos = new Vector2(target.DrawPosition.X, target.DrawPosition.Y);
|
||||
Vector2 flippedPos = target.Sprite.size * target.Scale * (Origin - new Vector2(0.5f));
|
||||
if (target.body.Dir < 0.0f)
|
||||
{
|
||||
flippedPos.X = -flippedPos.X;
|
||||
}
|
||||
endPos += Vector2.Transform(flippedPos, Matrix.CreateRotationZ(target.body.Rotation));
|
||||
endPos.Y = -endPos.Y;
|
||||
|
||||
if (Snapped)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
using Barotrauma.Networking;
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
{
|
||||
partial class Scanner : ItemComponent, IServerSerializable
|
||||
{
|
||||
partial void UpdateProjSpecific()
|
||||
{
|
||||
if (Holdable != null && Holdable.Attached && (AlwaysDisplayProgressBar || DisplayProgressBar) && !IsScanCompleted)
|
||||
{
|
||||
Character.Controlled?.UpdateHUDProgressBar(this,
|
||||
item.WorldPosition,
|
||||
ScanTimer / ScanDuration,
|
||||
GUI.Style.Red, GUI.Style.Green,
|
||||
textTag: "progressbar.scanning");
|
||||
}
|
||||
}
|
||||
|
||||
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
||||
{
|
||||
bool wasScanCompletedPreviously = IsScanCompleted;
|
||||
scanTimer = msg.ReadSingle();
|
||||
if (!wasScanCompletedPreviously && IsScanCompleted)
|
||||
{
|
||||
OnScanCompleted?.Invoke(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
using Barotrauma.Extensions;
|
||||
using Barotrauma.Networking;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
{
|
||||
partial class ButtonTerminal : ItemComponent, IClientSerializable, IServerSerializable
|
||||
{
|
||||
private string[] terminalButtonStyles;
|
||||
private GUIFrame containerHolder;
|
||||
private GUIImage containerIndicator;
|
||||
private GUIComponentStyle indicatorStyleRed, indicatorStyleGreen;
|
||||
|
||||
partial void InitProjSpecific(XElement element)
|
||||
{
|
||||
terminalButtonStyles = new string[RequiredSignalCount];
|
||||
int i = 0;
|
||||
foreach (var childElement in element.GetChildElements("TerminalButton"))
|
||||
{
|
||||
string style = childElement.GetAttributeString("style", null);
|
||||
if (style == null) { continue; }
|
||||
terminalButtonStyles[i++] = style;
|
||||
}
|
||||
indicatorStyleRed = GUI.Style.GetComponentStyle("IndicatorLightRed");
|
||||
indicatorStyleGreen = GUI.Style.GetComponentStyle("IndicatorLightGreen");
|
||||
CreateGUI();
|
||||
}
|
||||
|
||||
protected override void CreateGUI()
|
||||
{
|
||||
var paddedFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.8f), GuiFrame.RectTransform, Anchor.Center), isHorizontal: true, childAnchor: Anchor.CenterLeft)
|
||||
{
|
||||
Stretch = true,
|
||||
RelativeSpacing = 0.08f
|
||||
};
|
||||
paddedFrame.OnAddedToGUIUpdateList += (component) =>
|
||||
{
|
||||
bool buttonsEnabled = AllowUsingButtons;
|
||||
foreach (var child in component.Children)
|
||||
{
|
||||
if (!(child is GUIButton)) { continue; }
|
||||
if (!(child.UserData is int)) { continue; }
|
||||
child.Enabled = buttonsEnabled;
|
||||
child.Children.ForEach(c => c.Enabled = buttonsEnabled);
|
||||
}
|
||||
bool itemsContained = Container.Inventory.AllItems.Any();
|
||||
if (itemsContained)
|
||||
{
|
||||
var indicatorStyle = buttonsEnabled ? indicatorStyleGreen : indicatorStyleRed;
|
||||
if (containerIndicator.Style != indicatorStyle)
|
||||
{
|
||||
containerIndicator.ApplyStyle(indicatorStyle);
|
||||
}
|
||||
}
|
||||
containerIndicator.OverrideState = itemsContained ? GUIComponent.ComponentState.Selected : GUIComponent.ComponentState.None;
|
||||
};
|
||||
|
||||
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);
|
||||
|
||||
var containerSection = new GUIFrame(new RectTransform(new Vector2(x, 1.0f), paddedFrame.RectTransform), style: null);
|
||||
var containerSlot = new GUIFrame(new RectTransform(new Vector2(1.0f, y), containerSection.RectTransform, anchor: Anchor.Center), style: null);
|
||||
containerHolder = new GUIFrame(new RectTransform(new Vector2(1f, 1.2f), containerSlot.RectTransform, Anchor.BottomCenter), style: null);
|
||||
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++)
|
||||
{
|
||||
var button = new GUIButton(new RectTransform(relativeSize, paddedFrame.RectTransform), style: null)
|
||||
{
|
||||
UserData = i,
|
||||
OnClicked = (button, userData) =>
|
||||
{
|
||||
if (GameMain.IsSingleplayer)
|
||||
{
|
||||
SendSignal((int)userData);
|
||||
}
|
||||
else
|
||||
{
|
||||
item.CreateClientEvent(this, new object[] { userData });
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
var image = new GUIImage(new RectTransform(Vector2.One, button.RectTransform), terminalButtonStyles[i], scaleToFit: true);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnResolutionChanged()
|
||||
{
|
||||
base.OnResolutionChanged();
|
||||
OnItemLoadedProjSpecific();
|
||||
}
|
||||
|
||||
partial void OnItemLoadedProjSpecific()
|
||||
{
|
||||
Container.AllowUIOverlap = true;
|
||||
Container.Inventory.RectTransform = containerHolder.RectTransform;
|
||||
}
|
||||
|
||||
public void ClientWrite(IWriteMessage msg, object[] extraData = null)
|
||||
{
|
||||
Write(msg, extraData);
|
||||
}
|
||||
|
||||
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
||||
{
|
||||
SendSignal(msg.ReadRangedInteger(0, Signals.Length - 1), isServerMessage: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -54,6 +54,11 @@ namespace Barotrauma.Items.Components
|
||||
if (wireComponent != null)
|
||||
{
|
||||
equippedWire = wireComponent;
|
||||
var connectedEnd = equippedWire.OtherConnection(null);
|
||||
if (connectedEnd?.Item.Submarine != null && panel.Item.Submarine != connectedEnd.Item.Submarine)
|
||||
{
|
||||
equippedWire = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,11 +88,6 @@ namespace Barotrauma.Items.Components
|
||||
return character == Character.Controlled && character == user && character.SelectedConstruction == item;
|
||||
}
|
||||
|
||||
public override void AddToGUIUpdateList()
|
||||
{
|
||||
GuiFrame?.AddToGUIUpdateList();
|
||||
}
|
||||
|
||||
public override void UpdateHUD(Character character, float deltaTime, Camera cam)
|
||||
{
|
||||
if (character != Character.Controlled || character != user || character.SelectedConstruction != item) { return; }
|
||||
|
||||
@@ -63,11 +63,11 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
|
||||
OutputValue = input;
|
||||
ShowOnDisplay(input);
|
||||
ShowOnDisplay(input, addToHistory: true);
|
||||
item.SendSignal(input, "signal_out");
|
||||
}
|
||||
|
||||
partial void ShowOnDisplay(string input, bool addToHistory = true)
|
||||
partial void ShowOnDisplay(string input, bool addToHistory)
|
||||
{
|
||||
if (addToHistory)
|
||||
{
|
||||
@@ -85,7 +85,7 @@ namespace Barotrauma.Items.Components
|
||||
GUITextBlock newBlock = new GUITextBlock(
|
||||
new RectTransform(new Vector2(1, 0), historyBox.Content.RectTransform, anchor: Anchor.TopCenter),
|
||||
"> " + input,
|
||||
textColor: Color.LimeGreen, wrap: true)
|
||||
textColor: Color.LimeGreen, wrap: true, font: UseMonospaceFont ? GUI.MonospacedFont : GUI.GlobalFont)
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
@@ -118,9 +118,9 @@ namespace Barotrauma.Items.Components
|
||||
// This method is overrided instead of the UpdateHUD method because this ensures the input box is selected
|
||||
// even when the terminal component is selected for the very first time. Doing the input box selection in the
|
||||
// UpdateHUD method only selects the input box on every terminal selection except for the very first time.
|
||||
public override void AddToGUIUpdateList()
|
||||
public override void AddToGUIUpdateList(int order = 0)
|
||||
{
|
||||
base.AddToGUIUpdateList();
|
||||
base.AddToGUIUpdateList(order: order);
|
||||
if (shouldSelectInputBox)
|
||||
{
|
||||
inputBox.Select();
|
||||
|
||||
@@ -39,6 +39,34 @@ namespace Barotrauma.Items.Components
|
||||
private set;
|
||||
}
|
||||
|
||||
[Serialize(false, false)]
|
||||
public bool ThermalGoggles
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
[Serialize(true, false)]
|
||||
public bool ShowDeadCharacters
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
[Serialize(true, false)]
|
||||
public bool ShowTexts
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
[Serialize("72,119,72,120", false)]
|
||||
public Color OverlayColor
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
private readonly List<Character> visibleCharacters = new List<Character>();
|
||||
|
||||
private const float UpdateInterval = 0.5f;
|
||||
@@ -48,6 +76,8 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
private bool isEquippable;
|
||||
|
||||
private float thermalEffectState;
|
||||
|
||||
public IEnumerable<Character> VisibleCharacters
|
||||
{
|
||||
get
|
||||
@@ -80,7 +110,10 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
refEntity = item;
|
||||
}
|
||||
|
||||
|
||||
thermalEffectState += deltaTime;
|
||||
thermalEffectState %= 10000.0f;
|
||||
|
||||
if (updateTimer > 0.0f)
|
||||
{
|
||||
updateTimer -= deltaTime;
|
||||
@@ -91,6 +124,7 @@ namespace Barotrauma.Items.Components
|
||||
foreach (Character c in Character.CharacterList)
|
||||
{
|
||||
if (c == equipper || !c.Enabled || c.Removed) { continue; }
|
||||
if (!ShowDeadCharacters && c.IsDead) { continue; }
|
||||
|
||||
float dist = Vector2.DistanceSquared(refEntity.WorldPosition, c.WorldPosition);
|
||||
if (dist < Range * Range)
|
||||
@@ -123,27 +157,71 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
if (character == null) { return; }
|
||||
|
||||
GUI.UIGlow.Draw(spriteBatch, new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight),
|
||||
Color.LightGreen * 0.5f);
|
||||
|
||||
Character closestCharacter = null;
|
||||
float closestDist = float.PositiveInfinity;
|
||||
foreach (Character c in visibleCharacters)
|
||||
if (OverlayColor.A > 0)
|
||||
{
|
||||
if (c == character || !c.Enabled || c.Removed) { continue; }
|
||||
|
||||
float dist = Vector2.DistanceSquared(GameMain.GameScreen.Cam.ScreenToWorld(PlayerInput.MousePosition), c.WorldPosition);
|
||||
if (dist < closestDist)
|
||||
{
|
||||
closestCharacter = c;
|
||||
closestDist = dist;
|
||||
}
|
||||
GUI.UIGlow.Draw(spriteBatch, new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight), OverlayColor);
|
||||
}
|
||||
|
||||
if (closestCharacter != null)
|
||||
if (ShowTexts)
|
||||
{
|
||||
float dist = Vector2.Distance(GameMain.GameScreen.Cam.ScreenToWorld(PlayerInput.MousePosition), closestCharacter.WorldPosition);
|
||||
DrawCharacterInfo(spriteBatch, closestCharacter, 1.0f - MathHelper.Max((dist - (Range - FadeOutRange)) / FadeOutRange, 0.0f));
|
||||
Character closestCharacter = null;
|
||||
float closestDist = float.PositiveInfinity;
|
||||
foreach (Character c in visibleCharacters)
|
||||
{
|
||||
if (c == character || !c.Enabled || c.Removed) { continue; }
|
||||
|
||||
float dist = Vector2.DistanceSquared(GameMain.GameScreen.Cam.ScreenToWorld(PlayerInput.MousePosition), c.WorldPosition);
|
||||
if (dist < closestDist)
|
||||
{
|
||||
closestCharacter = c;
|
||||
closestDist = dist;
|
||||
}
|
||||
}
|
||||
|
||||
if (closestCharacter != null)
|
||||
{
|
||||
float dist = Vector2.Distance(GameMain.GameScreen.Cam.ScreenToWorld(PlayerInput.MousePosition), closestCharacter.WorldPosition);
|
||||
DrawCharacterInfo(spriteBatch, closestCharacter, 1.0f - MathHelper.Max((dist - (Range - FadeOutRange)) / FadeOutRange, 0.0f));
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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 = GUI.Style.UIThermalGlow.Sprite;
|
||||
foreach (Limb limb in c.AnimController.Limbs)
|
||||
{
|
||||
if (limb.Mass < 1.0f) { 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -177,6 +177,10 @@ namespace Barotrauma.Items.Components
|
||||
partial void LaunchProjSpecific()
|
||||
{
|
||||
recoilTimer = RetractionTime;
|
||||
if (user != null)
|
||||
{
|
||||
recoilTimer /= 1 + user.GetStatValue(StatTypes.TurretAttackSpeed);
|
||||
}
|
||||
PlaySound(ActionType.OnUse);
|
||||
Vector2 particlePos = GetRelativeFiringPosition(UseFiringOffsetForMuzzleFlash);
|
||||
foreach (ParticleEmitter emitter in particleEmitters)
|
||||
@@ -534,20 +538,20 @@ namespace Barotrauma.Items.Components
|
||||
minRotationWidget.Draw(spriteBatch, (float)Timing.Step);
|
||||
maxRotationWidget.Draw(spriteBatch, (float)Timing.Step);
|
||||
|
||||
Vector2 GetDrawPos()
|
||||
{
|
||||
Vector2 drawPos = new Vector2(item.Rect.X + transformedBarrelPos.X, item.Rect.Y - transformedBarrelPos.Y);
|
||||
if (item.Submarine != null) { drawPos += item.Submarine.DrawPosition; }
|
||||
drawPos.Y = -drawPos.Y;
|
||||
return drawPos;
|
||||
}
|
||||
|
||||
void UpdateBarrel()
|
||||
{
|
||||
rotation = (minRotation + maxRotation) / 2;
|
||||
}
|
||||
}
|
||||
|
||||
public Vector2 GetDrawPos()
|
||||
{
|
||||
Vector2 drawPos = new Vector2(item.Rect.X + transformedBarrelPos.X, item.Rect.Y - transformedBarrelPos.Y);
|
||||
if (item.Submarine != null) { drawPos += item.Submarine.DrawPosition; }
|
||||
drawPos.Y = -drawPos.Y;
|
||||
return drawPos;
|
||||
}
|
||||
|
||||
private Widget GetWidget(string id, SpriteBatch spriteBatch, int size = 5, float thickness = 1f, Action<Widget> initMethod = null)
|
||||
{
|
||||
Vector2 offset = new Vector2(size / 2 + 5, -10);
|
||||
|
||||
@@ -5,17 +5,17 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
partial class Wearable
|
||||
{
|
||||
private void GetDamageModifierText(ref string description, float damageMultiplier, string afflictionIdentifier)
|
||||
private void GetDamageModifierText(ref string description, DamageModifier damageModifier, string afflictionIdentifier)
|
||||
{
|
||||
int roundedValue = (int)Math.Round((1 - damageMultiplier) * 100);
|
||||
int roundedValue = (int)Math.Round((1 - damageModifier.DamageMultiplier * damageModifier.ProbabilityMultiplier) * 100);
|
||||
if (roundedValue == 0) { return; }
|
||||
string colorStr = XMLExtensions.ColorToString(GUI.Style.Green);
|
||||
description += $"\n ‖color:{colorStr}‖{roundedValue.ToString("-0;+#")}%‖color:end‖ {AfflictionPrefab.List.FirstOrDefault(ap => ap.Identifier.Equals(afflictionIdentifier, StringComparison.OrdinalIgnoreCase))?.Name ?? afflictionIdentifier}";
|
||||
}
|
||||
|
||||
public override void AddTooltipInfo(ref string description)
|
||||
public override void AddTooltipInfo(ref string name, ref string description)
|
||||
{
|
||||
if (damageModifiers.Any(d => !MathUtils.NearlyEqual(d.DamageMultiplier, 1f)) || SkillModifiers.Any())
|
||||
if (damageModifiers.Any(d => !MathUtils.NearlyEqual(d.DamageMultiplier, 1f) || !MathUtils.NearlyEqual(d.ProbabilityMultiplier, 1f)) || SkillModifiers.Any())
|
||||
{
|
||||
description += "\n";
|
||||
}
|
||||
@@ -31,11 +31,11 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
foreach (string afflictionIdentifier in damageModifier.ParsedAfflictionIdentifiers)
|
||||
{
|
||||
GetDamageModifierText(ref description, damageModifier.DamageMultiplier, afflictionIdentifier);
|
||||
GetDamageModifierText(ref description, damageModifier, afflictionIdentifier);
|
||||
}
|
||||
foreach (string afflictionIdentifier in damageModifier.ParsedAfflictionTypes)
|
||||
{
|
||||
GetDamageModifierText(ref description, damageModifier.DamageMultiplier, afflictionIdentifier);
|
||||
GetDamageModifierText(ref description, damageModifier, afflictionIdentifier);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user