Unstable 0.17.4.0
This commit is contained in:
@@ -0,0 +1,185 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
class CameraTransition
|
||||
{
|
||||
public bool Running
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public Camera AssignedCamera;
|
||||
private readonly Alignment? cameraStartPos;
|
||||
private readonly Alignment? cameraEndPos;
|
||||
private readonly float? startZoom;
|
||||
private readonly float? endZoom;
|
||||
|
||||
public readonly float WaitDuration;
|
||||
public readonly float PanDuration;
|
||||
public readonly bool FadeOut;
|
||||
public readonly bool LosFadeIn;
|
||||
|
||||
private readonly CoroutineHandle updateCoroutine;
|
||||
|
||||
private Character prevControlled;
|
||||
|
||||
public bool AllowInterrupt = false;
|
||||
public bool RemoveControlFromCharacter = true;
|
||||
|
||||
public CameraTransition(ISpatialEntity targetEntity, Camera cam, Alignment? cameraStartPos, Alignment? cameraEndPos, bool fadeOut = true, bool losFadeIn = false, float waitDuration = 0f, float panDuration = 10.0f, float? startZoom = null, float? endZoom = null)
|
||||
{
|
||||
WaitDuration = waitDuration;
|
||||
PanDuration = panDuration;
|
||||
FadeOut = fadeOut;
|
||||
LosFadeIn = losFadeIn;
|
||||
this.cameraStartPos = cameraStartPos;
|
||||
this.cameraEndPos = cameraEndPos;
|
||||
this.startZoom = startZoom;
|
||||
this.endZoom = endZoom;
|
||||
AssignedCamera = cam;
|
||||
|
||||
if (targetEntity == null) { return; }
|
||||
|
||||
Running = true;
|
||||
CoroutineManager.StopCoroutines("CameraTransition");
|
||||
updateCoroutine = CoroutineManager.StartCoroutine(Update(targetEntity, cam), "CameraTransition");
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
CoroutineManager.StopCoroutines(updateCoroutine);
|
||||
Running = false;
|
||||
#if CLIENT
|
||||
if (FadeOut) { GUI.ScreenOverlayColor = Color.TransparentBlack; }
|
||||
if (prevControlled != null && !prevControlled.Removed)
|
||||
{
|
||||
Character.Controlled = prevControlled;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
private IEnumerable<CoroutineStatus> Update(ISpatialEntity targetEntity, Camera cam)
|
||||
{
|
||||
if (targetEntity == null || (targetEntity is Entity e && e.Removed)) { yield return CoroutineStatus.Success; }
|
||||
|
||||
prevControlled = Character.Controlled;
|
||||
if (RemoveControlFromCharacter)
|
||||
{
|
||||
#if CLIENT
|
||||
GameMain.LightManager.LosEnabled = false;
|
||||
#endif
|
||||
Character.Controlled = null;
|
||||
}
|
||||
cam.TargetPos = Vector2.Zero;
|
||||
|
||||
float startZoom = this.startZoom ?? cam.Zoom;
|
||||
float endZoom = this.endZoom ?? 0.5f;
|
||||
Vector2 initialCameraPos = cam.Position;
|
||||
Vector2? initialTargetPos = targetEntity?.WorldPosition;
|
||||
|
||||
float timer = -WaitDuration;
|
||||
|
||||
while (timer < PanDuration)
|
||||
{
|
||||
float clampedTimer = Math.Max(timer, 0f);
|
||||
|
||||
if (Screen.Selected != GameMain.GameScreen)
|
||||
{
|
||||
yield return new WaitForSeconds(0.1f);
|
||||
#if CLIENT
|
||||
if (FadeOut) { GUI.ScreenOverlayColor = Color.TransparentBlack; }
|
||||
#endif
|
||||
Running = false;
|
||||
yield return CoroutineStatus.Success;
|
||||
}
|
||||
|
||||
//switched control to some other character during the transition -> remove control again
|
||||
if (Character.Controlled != null)
|
||||
{
|
||||
prevControlled = Character.Controlled;
|
||||
if (RemoveControlFromCharacter)
|
||||
{
|
||||
#if CLIENT
|
||||
GameMain.LightManager.LosEnabled = false;
|
||||
#endif
|
||||
Character.Controlled = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (prevControlled != null && prevControlled.Removed)
|
||||
{
|
||||
prevControlled = null;
|
||||
}
|
||||
#if CLIENT
|
||||
if (AllowInterrupt && PlayerInput.KeyHit(Microsoft.Xna.Framework.Input.Keys.Escape))
|
||||
{
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
Vector2 minPos = targetEntity.WorldPosition;
|
||||
Vector2 maxPos = targetEntity.WorldPosition;
|
||||
if (targetEntity is Submarine sub)
|
||||
{
|
||||
minPos = new Vector2(sub.WorldPosition.X - sub.Borders.Width / 2, sub.WorldPosition.Y - sub.Borders.Height / 2);
|
||||
maxPos = new Vector2(sub.WorldPosition.X + sub.Borders.Width / 2, sub.WorldPosition.Y + sub.Borders.Height / 2);
|
||||
}
|
||||
|
||||
Vector2 startPos = cameraStartPos.HasValue ?
|
||||
new Vector2(
|
||||
MathHelper.Lerp(minPos.X, maxPos.X, (cameraStartPos.Value.ToVector2().X + 1.0f) / 2.0f),
|
||||
MathHelper.Lerp(maxPos.Y, minPos.Y, (cameraStartPos.Value.ToVector2().Y + 1.0f) / 2.0f)) :
|
||||
initialCameraPos;
|
||||
if (!cameraStartPos.HasValue && initialTargetPos.HasValue)
|
||||
{
|
||||
startPos += targetEntity.WorldPosition - initialTargetPos.Value;
|
||||
}
|
||||
Vector2 endPos = cameraEndPos.HasValue ?
|
||||
new Vector2(
|
||||
MathHelper.Lerp(minPos.X, maxPos.X, (cameraEndPos.Value.ToVector2().X + 1.0f) / 2.0f),
|
||||
MathHelper.Lerp(maxPos.Y, minPos.Y, (cameraEndPos.Value.ToVector2().Y + 1.0f) / 2.0f)) :
|
||||
prevControlled?.WorldPosition ?? targetEntity.WorldPosition;
|
||||
|
||||
Vector2 cameraPos = Vector2.SmoothStep(startPos, endPos, clampedTimer / PanDuration);
|
||||
cam.Translate(cameraPos - cam.Position);
|
||||
|
||||
#if CLIENT
|
||||
cam.Zoom = MathHelper.SmoothStep(startZoom, endZoom, clampedTimer / PanDuration);
|
||||
if (clampedTimer / PanDuration > 0.9f)
|
||||
{
|
||||
if (FadeOut) { GUI.ScreenOverlayColor = Color.Lerp(Color.TransparentBlack, Color.Black, ((clampedTimer / PanDuration) - 0.9f) * 10.0f); }
|
||||
}
|
||||
if (LosFadeIn && clampedTimer / PanDuration > 0.8f)
|
||||
{
|
||||
GameMain.LightManager.LosAlpha = ((clampedTimer / PanDuration) - 0.8f) * 5.0f;
|
||||
Lights.LightManager.ViewTarget = prevControlled ?? (targetEntity as Entity);
|
||||
GameMain.LightManager.LosEnabled = true;
|
||||
}
|
||||
#endif
|
||||
timer += CoroutineManager.UnscaledDeltaTime;
|
||||
|
||||
yield return CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
Running = false;
|
||||
|
||||
yield return new WaitForSeconds(0.1f);
|
||||
|
||||
#if CLIENT
|
||||
GUI.ScreenOverlayColor = Color.TransparentBlack;
|
||||
GameMain.LightManager.LosEnabled = true;
|
||||
GameMain.LightManager.LosAlpha = 1f;
|
||||
#endif
|
||||
|
||||
if (prevControlled != null && !prevControlled.Removed)
|
||||
{
|
||||
Character.Controlled = prevControlled;
|
||||
}
|
||||
|
||||
yield return CoroutineStatus.Success;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -39,7 +39,7 @@ namespace Barotrauma
|
||||
targetPos.Y = -targetPos.Y;
|
||||
|
||||
GUI.DrawLine(spriteBatch, pos, targetPos, GUIStyle.Red * 0.5f, 0, 4);
|
||||
if (wallTarget != null)
|
||||
if (wallTarget != null && !IsCoolDownRunning)
|
||||
{
|
||||
Vector2 wallTargetPos = wallTarget.Position;
|
||||
if (wallTarget.Structure.Submarine != null) { wallTargetPos += wallTarget.Structure.Submarine.Position; }
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace Barotrauma
|
||||
|
||||
partial void InitProjSpecific(ContentXElement element)
|
||||
{
|
||||
if (element.Attribute("sound") != null)
|
||||
if (element.GetAttribute("sound") != null)
|
||||
{
|
||||
DebugConsole.ThrowError("Error in attack ("+element+") - sounds should be defined as child elements, not as attributes.");
|
||||
return;
|
||||
|
||||
@@ -152,7 +152,7 @@ namespace Barotrauma
|
||||
case TreatmentEventData _:
|
||||
msg.Write(AnimController.Anim == AnimController.Animation.CPR);
|
||||
break;
|
||||
case StatusEventData _:
|
||||
case CharacterStatusEventData _:
|
||||
//do nothing
|
||||
break;
|
||||
case UpdateTalentsEventData _:
|
||||
@@ -343,8 +343,12 @@ namespace Barotrauma
|
||||
if (controlled == this)
|
||||
{
|
||||
Controlled = null;
|
||||
IsRemotePlayer = ownerID > 0;
|
||||
}
|
||||
if (GameMain.Client?.Character == this)
|
||||
{
|
||||
GameMain.Client.Character = null;
|
||||
}
|
||||
IsRemotePlayer = ownerID > 0;
|
||||
}
|
||||
break;
|
||||
case EventType.Status:
|
||||
@@ -371,7 +375,9 @@ namespace Barotrauma
|
||||
if (attackLimbIndex == 255 || Removed) { break; }
|
||||
if (attackLimbIndex >= AnimController.Limbs.Length)
|
||||
{
|
||||
DebugConsole.ThrowError($"Received invalid {(eventType == EventType.SetAttackTarget ? "SetAttackTarget" : "ExecuteAttack")} message. Limb index out of bounds (character: {Name}, limb index: {attackLimbIndex}, limb count: {AnimController.Limbs.Length})");
|
||||
string errorMsg = $"Received invalid {(eventType == EventType.SetAttackTarget ? "SetAttackTarget" : "ExecuteAttack")} message. Limb index out of bounds (character: {Name}, limb index: {attackLimbIndex}, limb count: {AnimController.Limbs.Length})";
|
||||
DebugConsole.ThrowError(errorMsg);
|
||||
GameAnalyticsManager.AddErrorEventOnce("Character.ClientEventRead:AttackLimbOutOfBounds", GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
|
||||
break;
|
||||
}
|
||||
Limb attackLimb = AnimController.Limbs[attackLimbIndex];
|
||||
@@ -380,13 +386,16 @@ namespace Barotrauma
|
||||
if (targetEntity == null && eventType == EventType.SetAttackTarget)
|
||||
{
|
||||
DebugConsole.ThrowError($"Received invalid SetAttackTarget message. Target entity not found (ID {targetEntityID})");
|
||||
GameAnalyticsManager.AddErrorEventOnce("Character.ClientEventRead:TargetNotFound", GameAnalyticsManager.ErrorSeverity.Error, "Received invalid SetAttackTarget message. Target entity not found.");
|
||||
break;
|
||||
}
|
||||
if (targetEntity is Character targetCharacter)
|
||||
if (targetEntity is Character targetCharacter && targetLimbIndex != 255)
|
||||
{
|
||||
if (targetLimbIndex >= targetCharacter.AnimController.Limbs.Length)
|
||||
{
|
||||
DebugConsole.ThrowError($"Received invalid {(eventType == EventType.SetAttackTarget ? "SetAttackTarget" : "ExecuteAttack")} message. Target limb index out of bounds (target character: {targetCharacter.Name}, limb index: {targetLimbIndex}, limb count: {targetCharacter.AnimController.Limbs.Length})");
|
||||
string errorMsgWithoutName = $"Received invalid {(eventType == EventType.SetAttackTarget ? "SetAttackTarget" : "ExecuteAttack")} message. Target limb index out of bounds (target character: {targetCharacter.SpeciesName}, limb index: {targetLimbIndex}, limb count: {targetCharacter.AnimController.Limbs.Length})";
|
||||
GameAnalyticsManager.AddErrorEventOnce("Character.ClientEventRead:TargetLimbOutOfBounds", GameAnalyticsManager.ErrorSeverity.Error, errorMsgWithoutName);
|
||||
break;
|
||||
}
|
||||
targetLimb = targetCharacter.AnimController.Limbs[targetLimbIndex];
|
||||
@@ -560,6 +569,10 @@ namespace Barotrauma
|
||||
}
|
||||
character.TeamID = (CharacterTeamType)teamID;
|
||||
character.CampaignInteractionType = (CampaignMode.InteractionType)inc.ReadByte();
|
||||
if (character.CampaignInteractionType == CampaignMode.InteractionType.Store)
|
||||
{
|
||||
character.MerchantIdentifier = inc.ReadIdentifier();
|
||||
}
|
||||
character.Wallet.Balance = balance;
|
||||
character.Wallet.RewardDistribution = rewardDistribution;
|
||||
if (character.CampaignInteractionType != CampaignMode.InteractionType.None)
|
||||
|
||||
@@ -400,7 +400,7 @@ namespace Barotrauma
|
||||
{
|
||||
if (GameMain.Client != null)
|
||||
{
|
||||
GameMain.Client.CreateEntityEvent(Character.Controlled, new Character.StatusEventData());
|
||||
GameMain.Client.CreateEntityEvent(Character.Controlled, new Character.CharacterStatusEventData());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
+16
-8
@@ -12,22 +12,30 @@ namespace Barotrauma
|
||||
{
|
||||
public sealed partial class PackageSource : ICollection<ContentPackage>
|
||||
{
|
||||
public ContentPackage SaveAndEnableRegularMod(ModProject modProject)
|
||||
public string SaveRegularMod(ModProject modProject)
|
||||
{
|
||||
if (modProject.IsCore) { throw new ArgumentException("ModProject must not be a core package"); }
|
||||
|
||||
//save the content package
|
||||
|
||||
string fileListPath = Path.Combine(directory, ToolBox.RemoveInvalidFileNameChars(modProject.Name), ContentPackage.FileListFileName)
|
||||
.CleanUpPathCrossPlatform(correctFilenameCase: false);
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(fileListPath)!);
|
||||
modProject.Save(fileListPath);
|
||||
Refresh(); EnabledPackages.DisableRemovedMods();
|
||||
var newPackage = Regular.First(p => p.Path == fileListPath);
|
||||
|
||||
//enable it
|
||||
EnabledPackages.EnableRegular(newPackage);
|
||||
return fileListPath;
|
||||
}
|
||||
|
||||
return newPackage;
|
||||
public RegularPackage GetRegularModByPath(string fileListPath)
|
||||
{
|
||||
return Regular.First(p => p.Path == fileListPath);
|
||||
}
|
||||
|
||||
public RegularPackage SaveAndEnableRegularMod(ModProject modProject)
|
||||
{
|
||||
string fileListPath = SaveRegularMod(modProject);
|
||||
var package = GetRegularModByPath(fileListPath);
|
||||
EnabledPackages.EnableRegular(package);
|
||||
|
||||
return package;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1454,9 +1454,9 @@ namespace Barotrauma
|
||||
// omega nesting incoming
|
||||
if (fabricationRecipe != null)
|
||||
{
|
||||
foreach (KeyValuePair<Identifier, PriceInfo> itemLocationPrice in itemPrefab.GetSellPricesOver(0))
|
||||
foreach (var priceInfo in itemPrefab.GetSellPricesOver(0))
|
||||
{
|
||||
NewMessage(" If bought at " + itemLocationPrice.Key + " it costs " + itemLocationPrice.Value.Price);
|
||||
NewMessage($" If bought at {GetSeller(priceInfo.Value)} it costs {priceInfo.Value.Price}");
|
||||
int totalPrice = 0;
|
||||
int? totalBestPrice = 0;
|
||||
foreach (var ingredient in fabricationRecipe.RequiredItems)
|
||||
@@ -1464,31 +1464,33 @@ namespace Barotrauma
|
||||
foreach (ItemPrefab ingredientItemPrefab in ingredient.ItemPrefabs)
|
||||
{
|
||||
int defaultPrice = ingredientItemPrefab.DefaultPrice?.Price ?? 0;
|
||||
NewMessage(" Its ingredient " + ingredientItemPrefab.Name + " has base cost " + defaultPrice);
|
||||
NewMessage($" Its ingredient {ingredientItemPrefab.Name} has base cost {defaultPrice}");
|
||||
totalPrice += defaultPrice;
|
||||
totalBestPrice += ingredientItemPrefab.GetMinPrice();
|
||||
int basePrice = defaultPrice;
|
||||
foreach (KeyValuePair<Identifier, PriceInfo> ingredientItemLocationPrice in ingredientItemPrefab.GetBuyPricesUnder())
|
||||
foreach (var ingredientItemPriceInfo in ingredientItemPrefab.GetBuyPricesUnder())
|
||||
{
|
||||
if (basePrice > ingredientItemLocationPrice.Value.Price)
|
||||
if (basePrice > ingredientItemPriceInfo.Value.Price)
|
||||
{
|
||||
NewMessage(" Location " + ingredientItemLocationPrice.Key + " sells ingredient " + ingredientItemPrefab.Name + " for cheaper, " + ingredientItemLocationPrice.Value.Price, Color.Yellow);
|
||||
NewMessage($" {GetSeller(ingredientItemPriceInfo.Value).CapitaliseFirstInvariant()} sells ingredient {ingredientItemPrefab.Name} for cheaper, {ingredientItemPriceInfo.Value.Price}", Color.Yellow);
|
||||
}
|
||||
else
|
||||
{
|
||||
NewMessage(" Location " + ingredientItemLocationPrice.Key + " sells ingredient " + ingredientItemPrefab.Name + " for more, " + ingredientItemLocationPrice.Value.Price, Color.Teal);
|
||||
NewMessage($" {GetSeller(ingredientItemPriceInfo.Value).CapitaliseFirstInvariant()} sells ingredient {ingredientItemPrefab.Name} for more, {ingredientItemPriceInfo.Value.Price}", Color.Teal);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
int costDifference = itemPrefab.DefaultPrice.Price - totalPrice;
|
||||
NewMessage(" Constructing the item from store-bought items provides " + costDifference + " profit with default values.");
|
||||
NewMessage($" Constructing the item from store-bought items provides {costDifference} profit with default values.");
|
||||
|
||||
if (totalBestPrice.HasValue)
|
||||
{
|
||||
int? bestDifference = itemLocationPrice.Value.Price - totalBestPrice;
|
||||
NewMessage(" Constructing the item from store-bought items provides " + bestDifference + " profit with best-case scenario values.");
|
||||
int? bestDifference = priceInfo.Value.Price - totalBestPrice;
|
||||
NewMessage($" Constructing the item from store-bought items provides {bestDifference} profit with best-case scenario values.");
|
||||
}
|
||||
|
||||
static string GetSeller(PriceInfo priceInfo) => $"store with identifier \"{priceInfo.StoreIdentifier}\"";
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -1763,7 +1765,7 @@ namespace Barotrauma
|
||||
//check missing mission texts
|
||||
foreach (var missionPrefab in MissionPrefab.Prefabs)
|
||||
{
|
||||
Identifier missionId = (missionPrefab.ConfigElement.Attribute("textidentifier") == null ? missionPrefab.Identifier : missionPrefab.ConfigElement.GetAttributeIdentifier("textidentifier", Identifier.Empty));
|
||||
Identifier missionId = (missionPrefab.ConfigElement.GetAttribute("textidentifier") == null ? missionPrefab.Identifier : missionPrefab.ConfigElement.GetAttributeIdentifier("textidentifier", Identifier.Empty));
|
||||
addIfMissing($"missionname.{missionId}".ToIdentifier(), language);
|
||||
addIfMissing($"missiondescription.{missionId}".ToIdentifier(), language);
|
||||
}
|
||||
|
||||
@@ -130,7 +130,7 @@ namespace Barotrauma
|
||||
UISprite newSprite = new UISprite(subElement);
|
||||
|
||||
GUIComponent.ComponentState spriteState = GUIComponent.ComponentState.None;
|
||||
if (subElement.Attribute("state") != null)
|
||||
if (subElement.GetAttribute("state") != null)
|
||||
{
|
||||
string stateStr = subElement.GetAttributeString("state", "None");
|
||||
Enum.TryParse(stateStr, out spriteState);
|
||||
|
||||
@@ -172,7 +172,7 @@ namespace Barotrauma
|
||||
{
|
||||
AutoScaleVertical = true,
|
||||
TextScale = 1.1f,
|
||||
TextGetter = () => FormatCurrency(campaign.Wallet.Balance)
|
||||
TextGetter = () => TextManager.FormatCurrency(campaign.Wallet.Balance)
|
||||
};
|
||||
|
||||
var pendingAndCrewGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.95f), anchor: Anchor.Center,
|
||||
@@ -400,7 +400,7 @@ namespace Barotrauma
|
||||
if (listBox != crewList)
|
||||
{
|
||||
new GUITextBlock(new RectTransform(new Vector2(width, 1.0f), mainGroup.RectTransform),
|
||||
FormatCurrency(characterInfo.Salary),
|
||||
TextManager.FormatCurrency(characterInfo.Salary),
|
||||
textAlignment: Alignment.Center)
|
||||
{
|
||||
CanBeFocused = false
|
||||
@@ -629,7 +629,7 @@ namespace Barotrauma
|
||||
{
|
||||
total += ((InfoSkill)c.UserData).CharacterInfo.Salary;
|
||||
});
|
||||
totalBlock.Text = FormatCurrency(total);
|
||||
totalBlock.Text = TextManager.FormatCurrency(total);
|
||||
bool enoughMoney = campaign == null || campaign.Wallet.CanAfford(total);
|
||||
totalBlock.TextColor = enoughMoney ? Color.White : Color.Red;
|
||||
validateHiresButton.Enabled = enoughMoney && pendingList.Content.RectTransform.Children.Any();
|
||||
@@ -925,7 +925,5 @@ namespace Barotrauma
|
||||
GameMain.Client.ClientPeer?.Send(msg, DeliveryMethod.Reliable);
|
||||
}
|
||||
}
|
||||
|
||||
private LocalizedString FormatCurrency(int currency) => TextManager.GetWithVariable("currencyformat", "[credits]", string.Format(CultureInfo.InvariantCulture, "{0:N0}", currency));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ namespace Barotrauma
|
||||
|
||||
public IEnumerable<T> GetAllChildren<T>() where T : GUIComponent
|
||||
{
|
||||
return GetAllChildren().Where(c => c is T).Select(c => c as T);
|
||||
return GetAllChildren().OfType<T>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -67,7 +67,7 @@ namespace Barotrauma
|
||||
{
|
||||
foreach (GUIComponent child in Children)
|
||||
{
|
||||
if (child.UserData == obj || (child.UserData != null && child.UserData.Equals(obj))) { return child; }
|
||||
if (Equals(child.UserData, obj)) { return child; }
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -108,7 +108,7 @@ namespace Barotrauma
|
||||
}
|
||||
public GUIComponent FindChild(object userData, bool recursive = false)
|
||||
{
|
||||
var matchingChild = Children.FirstOrDefault(c => c.UserData == userData);
|
||||
var matchingChild = Children.FirstOrDefault(c => Equals(c.UserData, userData));
|
||||
if (recursive && matchingChild == null)
|
||||
{
|
||||
foreach (GUIComponent child in Children)
|
||||
@@ -123,7 +123,7 @@ namespace Barotrauma
|
||||
|
||||
public IEnumerable<GUIComponent> FindChildren(object userData)
|
||||
{
|
||||
return Children.Where(c => c.UserData == userData);
|
||||
return Children.Where(c => Equals(c.UserData, userData));
|
||||
}
|
||||
|
||||
public IEnumerable<GUIComponent> FindChildren(Func<GUIComponent, bool> predicate)
|
||||
|
||||
@@ -16,8 +16,8 @@ namespace Barotrauma
|
||||
public LocalizedString Tooltip;
|
||||
|
||||
|
||||
public ContextMenuOption(string labelTag, bool isEnabled, Action onSelected)
|
||||
: this(TextManager.Get(labelTag), isEnabled, onSelected) { }
|
||||
public ContextMenuOption(string label, bool isEnabled, Action onSelected)
|
||||
: this(TextManager.Get(label).Fallback(label), isEnabled, onSelected) { }
|
||||
|
||||
public ContextMenuOption(Identifier labelTag, bool isEnabled, Action onSelected)
|
||||
: this(TextManager.Get(labelTag), isEnabled, onSelected) { }
|
||||
|
||||
@@ -314,13 +314,12 @@ namespace Barotrauma
|
||||
foreach (GUIComponent child in ListBox.Content.Children)
|
||||
{
|
||||
var tickBox = child.GetChild<GUITickBox>();
|
||||
if (obj == child.UserData) { tickBox.Selected = true; }
|
||||
if (Equals(obj, child.UserData)) { tickBox.Selected = true; }
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
GUITextBlock textBlock = component as GUITextBlock;
|
||||
if (textBlock == null)
|
||||
if (!(component is GUITextBlock textBlock))
|
||||
{
|
||||
textBlock = component.GetChild<GUITextBlock>();
|
||||
if (textBlock is null && !AllowNonText) { return false; }
|
||||
|
||||
@@ -96,15 +96,11 @@ namespace Barotrauma
|
||||
switch (child.ScaleBasis)
|
||||
{
|
||||
case ScaleBasis.BothHeight:
|
||||
child.MinSize = new Point(child.Rect.Height, child.MinSize.Y);
|
||||
break;
|
||||
case ScaleBasis.Smallest when Rect.Height <= Rect.Width:
|
||||
case ScaleBasis.Largest when Rect.Height > Rect.Width:
|
||||
child.MinSize = new Point((int)((child.Rect.Height * child.RelativeSize.X) / child.RelativeSize.Y), child.MinSize.Y);
|
||||
break;
|
||||
case ScaleBasis.BothWidth:
|
||||
child.MinSize = new Point(child.MinSize.X, child.Rect.Width);
|
||||
break;
|
||||
case ScaleBasis.Smallest when Rect.Width <= Rect.Height:
|
||||
case ScaleBasis.Largest when Rect.Width > Rect.Height:
|
||||
child.MinSize = new Point(child.MinSize.X, (int)((child.Rect.Width * child.RelativeSize.Y) / child.RelativeSize.X));
|
||||
|
||||
@@ -402,8 +402,7 @@ namespace Barotrauma
|
||||
int i = 0;
|
||||
foreach (GUIComponent child in children)
|
||||
{
|
||||
if ((child.UserData != null && child.UserData.Equals(userData)) ||
|
||||
(child.UserData == null && userData == null))
|
||||
if (Equals(child.UserData, userData))
|
||||
{
|
||||
Select(i, force, autoScroll);
|
||||
if (!SelectMultiple) { return; }
|
||||
@@ -1219,6 +1218,20 @@ namespace Barotrauma
|
||||
i++;
|
||||
}
|
||||
|
||||
if (isDraggingElement && CurrentDragMode == DragMode.DragOutsideBox && HideDraggedElement)
|
||||
{
|
||||
Rectangle drawRect = DraggedElement.Rect;
|
||||
int draggedElementIndex = Content.GetChildIndex(DraggedElement);
|
||||
CalculateChildrenOffsets((index, point) =>
|
||||
{
|
||||
if (draggedElementIndex == index)
|
||||
{
|
||||
drawRect.Location = Content.Rect.Location + point;
|
||||
}
|
||||
});
|
||||
GUI.DrawRectangle(spriteBatch, drawRect, Color.White * 0.5f, thickness: 2f);
|
||||
}
|
||||
|
||||
if (HideChildrenOutsideFrame)
|
||||
{
|
||||
spriteBatch.End();
|
||||
|
||||
@@ -65,7 +65,7 @@ namespace Barotrauma
|
||||
LoadFont();
|
||||
}
|
||||
|
||||
private void LoadFont()
|
||||
public void LoadFont()
|
||||
{
|
||||
string fontPath = GetFontFilePath(element);
|
||||
uint size = GetFontSize(element);
|
||||
|
||||
@@ -268,7 +268,7 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
int totalCost = medicalClinic.GetTotalCost();
|
||||
healList.PriceBlock.Text = UpgradeStore.FormatCurrency(totalCost);
|
||||
healList.PriceBlock.Text = TextManager.FormatCurrency(totalCost);
|
||||
healList.PriceBlock.TextColor = GUIStyle.Red;
|
||||
healList.HealButton.Enabled = false;
|
||||
if (medicalClinic.GetWallet().CanAfford(totalCost))
|
||||
@@ -288,7 +288,7 @@ namespace Barotrauma
|
||||
{
|
||||
if (element.FindAfflictionElement(affliction) is { } existingAffliction)
|
||||
{
|
||||
existingAffliction.Price.Text = UpgradeStore.FormatCurrency(affliction.Strength);
|
||||
existingAffliction.Price.Text = TextManager.FormatCurrency(affliction.Strength);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -467,7 +467,7 @@ namespace Barotrauma
|
||||
|
||||
GUITextBlock moneyLabel = new GUITextBlock(new RectTransform(new Vector2(1f, 0.5f), balanceLayout.RectTransform), string.Empty, textAlignment: Alignment.TopRight, font: GUIStyle.SubHeadingFont)
|
||||
{
|
||||
TextGetter = () => UpgradeStore.FormatCurrency(medicalClinic.GetWallet().Balance),
|
||||
TextGetter = () => TextManager.FormatCurrency(medicalClinic.GetWallet().Balance),
|
||||
AutoScaleVertical = true,
|
||||
TextScale = 1.1f
|
||||
};
|
||||
@@ -571,7 +571,7 @@ namespace Barotrauma
|
||||
|
||||
GUILayoutGroup priceLayout = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.5f), footerLayout.RectTransform), isHorizontal: true);
|
||||
GUITextBlock priceLabelBlock = new GUITextBlock(new RectTransform(new Vector2(0.5f, 1f), priceLayout.RectTransform), TextManager.Get("campaignstore.total"));
|
||||
GUITextBlock priceBlock = new GUITextBlock(new RectTransform(new Vector2(0.5f, 1f), priceLayout.RectTransform), UpgradeStore.FormatCurrency(medicalClinic.GetTotalCost()), font: GUIStyle.SubHeadingFont,
|
||||
GUITextBlock priceBlock = new GUITextBlock(new RectTransform(new Vector2(0.5f, 1f), priceLayout.RectTransform), TextManager.FormatCurrency(medicalClinic.GetTotalCost()), font: GUIStyle.SubHeadingFont,
|
||||
textAlignment: Alignment.Right);
|
||||
|
||||
GUILayoutGroup buttonLayout = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.5f), footerLayout.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterRight);
|
||||
@@ -684,7 +684,7 @@ namespace Barotrauma
|
||||
GUIFrame textContainer = new GUIFrame(new RectTransform(new Vector2(0.6f, 1f), textLayout.RectTransform), style: null);
|
||||
GUITextBlock afflictionName = new GUITextBlock(new RectTransform(Vector2.One, textContainer.RectTransform), name, font: GUIStyle.SubHeadingFont);
|
||||
|
||||
GUITextBlock healCost = new GUITextBlock(new RectTransform(new Vector2(0.2f, 1f), textLayout.RectTransform), UpgradeStore.FormatCurrency(affliction.Price), textAlignment: Alignment.Center, font: GUIStyle.LargeFont)
|
||||
GUITextBlock healCost = new GUITextBlock(new RectTransform(new Vector2(0.2f, 1f), textLayout.RectTransform), TextManager.FormatCurrency(affliction.Price), textAlignment: Alignment.Center, font: GUIStyle.LargeFont)
|
||||
{
|
||||
Padding = Vector4.Zero
|
||||
};
|
||||
@@ -876,7 +876,7 @@ namespace Barotrauma
|
||||
ToolTip = prefab.Description
|
||||
};
|
||||
|
||||
GUITextBlock priceBlock = new GUITextBlock(new RectTransform(new Vector2(1f, 0.5f), bottomTextLayout.RectTransform), UpgradeStore.FormatCurrency(affliction.Price), font: GUIStyle.LargeFont);
|
||||
GUITextBlock priceBlock = new GUITextBlock(new RectTransform(new Vector2(1f, 0.5f), bottomTextLayout.RectTransform), TextManager.FormatCurrency(affliction.Price), font: GUIStyle.LargeFont);
|
||||
|
||||
GUIButton buyButton = new GUIButton(new RectTransform(new Vector2(0.2f, 0.75f), bottomLayout.RectTransform), style: "CrewManagementAddButton");
|
||||
|
||||
@@ -931,7 +931,7 @@ namespace Barotrauma
|
||||
});
|
||||
}
|
||||
|
||||
private static void EnsureTextDoesntOverflow(string? text, GUITextBlock textBlock, Rectangle bounds, ImmutableArray<GUILayoutGroup>? layoutGroups = null)
|
||||
public static void EnsureTextDoesntOverflow(string? text, GUITextBlock textBlock, Rectangle bounds, ImmutableArray<GUILayoutGroup>? layoutGroups = null)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(text)) { return; }
|
||||
|
||||
|
||||
@@ -44,6 +44,7 @@ namespace Barotrauma
|
||||
private bool suppressBuySell;
|
||||
private int buyTotal, sellTotal, sellFromSubTotal;
|
||||
|
||||
private GUITextBlock storeNameBlock;
|
||||
private GUITextBlock merchantBalanceBlock;
|
||||
private GUITextBlock currentSellValueBlock, newSellValueBlock;
|
||||
private GUIImage sellValueChangeArrow;
|
||||
@@ -65,6 +66,7 @@ namespace Barotrauma
|
||||
private Point resolutionWhenCreated;
|
||||
|
||||
private Dictionary<ItemPrefab, ItemQuantity> OwnedItems { get; } = new Dictionary<ItemPrefab, ItemQuantity>();
|
||||
private Location.StoreInfo ActiveStore { get; set; }
|
||||
|
||||
private CargoManager CargoManager => campaignUI.Campaign.CargoManager;
|
||||
private Location CurrentLocation => campaignUI.Campaign.Map?.CurrentLocation;
|
||||
@@ -238,6 +240,39 @@ namespace Barotrauma
|
||||
campaignUI.Campaign.CargoManager.OnItemsInSellFromSubCrateChanged += () => { needsSellingFromSubRefresh = true; };
|
||||
}
|
||||
|
||||
public void SelectStore(Identifier identifier)
|
||||
{
|
||||
if (CurrentLocation?.Stores != null)
|
||||
{
|
||||
if (CurrentLocation.GetStore(identifier) is { } store)
|
||||
{
|
||||
ActiveStore = store;
|
||||
if (storeNameBlock != null)
|
||||
{
|
||||
var storeName = TextManager.Get($"storename.{store.Identifier}");
|
||||
if (storeName.IsNullOrEmpty())
|
||||
{
|
||||
storeName = TextManager.Get("store");
|
||||
}
|
||||
storeNameBlock.SetRichText(storeName);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ActiveStore = null;
|
||||
string msg = $"Error selecting store with identifier \"{identifier}\" at {CurrentLocation}: store with the identifier doesn't exist at the location.";
|
||||
DebugConsole.ShowError(msg);
|
||||
GameAnalyticsManager.AddErrorEventOnce("Store.SelectStore:StoreDoesntExist", GameAnalyticsManager.ErrorSeverity.Error, msg);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ActiveStore = null;
|
||||
}
|
||||
RefreshItemsToSell();
|
||||
Refresh();
|
||||
}
|
||||
|
||||
public void Refresh(bool updateOwned = true)
|
||||
{
|
||||
UpdatePermissions();
|
||||
@@ -321,7 +356,7 @@ namespace Barotrauma
|
||||
};
|
||||
var imageWidth = (float)headerGroup.Rect.Height / headerGroup.Rect.Width;
|
||||
new GUIImage(new RectTransform(new Vector2(imageWidth, 1.0f), headerGroup.RectTransform), "StoreTradingIcon");
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f - imageWidth, 1.0f), headerGroup.RectTransform), TextManager.Get("store"), font: GUIStyle.LargeFont)
|
||||
storeNameBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f - imageWidth, 1.0f), headerGroup.RectTransform), TextManager.Get("store"), font: GUIStyle.LargeFont)
|
||||
{
|
||||
CanBeFocused = false,
|
||||
ForceUpperCase = ForceUpperCase.Yes
|
||||
@@ -350,7 +385,7 @@ namespace Barotrauma
|
||||
TextScale = 1.1f,
|
||||
TextGetter = () =>
|
||||
{
|
||||
merchantBalanceBlock.TextColor = CurrentLocation?.BalanceColor ?? Color.Red;
|
||||
merchantBalanceBlock.TextColor = ActiveStore?.BalanceColor ?? Color.Red;
|
||||
return GetMerchantBalanceText();
|
||||
}
|
||||
};
|
||||
@@ -388,17 +423,17 @@ namespace Barotrauma
|
||||
{
|
||||
int balanceAfterTransaction = activeTab switch
|
||||
{
|
||||
StoreTab.Buy => CurrentLocation.StoreCurrentBalance + buyTotal,
|
||||
StoreTab.Sell => CurrentLocation.StoreCurrentBalance - sellTotal,
|
||||
StoreTab.SellSub => CurrentLocation.StoreCurrentBalance - sellFromSubTotal,
|
||||
StoreTab.Buy => ActiveStore.Balance + buyTotal,
|
||||
StoreTab.Sell => ActiveStore.Balance - sellTotal,
|
||||
StoreTab.SellSub => ActiveStore.Balance - sellFromSubTotal,
|
||||
_ => throw new NotImplementedException(),
|
||||
};
|
||||
if (balanceAfterTransaction != CurrentLocation.StoreCurrentBalance)
|
||||
if (balanceAfterTransaction != ActiveStore.Balance)
|
||||
{
|
||||
var newStatus = CurrentLocation.GetStoreBalanceStatus(balanceAfterTransaction);
|
||||
if (CurrentLocation.ActiveStoreBalanceStatus.SellPriceModifier != newStatus.SellPriceModifier)
|
||||
if (ActiveStore.ActiveBalanceStatus.SellPriceModifier != newStatus.SellPriceModifier)
|
||||
{
|
||||
string tooltipTag = newStatus.SellPriceModifier > CurrentLocation.ActiveStoreBalanceStatus.SellPriceModifier ?
|
||||
string tooltipTag = newStatus.SellPriceModifier > ActiveStore.ActiveBalanceStatus.SellPriceModifier ?
|
||||
"campaingstore.valueincreasetooltip" : "campaingstore.valuedecreasetooltip";
|
||||
sellValueContainer.ToolTip = TextManager.Get(tooltipTag);
|
||||
currentSellValueBlock.TextColor = newStatus.Color;
|
||||
@@ -406,14 +441,14 @@ namespace Barotrauma
|
||||
sellValueChangeArrow.Visible = true;
|
||||
newSellValueBlock.TextColor = newStatus.Color;
|
||||
newSellValueBlock.Text = $"{(newStatus.SellPriceModifier * 100).FormatZeroDecimal()} %";
|
||||
return $"{(CurrentLocation.ActiveStoreBalanceStatus.SellPriceModifier * 100).FormatZeroDecimal()} %";
|
||||
return $"{(ActiveStore.ActiveBalanceStatus.SellPriceModifier * 100).FormatZeroDecimal()} %";
|
||||
}
|
||||
}
|
||||
sellValueContainer.ToolTip = TextManager.Get("campaignstore.sellvaluetooltip");
|
||||
currentSellValueBlock.TextColor = CurrentLocation.BalanceColor;
|
||||
currentSellValueBlock.TextColor = ActiveStore.BalanceColor;
|
||||
sellValueChangeArrow.Visible = false;
|
||||
newSellValueBlock.Text = null;
|
||||
return $"{(CurrentLocation.ActiveStoreBalanceStatus.SellPriceModifier * 100).FormatZeroDecimal()} %";
|
||||
return $"{(ActiveStore.ActiveBalanceStatus.SellPriceModifier * 100).FormatZeroDecimal()} %";
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -698,9 +733,9 @@ namespace Barotrauma
|
||||
if (!HasActiveTabPermissions()) { return false; }
|
||||
var itemsToRemove = activeTab switch
|
||||
{
|
||||
StoreTab.Buy => new List<PurchasedItem>(CargoManager.ItemsInBuyCrate),
|
||||
StoreTab.Sell => new List<PurchasedItem>(CargoManager.ItemsInSellCrate),
|
||||
StoreTab.SellSub => new List<PurchasedItem>(CargoManager.ItemsInSellFromSubCrate),
|
||||
StoreTab.Buy => new List<PurchasedItem>(CargoManager.GetBuyCrateItems(ActiveStore)),
|
||||
StoreTab.Sell => new List<PurchasedItem>(CargoManager.GetSellCrateItems(ActiveStore)),
|
||||
StoreTab.SellSub => new List<PurchasedItem>(CargoManager.GetSubCrateItems(ActiveStore)),
|
||||
_ => throw new NotImplementedException(),
|
||||
};
|
||||
itemsToRemove.ForEach(i => ClearFromShoppingCrate(i));
|
||||
@@ -708,14 +743,13 @@ namespace Barotrauma
|
||||
}
|
||||
};
|
||||
|
||||
Refresh();
|
||||
ChangeStoreTab(activeTab);
|
||||
resolutionWhenCreated = new Point(GameMain.GraphicsWidth, GameMain.GraphicsHeight);
|
||||
}
|
||||
|
||||
private LocalizedString GetMerchantBalanceText() => GetCurrencyFormatted(CurrentLocation?.StoreCurrentBalance ?? 0);
|
||||
private LocalizedString GetMerchantBalanceText() => TextManager.FormatCurrency(ActiveStore?.Balance ?? 0);
|
||||
|
||||
private LocalizedString GetPlayerBalanceText() => GetCurrencyFormatted(PlayerWallet.Balance);
|
||||
private LocalizedString GetPlayerBalanceText() => TextManager.FormatCurrency(PlayerWallet.Balance);
|
||||
|
||||
private GUILayoutGroup CreateDealsGroup(GUIListBox parentList, int elementCount = 4)
|
||||
{
|
||||
@@ -746,21 +780,25 @@ namespace Barotrauma
|
||||
private void UpdateLocation(Location prevLocation, Location newLocation)
|
||||
{
|
||||
if (prevLocation == newLocation) { return; }
|
||||
|
||||
if (prevLocation?.Reputation != null)
|
||||
{
|
||||
prevLocation.Reputation.OnReputationValueChanged = null;
|
||||
prevLocation.Reputation.OnReputationValueChanged -= SetNeedsRefresh;
|
||||
}
|
||||
if (ItemPrefab.Prefabs.Any(p => p.CanBeBoughtAtLocation(CurrentLocation, out PriceInfo _)))
|
||||
if (ItemPrefab.Prefabs.Any(p => p.CanBeBoughtFrom(newLocation)))
|
||||
{
|
||||
selectedItemCategory = null;
|
||||
searchBox.Text = "";
|
||||
ChangeStoreTab(StoreTab.Buy);
|
||||
if (newLocation?.Reputation != null)
|
||||
{
|
||||
newLocation.Reputation.OnReputationValueChanged += () => { needsRefresh = true; };
|
||||
newLocation.Reputation.OnReputationValueChanged += SetNeedsRefresh;
|
||||
}
|
||||
}
|
||||
|
||||
void SetNeedsRefresh()
|
||||
{
|
||||
needsRefresh = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void ChangeStoreTab(StoreTab tab)
|
||||
@@ -862,9 +900,9 @@ namespace Barotrauma
|
||||
bool hasPermissions = HasBuyPermissions;
|
||||
HashSet<GUIComponent> existingItemFrames = new HashSet<GUIComponent>();
|
||||
|
||||
int dailySpecialCount = CurrentLocation?.DailySpecials.Count() ?? 3;
|
||||
int dailySpecialCount = ActiveStore.DailySpecials.Count;
|
||||
|
||||
if ((storeDailySpecialsGroup != null) != CurrentLocation.DailySpecials.Any() || dailySpecialCount != prevDailySpecialCount)
|
||||
if ((storeDailySpecialsGroup != null) != ActiveStore.DailySpecials.Any() || dailySpecialCount != prevDailySpecialCount)
|
||||
{
|
||||
if (storeDailySpecialsGroup == null || dailySpecialCount != prevDailySpecialCount)
|
||||
{
|
||||
@@ -881,32 +919,32 @@ namespace Barotrauma
|
||||
prevDailySpecialCount = dailySpecialCount;
|
||||
}
|
||||
|
||||
foreach (PurchasedItem item in CurrentLocation.StoreStock)
|
||||
foreach (PurchasedItem item in ActiveStore.Stock)
|
||||
{
|
||||
CreateOrUpdateItemFrame(item.ItemPrefab, item.Quantity);
|
||||
}
|
||||
|
||||
foreach (ItemPrefab itemPrefab in CurrentLocation.DailySpecials)
|
||||
foreach (ItemPrefab itemPrefab in ActiveStore.DailySpecials)
|
||||
{
|
||||
if (CurrentLocation.StoreStock.Any(pi => pi.ItemPrefab == itemPrefab)) { continue; }
|
||||
if (ActiveStore.Stock.Any(pi => pi.ItemPrefab == itemPrefab)) { continue; }
|
||||
CreateOrUpdateItemFrame(itemPrefab, 0);
|
||||
}
|
||||
|
||||
void CreateOrUpdateItemFrame(ItemPrefab itemPrefab, int quantity)
|
||||
{
|
||||
if (itemPrefab.CanBeBoughtAtLocation(CurrentLocation, out PriceInfo priceInfo))
|
||||
if (itemPrefab.CanBeBoughtFrom(ActiveStore, out PriceInfo priceInfo))
|
||||
{
|
||||
var isDailySpecial = CurrentLocation.DailySpecials.Contains(itemPrefab);
|
||||
bool isDailySpecial = ActiveStore.DailySpecials.Contains(itemPrefab);
|
||||
var itemFrame = isDailySpecial ?
|
||||
storeDailySpecialsGroup.FindChild(c => c.UserData is PurchasedItem pi && pi.ItemPrefab == itemPrefab) :
|
||||
storeBuyList.Content.FindChild(c => c.UserData is PurchasedItem pi && pi.ItemPrefab == itemPrefab);
|
||||
if (CargoManager.PurchasedItems.Find(i => i.ItemPrefab == itemPrefab) is PurchasedItem purchasedItem)
|
||||
if (CargoManager.GetPurchasedItem(ActiveStore, itemPrefab) is { } purchasedItem)
|
||||
{
|
||||
quantity = Math.Max(quantity - purchasedItem.Quantity, 0);
|
||||
}
|
||||
if (CargoManager.ItemsInBuyCrate.Find(i => i.ItemPrefab == itemPrefab) is PurchasedItem itemInBuyCrate)
|
||||
if (CargoManager.GetBuyCrateItem(ActiveStore, itemPrefab) is { } buyCrateItem)
|
||||
{
|
||||
quantity = Math.Max(quantity - itemInBuyCrate.Quantity, 0);
|
||||
quantity = Math.Max(quantity - buyCrateItem.Quantity, 0);
|
||||
}
|
||||
if (itemFrame == null)
|
||||
{
|
||||
@@ -945,7 +983,7 @@ namespace Barotrauma
|
||||
bool hasPermissions = HasTabPermissions(StoreTab.Sell);
|
||||
HashSet<GUIComponent> existingItemFrames = new HashSet<GUIComponent>();
|
||||
|
||||
if ((storeRequestedGoodGroup != null) != CurrentLocation.RequestedGoods.Any())
|
||||
if ((storeRequestedGoodGroup != null) != ActiveStore.RequestedGoods.Any())
|
||||
{
|
||||
if (storeRequestedGoodGroup == null)
|
||||
{
|
||||
@@ -965,7 +1003,7 @@ namespace Barotrauma
|
||||
CreateOrUpdateItemFrame(item.ItemPrefab, item.Quantity);
|
||||
}
|
||||
|
||||
foreach (var requestedGood in CurrentLocation.RequestedGoods)
|
||||
foreach (var requestedGood in ActiveStore.RequestedGoods)
|
||||
{
|
||||
if (itemsToSell.Any(pi => pi.ItemPrefab == requestedGood)) { continue; }
|
||||
CreateOrUpdateItemFrame(requestedGood, 0);
|
||||
@@ -973,15 +1011,15 @@ namespace Barotrauma
|
||||
|
||||
void CreateOrUpdateItemFrame(ItemPrefab itemPrefab, int itemQuantity)
|
||||
{
|
||||
PriceInfo priceInfo = itemPrefab.GetPriceInfo(CurrentLocation);
|
||||
PriceInfo priceInfo = itemPrefab.GetPriceInfo(ActiveStore);
|
||||
if (priceInfo == null) { return; }
|
||||
var isRequestedGood = CurrentLocation.RequestedGoods.Contains(itemPrefab);
|
||||
var isRequestedGood = ActiveStore.RequestedGoods.Contains(itemPrefab);
|
||||
var itemFrame = isRequestedGood ?
|
||||
storeRequestedGoodGroup.FindChild(c => c.UserData is PurchasedItem pi && pi.ItemPrefab == itemPrefab) :
|
||||
storeSellList.Content.FindChild(c => c.UserData is PurchasedItem pi && pi.ItemPrefab == itemPrefab);
|
||||
if (CargoManager.ItemsInSellCrate.Find(i => i.ItemPrefab == itemPrefab) is PurchasedItem itemInSellCrate)
|
||||
if (CargoManager.GetSellCrateItem(ActiveStore, itemPrefab) is { } sellCrateItem)
|
||||
{
|
||||
itemQuantity = Math.Max(itemQuantity - itemInSellCrate.Quantity, 0);
|
||||
itemQuantity = Math.Max(itemQuantity - sellCrateItem.Quantity, 0);
|
||||
}
|
||||
if (itemFrame == null)
|
||||
{
|
||||
@@ -1023,7 +1061,7 @@ namespace Barotrauma
|
||||
bool hasPermissions = HasSellSubPermissions;
|
||||
HashSet<GUIComponent> existingItemFrames = new HashSet<GUIComponent>();
|
||||
|
||||
if ((storeRequestedSubGoodGroup != null) != CurrentLocation.RequestedGoods.Any())
|
||||
if ((storeRequestedSubGoodGroup != null) != ActiveStore.RequestedGoods.Any())
|
||||
{
|
||||
if (storeRequestedSubGoodGroup == null)
|
||||
{
|
||||
@@ -1043,7 +1081,7 @@ namespace Barotrauma
|
||||
CreateOrUpdateItemFrame(item.ItemPrefab, item.Quantity);
|
||||
}
|
||||
|
||||
foreach (var requestedGood in CurrentLocation.RequestedGoods)
|
||||
foreach (var requestedGood in ActiveStore.RequestedGoods)
|
||||
{
|
||||
if (itemsToSellFromSub.Any(pi => pi.ItemPrefab == requestedGood)) { continue; }
|
||||
CreateOrUpdateItemFrame(requestedGood, 0);
|
||||
@@ -1051,15 +1089,15 @@ namespace Barotrauma
|
||||
|
||||
void CreateOrUpdateItemFrame(ItemPrefab itemPrefab, int itemQuantity)
|
||||
{
|
||||
PriceInfo priceInfo = itemPrefab.GetPriceInfo(CurrentLocation);
|
||||
PriceInfo priceInfo = itemPrefab.GetPriceInfo(ActiveStore);
|
||||
if (priceInfo == null) { return; }
|
||||
var isRequestedGood = CurrentLocation.RequestedGoods.Contains(itemPrefab);
|
||||
bool isRequestedGood = ActiveStore.RequestedGoods.Contains(itemPrefab);
|
||||
var itemFrame = isRequestedGood ?
|
||||
storeRequestedSubGoodGroup.FindChild(c => c.UserData is PurchasedItem pi && pi.ItemPrefab == itemPrefab) :
|
||||
storeSellFromSubList.Content.FindChild(c => c.UserData is PurchasedItem pi && pi.ItemPrefab == itemPrefab);
|
||||
if (CargoManager.ItemsInSellFromSubCrate.Find(i => i.ItemPrefab == itemPrefab) is PurchasedItem itemInSellFromSubCrate)
|
||||
if (CargoManager.GetSubCrateItem(ActiveStore, itemPrefab) is { } subCrateItem)
|
||||
{
|
||||
itemQuantity = Math.Max(itemQuantity - itemInSellFromSubCrate.Quantity, 0);
|
||||
itemQuantity = Math.Max(itemQuantity - subCrateItem.Quantity, 0);
|
||||
}
|
||||
if (itemFrame == null)
|
||||
{
|
||||
@@ -1102,13 +1140,13 @@ namespace Barotrauma
|
||||
{
|
||||
if (buying)
|
||||
{
|
||||
undiscountedPriceBlock.TextGetter = () => GetCurrencyFormatted(
|
||||
CurrentLocation?.GetAdjustedItemBuyPrice(pi.ItemPrefab, considerDailySpecials: false) ?? 0);
|
||||
undiscountedPriceBlock.TextGetter = () => TextManager.FormatCurrency(
|
||||
ActiveStore?.GetAdjustedItemBuyPrice(pi.ItemPrefab, considerDailySpecials: false) ?? 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
undiscountedPriceBlock.TextGetter = () => GetCurrencyFormatted(
|
||||
CurrentLocation?.GetAdjustedItemSellPrice(pi.ItemPrefab, considerRequestedGoods: false) ?? 0);
|
||||
undiscountedPriceBlock.TextGetter = () => TextManager.FormatCurrency(
|
||||
ActiveStore?.GetAdjustedItemSellPrice(pi.ItemPrefab, considerRequestedGoods: false) ?? 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1116,11 +1154,11 @@ namespace Barotrauma
|
||||
{
|
||||
if (buying)
|
||||
{
|
||||
priceBlock.TextGetter = () => GetCurrencyFormatted(CurrentLocation?.GetAdjustedItemBuyPrice(pi.ItemPrefab) ?? 0);
|
||||
priceBlock.TextGetter = () => TextManager.FormatCurrency(ActiveStore?.GetAdjustedItemBuyPrice(pi.ItemPrefab) ?? 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
priceBlock.TextGetter = () => GetCurrencyFormatted(CurrentLocation?.GetAdjustedItemSellPrice(pi.ItemPrefab) ?? 0);
|
||||
priceBlock.TextGetter = () => TextManager.FormatCurrency(ActiveStore?.GetAdjustedItemSellPrice(pi.ItemPrefab) ?? 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1135,21 +1173,21 @@ namespace Barotrauma
|
||||
{
|
||||
item.Quantity += 1;
|
||||
}
|
||||
else if (playerItem.Prefab.GetPriceInfo(CurrentLocation) != null)
|
||||
else if (playerItem.Prefab.GetPriceInfo(ActiveStore) != null)
|
||||
{
|
||||
itemsToSell.Add(new PurchasedItem(playerItem.Prefab, 1));
|
||||
}
|
||||
}
|
||||
|
||||
// Remove items from sell crate if they aren't in player inventory anymore
|
||||
var itemsInCrate = new List<PurchasedItem>(CargoManager.ItemsInSellCrate);
|
||||
var itemsInCrate = new List<PurchasedItem>(CargoManager.GetSellCrateItems(ActiveStore));
|
||||
foreach (PurchasedItem crateItem in itemsInCrate)
|
||||
{
|
||||
var playerItem = itemsToSell.Find(i => i.ItemPrefab == crateItem.ItemPrefab);
|
||||
var playerItemQuantity = playerItem != null ? playerItem.Quantity : 0;
|
||||
if (crateItem.Quantity > playerItemQuantity)
|
||||
{
|
||||
CargoManager.ModifyItemQuantityInSellCrate(crateItem.ItemPrefab, playerItemQuantity - crateItem.Quantity);
|
||||
CargoManager.ModifyItemQuantityInSellCrate(ActiveStore.Identifier, crateItem.ItemPrefab, playerItemQuantity - crateItem.Quantity);
|
||||
}
|
||||
}
|
||||
needsItemsToSellRefresh = false;
|
||||
@@ -1165,35 +1203,35 @@ namespace Barotrauma
|
||||
{
|
||||
item.Quantity += 1;
|
||||
}
|
||||
else if (subItem.Prefab.GetPriceInfo(CurrentLocation) != null)
|
||||
else if (subItem.Prefab.GetPriceInfo(ActiveStore) != null)
|
||||
{
|
||||
itemsToSellFromSub.Add(new PurchasedItem(subItem.Prefab, 1));
|
||||
}
|
||||
}
|
||||
|
||||
// Remove items from sell crate if they aren't on the sub anymore
|
||||
var itemsInCrate = new List<PurchasedItem>(CargoManager.ItemsInSellFromSubCrate);
|
||||
var itemsInCrate = new List<PurchasedItem>(CargoManager.GetSubCrateItems(ActiveStore));
|
||||
foreach (PurchasedItem crateItem in itemsInCrate)
|
||||
{
|
||||
var subItem = itemsToSellFromSub.Find(i => i.ItemPrefab == crateItem.ItemPrefab);
|
||||
var subItemQuantity = subItem != null ? subItem.Quantity : 0;
|
||||
if (crateItem.Quantity > subItemQuantity)
|
||||
{
|
||||
CargoManager.ModifyItemQuantityInSellFromSubCrate(crateItem.ItemPrefab, subItemQuantity - crateItem.Quantity);
|
||||
CargoManager.ModifyItemQuantityInSubSellCrate(ActiveStore.Identifier, crateItem.ItemPrefab, subItemQuantity - crateItem.Quantity);
|
||||
}
|
||||
}
|
||||
sellableItemsFromSubUpdateTimer = 0.0f;
|
||||
needsItemsToSellFromSubRefresh = false;
|
||||
}
|
||||
|
||||
private void RefreshShoppingCrateList(List<PurchasedItem> items, GUIListBox listBox, StoreTab tab)
|
||||
private void RefreshShoppingCrateList(IEnumerable<PurchasedItem> items, GUIListBox listBox, StoreTab tab)
|
||||
{
|
||||
bool hasPermissions = HasTabPermissions(tab);
|
||||
HashSet<GUIComponent> existingItemFrames = new HashSet<GUIComponent>();
|
||||
int totalPrice = 0;
|
||||
foreach (PurchasedItem item in items)
|
||||
{
|
||||
if (!(item.ItemPrefab.GetPriceInfo(CurrentLocation) is { } priceInfo)) { continue; }
|
||||
if (!(item.ItemPrefab.GetPriceInfo(ActiveStore) is { } priceInfo)) { continue; }
|
||||
GUINumberInput numInput = null;
|
||||
if (!(listBox.Content.FindChild(c => c.UserData is PurchasedItem pi && pi.ItemPrefab.Identifier == item.ItemPrefab.Identifier) is { } itemFrame))
|
||||
{
|
||||
@@ -1227,9 +1265,9 @@ namespace Barotrauma
|
||||
{
|
||||
int price = tab switch
|
||||
{
|
||||
StoreTab.Buy => CurrentLocation.GetAdjustedItemBuyPrice(item.ItemPrefab, priceInfo: priceInfo),
|
||||
StoreTab.Sell => CurrentLocation.GetAdjustedItemSellPrice(item.ItemPrefab, priceInfo: priceInfo),
|
||||
StoreTab.SellSub => CurrentLocation.GetAdjustedItemSellPrice(item.ItemPrefab, priceInfo: priceInfo),
|
||||
StoreTab.Buy => ActiveStore.GetAdjustedItemBuyPrice(item.ItemPrefab, priceInfo: priceInfo),
|
||||
StoreTab.Sell => ActiveStore.GetAdjustedItemSellPrice(item.ItemPrefab, priceInfo: priceInfo),
|
||||
StoreTab.SellSub => ActiveStore.GetAdjustedItemSellPrice(item.ItemPrefab, priceInfo: priceInfo),
|
||||
_ => throw new NotImplementedException()
|
||||
};
|
||||
totalPrice += item.Quantity * price;
|
||||
@@ -1265,11 +1303,11 @@ namespace Barotrauma
|
||||
SetConfirmButtonStatus();
|
||||
}
|
||||
|
||||
private void RefreshShoppingCrateBuyList() => RefreshShoppingCrateList(CargoManager.ItemsInBuyCrate, shoppingCrateBuyList, StoreTab.Buy);
|
||||
private void RefreshShoppingCrateBuyList() => RefreshShoppingCrateList(CargoManager.GetBuyCrateItems(ActiveStore), shoppingCrateBuyList, StoreTab.Buy);
|
||||
|
||||
private void RefreshShoppingCrateSellList() => RefreshShoppingCrateList(CargoManager.ItemsInSellCrate, shoppingCrateSellList, StoreTab.Sell);
|
||||
private void RefreshShoppingCrateSellList() => RefreshShoppingCrateList(CargoManager.GetSellCrateItems(ActiveStore), shoppingCrateSellList, StoreTab.Sell);
|
||||
|
||||
private void RefreshShoppingCrateSellFromSubList() => RefreshShoppingCrateList(CargoManager.ItemsInSellFromSubCrate, shoppingCrateSellFromSubList, StoreTab.SellSub);
|
||||
private void RefreshShoppingCrateSellFromSubList() => RefreshShoppingCrateList(CargoManager.GetSubCrateItems(ActiveStore), shoppingCrateSellFromSubList, StoreTab.SellSub);
|
||||
|
||||
private void SortItems(GUIListBox list, SortingMethod sortingMethod)
|
||||
{
|
||||
@@ -1316,8 +1354,8 @@ namespace Barotrauma
|
||||
{
|
||||
if (x.GUIComponent.UserData is PurchasedItem itemX && y.GUIComponent.UserData is PurchasedItem itemY)
|
||||
{
|
||||
var sortResult = CurrentLocation.GetAdjustedItemSellPrice(itemX.ItemPrefab).CompareTo(
|
||||
CurrentLocation.GetAdjustedItemSellPrice(itemY.ItemPrefab));
|
||||
int sortResult = ActiveStore.GetAdjustedItemSellPrice(itemX.ItemPrefab).CompareTo(
|
||||
ActiveStore.GetAdjustedItemSellPrice(itemY.ItemPrefab));
|
||||
if (sortingMethod == SortingMethod.PriceDesc) { sortResult *= -1; }
|
||||
return sortResult;
|
||||
}
|
||||
@@ -1340,8 +1378,8 @@ namespace Barotrauma
|
||||
{
|
||||
if (x.GUIComponent.UserData is PurchasedItem itemX && y.GUIComponent.UserData is PurchasedItem itemY)
|
||||
{
|
||||
var sortResult = CurrentLocation.GetAdjustedItemBuyPrice(itemX.ItemPrefab).CompareTo(
|
||||
CurrentLocation.GetAdjustedItemBuyPrice(itemY.ItemPrefab));
|
||||
int sortResult = ActiveStore.GetAdjustedItemBuyPrice(itemX.ItemPrefab).CompareTo(
|
||||
ActiveStore.GetAdjustedItemBuyPrice(itemY.ItemPrefab));
|
||||
if (sortingMethod == SortingMethod.PriceDesc) { sortResult *= -1; }
|
||||
return sortResult;
|
||||
}
|
||||
@@ -1485,7 +1523,7 @@ namespace Barotrauma
|
||||
};
|
||||
bool isSellingRelatedList = containingTab != StoreTab.Buy;
|
||||
bool locationHasDealOnItem = isSellingRelatedList ?
|
||||
CurrentLocation.RequestedGoods.Contains(pi.ItemPrefab) : CurrentLocation.DailySpecials.Contains(pi.ItemPrefab);
|
||||
ActiveStore.RequestedGoods.Contains(pi.ItemPrefab) : ActiveStore.DailySpecials.Contains(pi.ItemPrefab);
|
||||
GUITextBlock nameBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.4f), nameAndQuantityGroup.RectTransform),
|
||||
pi.ItemPrefab.Name, font: GUIStyle.SubHeadingFont, textAlignment: Alignment.BottomLeft)
|
||||
{
|
||||
@@ -1673,7 +1711,7 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
// Add items already purchased
|
||||
CargoManager?.PurchasedItems?.ForEach(pi => AddNonEmptyOwnedItems(pi));
|
||||
CargoManager?.GetPurchasedItems(ActiveStore).ForEach(pi => AddNonEmptyOwnedItems(pi));
|
||||
|
||||
ownedItemsUpdateTimer = 0.0f;
|
||||
|
||||
@@ -1689,7 +1727,7 @@ namespace Barotrauma
|
||||
|
||||
void AddOwnedItem(Item item)
|
||||
{
|
||||
if (!(item?.Prefab.GetPriceInfo(CurrentLocation) is PriceInfo priceInfo)) { return; }
|
||||
if (!(item?.Prefab.GetPriceInfo(ActiveStore) is PriceInfo priceInfo)) { return; }
|
||||
bool isNonEmpty = !priceInfo.DisplayNonEmpty || item.ConditionPercentage > 5.0f;
|
||||
if (OwnedItems.TryGetValue(item.Prefab, out ItemQuantity itemQuantity))
|
||||
{
|
||||
@@ -1862,7 +1900,7 @@ namespace Barotrauma
|
||||
{
|
||||
list = mode switch
|
||||
{
|
||||
StoreTab.Buy => CurrentLocation?.StoreStock,
|
||||
StoreTab.Buy => ActiveStore?.Stock,
|
||||
StoreTab.Sell => itemsToSell,
|
||||
StoreTab.SellSub => itemsToSellFromSub,
|
||||
_ => throw new NotImplementedException()
|
||||
@@ -1876,7 +1914,7 @@ namespace Barotrauma
|
||||
{
|
||||
if (mode == StoreTab.Buy)
|
||||
{
|
||||
var purchasedItem = CargoManager.PurchasedItems.Find(i => i.ItemPrefab == item.ItemPrefab);
|
||||
var purchasedItem = CargoManager.GetPurchasedItem(ActiveStore, item.ItemPrefab);
|
||||
if (purchasedItem != null) { return Math.Max(item.Quantity - purchasedItem.Quantity, 0); }
|
||||
}
|
||||
return item.Quantity;
|
||||
@@ -1887,22 +1925,19 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
private LocalizedString GetCurrencyFormatted(int amount) =>
|
||||
TextManager.GetWithVariable("currencyformat", "[credits]", string.Format(CultureInfo.InvariantCulture, "{0:N0}", amount));
|
||||
|
||||
private bool ModifyBuyQuantity(PurchasedItem item, int quantity)
|
||||
{
|
||||
if (item?.ItemPrefab == null) { return false; }
|
||||
if (!HasBuyPermissions) { return false; }
|
||||
if (quantity > 0)
|
||||
{
|
||||
var itemInCrate = CargoManager.ItemsInBuyCrate.Find(i => i.ItemPrefab == item.ItemPrefab);
|
||||
if (itemInCrate != null && itemInCrate.Quantity >= CargoManager.MaxQuantity) { return false; }
|
||||
var crateItem = CargoManager.GetBuyCrateItem(ActiveStore, item.ItemPrefab);
|
||||
if (crateItem != null && crateItem.Quantity >= CargoManager.MaxQuantity) { return false; }
|
||||
// Make sure there's enough available in the store
|
||||
var totalQuantityToBuy = itemInCrate != null ? itemInCrate.Quantity + quantity : quantity;
|
||||
var totalQuantityToBuy = crateItem != null ? crateItem.Quantity + quantity : quantity;
|
||||
if (totalQuantityToBuy > GetMaxAvailable(item.ItemPrefab, StoreTab.Buy)) { return false; }
|
||||
}
|
||||
CargoManager.ModifyItemQuantityInBuyCrate(item.ItemPrefab, quantity);
|
||||
CargoManager.ModifyItemQuantityInBuyCrate(ActiveStore.Identifier, item.ItemPrefab, quantity);
|
||||
GameMain.Client?.SendCampaignState();
|
||||
return true;
|
||||
}
|
||||
@@ -1914,11 +1949,11 @@ namespace Barotrauma
|
||||
if (quantity > 0)
|
||||
{
|
||||
// Make sure there's enough available to sell
|
||||
var itemToSell = CargoManager.ItemsInSellCrate.Find(i => i.ItemPrefab == item.ItemPrefab);
|
||||
var itemToSell = CargoManager.GetSellCrateItem(ActiveStore, item.ItemPrefab);
|
||||
var totalQuantityToSell = itemToSell != null ? itemToSell.Quantity + quantity : quantity;
|
||||
if (totalQuantityToSell > GetMaxAvailable(item.ItemPrefab, StoreTab.Sell)) { return false; }
|
||||
}
|
||||
CargoManager.ModifyItemQuantityInSellCrate(item.ItemPrefab, quantity);
|
||||
CargoManager.ModifyItemQuantityInSellCrate(ActiveStore.Identifier, item.ItemPrefab, quantity);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1929,11 +1964,11 @@ namespace Barotrauma
|
||||
if (quantity > 0)
|
||||
{
|
||||
// Make sure there's enough available to sell
|
||||
var itemToSell = CargoManager.ItemsInSellFromSubCrate.Find(i => i.ItemPrefab == item.ItemPrefab);
|
||||
var itemToSell = CargoManager.GetSubCrateItem(ActiveStore, item.ItemPrefab);
|
||||
var totalQuantityToSell = itemToSell != null ? itemToSell.Quantity + quantity : quantity;
|
||||
if (totalQuantityToSell > GetMaxAvailable(item.ItemPrefab, StoreTab.SellSub)) { return false; }
|
||||
}
|
||||
CargoManager.ModifyItemQuantityInSellFromSubCrate(item.ItemPrefab, quantity);
|
||||
CargoManager.ModifyItemQuantityInSubSellCrate(ActiveStore.Identifier, item.ItemPrefab, quantity);
|
||||
GameMain.Client?.SendCampaignState();
|
||||
return true;
|
||||
}
|
||||
@@ -1981,32 +2016,27 @@ namespace Barotrauma
|
||||
private bool BuyItems()
|
||||
{
|
||||
if (!HasBuyPermissions) { return false; }
|
||||
|
||||
var itemsToPurchase = new List<PurchasedItem>(CargoManager.ItemsInBuyCrate);
|
||||
var itemsToPurchase = new List<PurchasedItem>(CargoManager.GetBuyCrateItems(ActiveStore));
|
||||
var itemsToRemove = new List<PurchasedItem>();
|
||||
var totalPrice = 0;
|
||||
foreach (PurchasedItem item in itemsToPurchase)
|
||||
int totalPrice = 0;
|
||||
foreach (var item in itemsToPurchase)
|
||||
{
|
||||
if (item?.ItemPrefab == null || !item.ItemPrefab.CanBeBoughtAtLocation(CurrentLocation, out PriceInfo priceInfo))
|
||||
if (item?.ItemPrefab == null || !item.ItemPrefab.CanBeBoughtFrom(ActiveStore, out var priceInfo))
|
||||
{
|
||||
itemsToRemove.Add(item);
|
||||
continue;
|
||||
}
|
||||
totalPrice += item.Quantity * CurrentLocation.GetAdjustedItemBuyPrice(item.ItemPrefab, priceInfo: priceInfo);
|
||||
totalPrice += item.Quantity * ActiveStore.GetAdjustedItemBuyPrice(item.ItemPrefab, priceInfo: priceInfo);
|
||||
}
|
||||
itemsToRemove.ForEach(i => itemsToPurchase.Remove(i));
|
||||
|
||||
if (itemsToPurchase.None() || !PlayerWallet.CanAfford(totalPrice)) { return false; }
|
||||
|
||||
CargoManager.PurchaseItems(itemsToPurchase, true);
|
||||
CargoManager.PurchaseItems(ActiveStore.Identifier, itemsToPurchase, true);
|
||||
GameMain.Client?.SendCampaignState();
|
||||
|
||||
var dialog = new GUIMessageBox(
|
||||
TextManager.Get("newsupplies"),
|
||||
TextManager.GetWithVariable("suppliespurchasedmessage", "[location]", campaignUI?.Campaign?.Map?.CurrentLocation?.Name),
|
||||
new LocalizedString[] { TextManager.Get("Ok") });
|
||||
dialog.Buttons[0].OnClicked += dialog.Close;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -2018,8 +2048,8 @@ namespace Barotrauma
|
||||
{
|
||||
itemsToSell = activeTab switch
|
||||
{
|
||||
StoreTab.Sell => new List<PurchasedItem>(CargoManager.ItemsInSellCrate),
|
||||
StoreTab.SellSub => new List<PurchasedItem>(CargoManager.ItemsInSellFromSubCrate),
|
||||
StoreTab.Sell => new List<PurchasedItem>(CargoManager.GetSellCrateItems(ActiveStore)),
|
||||
StoreTab.SellSub => new List<PurchasedItem>(CargoManager.GetSubCrateItems(ActiveStore)),
|
||||
_ => throw new NotImplementedException()
|
||||
};
|
||||
}
|
||||
@@ -2032,9 +2062,9 @@ namespace Barotrauma
|
||||
int totalValue = 0;
|
||||
foreach (PurchasedItem item in itemsToSell)
|
||||
{
|
||||
if (item?.ItemPrefab?.GetPriceInfo(CurrentLocation) is PriceInfo priceInfo)
|
||||
if (item?.ItemPrefab?.GetPriceInfo(ActiveStore) is PriceInfo priceInfo)
|
||||
{
|
||||
totalValue += item.Quantity * CurrentLocation.GetAdjustedItemSellPrice(item.ItemPrefab, priceInfo: priceInfo);
|
||||
totalValue += item.Quantity * ActiveStore.GetAdjustedItemSellPrice(item.ItemPrefab, priceInfo: priceInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2042,8 +2072,8 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
itemsToRemove.ForEach(i => itemsToSell.Remove(i));
|
||||
if (itemsToSell.None() || totalValue > CurrentLocation.StoreCurrentBalance) { return false; }
|
||||
CargoManager.SellItems(itemsToSell, activeTab);
|
||||
if (itemsToSell.None() || totalValue > ActiveStore.Balance) { return false; }
|
||||
CargoManager.SellItems(ActiveStore.Identifier, itemsToSell, activeTab);
|
||||
GameMain.Client?.SendCampaignState();
|
||||
return false;
|
||||
}
|
||||
@@ -2052,7 +2082,7 @@ namespace Barotrauma
|
||||
{
|
||||
if (IsBuying)
|
||||
{
|
||||
shoppingCrateTotal.Text = GetCurrencyFormatted(buyTotal);
|
||||
shoppingCrateTotal.Text = TextManager.FormatCurrency(buyTotal);
|
||||
shoppingCrateTotal.TextColor = !PlayerWallet.CanAfford(buyTotal) ? Color.Red : Color.White;
|
||||
}
|
||||
else
|
||||
@@ -2063,8 +2093,8 @@ namespace Barotrauma
|
||||
StoreTab.SellSub => sellFromSubTotal,
|
||||
_ => throw new NotImplementedException(),
|
||||
};
|
||||
shoppingCrateTotal.Text = GetCurrencyFormatted(total);
|
||||
shoppingCrateTotal.TextColor = CurrentLocation != null && total > CurrentLocation.StoreCurrentBalance ? Color.Red : Color.White;
|
||||
shoppingCrateTotal.Text = TextManager.FormatCurrency(total);
|
||||
shoppingCrateTotal.TextColor = CurrentLocation != null && total > ActiveStore.Balance ? Color.Red : Color.White;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2100,8 +2130,8 @@ namespace Barotrauma
|
||||
activeTab switch
|
||||
{
|
||||
StoreTab.Buy => PlayerWallet.CanAfford(buyTotal),
|
||||
StoreTab.Sell => CurrentLocation != null && sellTotal <= CurrentLocation.StoreCurrentBalance,
|
||||
StoreTab.SellSub => CurrentLocation != null && sellFromSubTotal <= CurrentLocation.StoreCurrentBalance,
|
||||
StoreTab.Sell => CurrentLocation != null && sellTotal <= ActiveStore.Balance,
|
||||
StoreTab.SellSub => CurrentLocation != null && sellFromSubTotal <= ActiveStore.Balance,
|
||||
_ => false
|
||||
};
|
||||
}
|
||||
@@ -2124,6 +2154,7 @@ namespace Barotrauma
|
||||
if (GameMain.GraphicsWidth != resolutionWhenCreated.X || GameMain.GraphicsHeight != resolutionWhenCreated.Y)
|
||||
{
|
||||
CreateUI();
|
||||
needsRefresh = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2131,38 +2162,62 @@ namespace Barotrauma
|
||||
ownedItemsUpdateTimer += deltaTime;
|
||||
if (ownedItemsUpdateTimer >= timerUpdateInterval)
|
||||
{
|
||||
var prevOwnedItems = new Dictionary<ItemPrefab, ItemQuantity>(OwnedItems);
|
||||
bool checkForRefresh = !needsItemsToSellRefresh || !needsRefresh;
|
||||
var prevOwnedItems = checkForRefresh ? new Dictionary<ItemPrefab, ItemQuantity>(OwnedItems) : null;
|
||||
UpdateOwnedItems();
|
||||
bool refresh = OwnedItems.Count != prevOwnedItems.Count ||
|
||||
OwnedItems.Values.Sum(v => v.Total) != prevOwnedItems.Values.Sum(v => v.Total) ||
|
||||
OwnedItems.Any(kvp => !prevOwnedItems.TryGetValue(kvp.Key, out ItemQuantity v) || kvp.Value.Total != v.Total) ||
|
||||
prevOwnedItems.Any(kvp => !OwnedItems.ContainsKey(kvp.Key));
|
||||
if (refresh)
|
||||
if (checkForRefresh)
|
||||
{
|
||||
needsItemsToSellRefresh = true;
|
||||
needsRefresh = true;
|
||||
bool refresh = OwnedItems.Count != prevOwnedItems.Count ||
|
||||
OwnedItems.Values.Sum(v => v.Total) != prevOwnedItems.Values.Sum(v => v.Total) ||
|
||||
OwnedItems.Any(kvp => !prevOwnedItems.TryGetValue(kvp.Key, out ItemQuantity v) || kvp.Value.Total != v.Total) ||
|
||||
prevOwnedItems.Any(kvp => !OwnedItems.ContainsKey(kvp.Key));
|
||||
if (refresh)
|
||||
{
|
||||
needsItemsToSellRefresh = true;
|
||||
needsRefresh = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Update the sellable sub items at short intervals and check if the interface should be refreshed
|
||||
sellableItemsFromSubUpdateTimer += deltaTime;
|
||||
if (sellableItemsFromSubUpdateTimer >= timerUpdateInterval)
|
||||
{
|
||||
var prevSubItems = new List<PurchasedItem>(itemsToSellFromSub);
|
||||
bool checkForRefresh = !needsRefresh;
|
||||
var prevSubItems = checkForRefresh ? new List<PurchasedItem>(itemsToSellFromSub) : null;
|
||||
RefreshItemsToSellFromSub();
|
||||
needsRefresh = needsRefresh ||
|
||||
itemsToSellFromSub.Count != prevSubItems.Count ||
|
||||
itemsToSellFromSub.Sum(i => i.Quantity) != prevSubItems.Sum(i => i.Quantity) ||
|
||||
itemsToSellFromSub.Any(i => !(prevSubItems.FirstOrDefault(prev => prev.ItemPrefab == i.ItemPrefab) is PurchasedItem prev) || i.Quantity != prev.Quantity) ||
|
||||
prevSubItems.Any(prev => itemsToSellFromSub.None(i => i.ItemPrefab == prev.ItemPrefab));
|
||||
if (checkForRefresh)
|
||||
{
|
||||
needsRefresh = itemsToSellFromSub.Count != prevSubItems.Count ||
|
||||
itemsToSellFromSub.Sum(i => i.Quantity) != prevSubItems.Sum(i => i.Quantity) ||
|
||||
itemsToSellFromSub.Any(i => !(prevSubItems.FirstOrDefault(prev => prev.ItemPrefab == i.ItemPrefab) is PurchasedItem prev) || i.Quantity != prev.Quantity) ||
|
||||
prevSubItems.Any(prev => itemsToSellFromSub.None(i => i.ItemPrefab == prev.ItemPrefab));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (needsItemsToSellRefresh) { RefreshItemsToSell(); }
|
||||
if (needsItemsToSellFromSubRefresh) { RefreshItemsToSellFromSub(); }
|
||||
if (needsRefresh || HavePermissionsChanged()) { Refresh(updateOwned: ownedItemsUpdateTimer > 0.0f); }
|
||||
if (needsBuyingRefresh || HavePermissionsChanged(StoreTab.Buy)) { RefreshBuying(updateOwned: ownedItemsUpdateTimer > 0.0f); }
|
||||
if (needsSellingRefresh || HavePermissionsChanged(StoreTab.Sell)) { RefreshSelling(updateOwned: ownedItemsUpdateTimer > 0.0f); }
|
||||
if (needsSellingFromSubRefresh || HavePermissionsChanged(StoreTab.SellSub)) { RefreshSellingFromSub(updateOwned: ownedItemsUpdateTimer > 0.0f, updateItemsToSellFromSub: sellableItemsFromSubUpdateTimer > 0.0f); }
|
||||
if (needsItemsToSellRefresh)
|
||||
{
|
||||
RefreshItemsToSell();
|
||||
}
|
||||
if (needsItemsToSellFromSubRefresh)
|
||||
{
|
||||
RefreshItemsToSellFromSub();
|
||||
}
|
||||
if (needsRefresh || HavePermissionsChanged())
|
||||
{
|
||||
Refresh(updateOwned: ownedItemsUpdateTimer > 0.0f);
|
||||
}
|
||||
if (needsBuyingRefresh || HavePermissionsChanged(StoreTab.Buy))
|
||||
{
|
||||
RefreshBuying(updateOwned: ownedItemsUpdateTimer > 0.0f);
|
||||
}
|
||||
if (needsSellingRefresh || HavePermissionsChanged(StoreTab.Sell))
|
||||
{
|
||||
RefreshSelling(updateOwned: ownedItemsUpdateTimer > 0.0f);
|
||||
}
|
||||
if (needsSellingFromSubRefresh || HavePermissionsChanged(StoreTab.SellSub))
|
||||
{
|
||||
RefreshSellingFromSub(updateOwned: ownedItemsUpdateTimer > 0.0f, updateItemsToSellFromSub: sellableItemsFromSubUpdateTimer > 0.0f);
|
||||
}
|
||||
|
||||
updateStopwatch.Stop();
|
||||
GameMain.PerformanceCounter.AddPartialElapsedTicks("GameSessionUpdate", "StoreUpdate", updateStopwatch.ElapsedTicks);
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace Barotrauma
|
||||
private readonly List<SubmarineInfo> subsToShow;
|
||||
private readonly SubmarineDisplayContent[] submarineDisplays = new SubmarineDisplayContent[submarinesPerPage];
|
||||
private SubmarineInfo selectedSubmarine = null;
|
||||
private LocalizedString purchaseAndSwitchText, purchaseOnlyText, deliveryText, currentSubText, deliveryFeeText, priceText, switchText, missingPreviewText, currencyShorthandText, currencyLongText;
|
||||
private LocalizedString purchaseAndSwitchText, purchaseOnlyText, deliveryText, currentSubText, deliveryFeeText, priceText, switchText, missingPreviewText, currencyName;
|
||||
private readonly RectTransform parent;
|
||||
private readonly Action closeAction;
|
||||
private Sprite pageIndicator;
|
||||
@@ -99,8 +99,7 @@ namespace Barotrauma
|
||||
priceText = TextManager.Get("price");
|
||||
}
|
||||
|
||||
currencyShorthandText = TextManager.Get("currencyformat");
|
||||
currencyLongText = TextManager.Get("credit").Value.ToLowerInvariant();
|
||||
currencyName = TextManager.Get("credit").Value.ToLowerInvariant();
|
||||
|
||||
UpdateSubmarines();
|
||||
missingPreviewText = TextManager.Get("SubPreviewImageNotFound");
|
||||
@@ -335,7 +334,7 @@ namespace Barotrauma
|
||||
|
||||
if (!GameMain.GameSession.IsSubmarineOwned(subToDisplay))
|
||||
{
|
||||
LocalizedString amountString = currencyShorthandText.Replace("[credits]", subToDisplay.Price.ToString());
|
||||
LocalizedString amountString = TextManager.FormatCurrency(subToDisplay.Price);
|
||||
submarineDisplays[i].submarineFee.Text = priceText.Replace("[amount]", amountString).Replace("[currencyname]", string.Empty).TrimEnd();
|
||||
}
|
||||
else
|
||||
@@ -344,7 +343,7 @@ namespace Barotrauma
|
||||
{
|
||||
if (deliveryFee > 0)
|
||||
{
|
||||
LocalizedString amountString = currencyShorthandText.Replace("[credits]", deliveryFee.ToString());
|
||||
LocalizedString amountString = TextManager.FormatCurrency(deliveryFee);
|
||||
submarineDisplays[i].submarineFee.Text = deliveryFeeText.Replace("[amount]", amountString).Replace("[currencyname]", string.Empty).TrimEnd();
|
||||
}
|
||||
else
|
||||
@@ -584,7 +583,7 @@ namespace Barotrauma
|
||||
if (!GameMain.GameSession.Campaign.Wallet.CanAfford(deliveryFee) && deliveryFee > 0)
|
||||
{
|
||||
new GUIMessageBox(TextManager.Get("deliveryrequestheader"), TextManager.GetWithVariables("notenoughmoneyfordeliverytext",
|
||||
("[currencyname]", currencyLongText),
|
||||
("[currencyname]", currencyName),
|
||||
("[submarinename]", selectedSubmarine.DisplayName),
|
||||
("[location1]", deliveryLocationName),
|
||||
("[location2]", GameMain.GameSession.Map.CurrentLocation.Name)));
|
||||
@@ -601,7 +600,7 @@ namespace Barotrauma
|
||||
("[location2]", GameMain.GameSession.Map.CurrentLocation.Name),
|
||||
("[submarinename2]", CurrentOrPendingSubmarine().DisplayName),
|
||||
("[amount]", deliveryFee.ToString()),
|
||||
("[currencyname]", currencyLongText)), messageBoxOptions);
|
||||
("[currencyname]", currencyName)), messageBoxOptions);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -632,7 +631,7 @@ namespace Barotrauma
|
||||
if (!GameMain.GameSession.Campaign.Wallet.CanAfford(selectedSubmarine.Price))
|
||||
{
|
||||
new GUIMessageBox(TextManager.Get("purchasesubmarineheader"), TextManager.GetWithVariables("notenoughmoneyforpurchasetext",
|
||||
("[currencyname]", currencyLongText),
|
||||
("[currencyname]", currencyName),
|
||||
("[submarinename]", selectedSubmarine.DisplayName)));
|
||||
return;
|
||||
}
|
||||
@@ -644,7 +643,7 @@ namespace Barotrauma
|
||||
msgBox = new GUIMessageBox(TextManager.Get("purchaseandswitchsubmarineheader"), TextManager.GetWithVariables("purchaseandswitchsubmarinetext",
|
||||
("[submarinename1]", selectedSubmarine.DisplayName),
|
||||
("[amount]", selectedSubmarine.Price.ToString()),
|
||||
("[currencyname]", currencyLongText),
|
||||
("[currencyname]", currencyName),
|
||||
("[submarinename2]", CurrentOrPendingSubmarine().DisplayName)), messageBoxOptions);
|
||||
|
||||
msgBox.Buttons[0].OnClicked = (applyButton, obj) =>
|
||||
@@ -667,7 +666,7 @@ namespace Barotrauma
|
||||
msgBox = new GUIMessageBox(TextManager.Get("purchasesubmarineheader"), TextManager.GetWithVariables("purchasesubmarinetext",
|
||||
("[submarinename]", selectedSubmarine.DisplayName),
|
||||
("[amount]", selectedSubmarine.Price.ToString()),
|
||||
("[currencyname]", currencyLongText)), messageBoxOptions);
|
||||
("[currencyname]", currencyName)), messageBoxOptions);
|
||||
|
||||
msgBox.Buttons[0].OnClicked = (applyButton, obj) =>
|
||||
{
|
||||
|
||||
@@ -218,7 +218,7 @@ namespace Barotrauma
|
||||
|
||||
public void AddToGUIUpdateList()
|
||||
{
|
||||
infoFrame?.AddToGUIUpdateList();
|
||||
infoFrame?.AddToGUIUpdateList(order: 1);
|
||||
NetLobbyScreen.JobInfoFrame?.AddToGUIUpdateList();
|
||||
}
|
||||
|
||||
@@ -379,8 +379,7 @@ namespace Barotrauma
|
||||
|
||||
private void CreateCrewListFrame(GUIFrame crewFrame)
|
||||
{
|
||||
// FIXME remove TestScreen stuff
|
||||
crew = GameMain.GameSession?.CrewManager?.GetCharacters() ?? new []{ TestScreen.dummyCharacter };
|
||||
crew = GameMain.GameSession?.CrewManager?.GetCharacters() ?? Array.Empty<Character>();
|
||||
teamIDs = crew.Select(c => c.TeamID).Distinct().ToList();
|
||||
|
||||
// Show own team first when there's more than one team
|
||||
@@ -817,8 +816,11 @@ namespace Barotrauma
|
||||
else if (client != null)
|
||||
{
|
||||
GUIComponent preview = CreateClientInfoFrame(background, client, GetPermissionIcon(client));
|
||||
if (GameMain.NetworkMember != null) { GameMain.Client.SelectCrewClient(client, preview); }
|
||||
CreateWalletFrame(background, client.Character);
|
||||
GameMain.Client?.SelectCrewClient(client, preview);
|
||||
if (client.Character != null)
|
||||
{
|
||||
CreateWalletFrame(background, client.Character);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -845,22 +847,23 @@ namespace Barotrauma
|
||||
float relativeX = icon.RectTransform.NonScaledSize.X / (float)icon.Parent.RectTransform.NonScaledSize.X;
|
||||
GUILayoutGroup headerTextLayout = new GUILayoutGroup(new RectTransform(new Vector2(1.0f - relativeX, 1f), headerLayout.RectTransform), isHorizontal: true) { Stretch = true };
|
||||
new GUITextBlock(new RectTransform(new Vector2(0.5f, 1f), headerTextLayout.RectTransform), TextManager.Get("crewwallet.wallet"), font: GUIStyle.LargeFont);
|
||||
GUITextBlock moneyBlock = new GUITextBlock(new RectTransform(new Vector2(0.5f, 1f), headerTextLayout.RectTransform), UpgradeStore.FormatCurrency(targetWallet.Balance), font: GUIStyle.SubHeadingFont, textAlignment: Alignment.Right);
|
||||
GUITextBlock moneyBlock = new GUITextBlock(new RectTransform(new Vector2(0.5f, 1f), headerTextLayout.RectTransform), TextManager.FormatCurrency(targetWallet.Balance), font: GUIStyle.SubHeadingFont, textAlignment: Alignment.Right);
|
||||
|
||||
GUILayoutGroup middleLayout = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.66f), walletLayout.RectTransform));
|
||||
GUILayoutGroup salaryTextLayout = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.5f), middleLayout.RectTransform), isHorizontal: true);
|
||||
GUITextBlock salaryTitle = new GUITextBlock(new RectTransform(new Vector2(0.5f, 1f), salaryTextLayout.RectTransform), TextManager.Get("crewwallet.salary"), font: GUIStyle.SubHeadingFont, textAlignment: Alignment.BottomLeft);
|
||||
GUITextBlock rewardBlock = new GUITextBlock(new RectTransform(new Vector2(0.5f, 1f), salaryTextLayout.RectTransform), TextManager.GetWithVariable("percentageformat", "[value]", GetSharePercentage()), textAlignment: Alignment.BottomRight);
|
||||
GUITextBlock rewardBlock = new GUITextBlock(new RectTransform(new Vector2(0.5f, 1f), salaryTextLayout.RectTransform), string.Empty, textAlignment: Alignment.BottomRight);
|
||||
GUILayoutGroup sliderLayout = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.5f), middleLayout.RectTransform), isHorizontal: true, childAnchor: Anchor.Center);
|
||||
GUIScrollBar salarySlider = new GUIScrollBar(new RectTransform(new Vector2(0.9f, 1f), sliderLayout.RectTransform), style: "GUISlider", barSize: 0.03f)
|
||||
{
|
||||
Range = Vector2.UnitY,
|
||||
ToolTip = TextManager.Get("crewwallet.salary.tooltip"),
|
||||
Range = new Vector2(0, 1),
|
||||
BarScrollValue = targetWallet.RewardDistribution / 100f,
|
||||
Step = 0.01f,
|
||||
BarSize = 0.1f,
|
||||
OnMoved = (bar, scroll) =>
|
||||
{
|
||||
rewardBlock.Text = TextManager.GetWithVariable("percentageformat", "[value]", GetSharePercentage());
|
||||
SetRewardText((int)(scroll * 100), rewardBlock);
|
||||
return true;
|
||||
},
|
||||
OnReleased = (bar, scroll) =>
|
||||
@@ -871,6 +874,9 @@ namespace Barotrauma
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
SetRewardText(targetWallet.RewardDistribution, rewardBlock);
|
||||
|
||||
// @formatter:off
|
||||
GUIScissorComponent scissorComponent = new GUIScissorComponent(new RectTransform(new Vector2(0.85f, 1.25f), walletFrame.RectTransform, Anchor.BottomCenter, Pivot.TopCenter))
|
||||
{
|
||||
@@ -883,7 +889,7 @@ namespace Barotrauma
|
||||
GUILayoutGroup mainLayout = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.5f), paddedTransferMenuLayout.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterLeft);
|
||||
GUILayoutGroup leftLayout = new GUILayoutGroup(new RectTransform(new Vector2(0.5f, 1f), mainLayout.RectTransform));
|
||||
GUITextBlock leftName = new GUITextBlock(new RectTransform(new Vector2(1f, 0.5f), leftLayout.RectTransform), character.Name, textAlignment: Alignment.CenterLeft, font: GUIStyle.SubHeadingFont);
|
||||
GUITextBlock leftBalance = new GUITextBlock(new RectTransform(new Vector2(1f, 0.5f), leftLayout.RectTransform), UpgradeStore.FormatCurrency(targetWallet.Balance), textAlignment: Alignment.Left) { TextColor = GUIStyle.Blue };
|
||||
GUITextBlock leftBalance = new GUITextBlock(new RectTransform(new Vector2(1f, 0.5f), leftLayout.RectTransform), TextManager.FormatCurrency(targetWallet.Balance), textAlignment: Alignment.Left) { TextColor = GUIStyle.Blue };
|
||||
GUILayoutGroup rightLayout = new GUILayoutGroup(new RectTransform(new Vector2(0.5f, 1f), mainLayout.RectTransform), childAnchor: Anchor.TopRight);
|
||||
GUITextBlock rightName = new GUITextBlock(new RectTransform(new Vector2(1f, 0.5f), rightLayout.RectTransform), string.Empty, font: GUIStyle.SubHeadingFont, textAlignment: Alignment.CenterRight);
|
||||
GUITextBlock rightBalance = new GUITextBlock(new RectTransform(new Vector2(1f, 0.5f), rightLayout.RectTransform), string.Empty, textAlignment: Alignment.Right) { TextColor = GUIStyle.Red };
|
||||
@@ -902,8 +908,11 @@ namespace Barotrauma
|
||||
GUIButton confirmButton = new GUIButton(new RectTransform(new Vector2(0.5f, 1f), centerButtonLayout.RectTransform), TextManager.Get("confirm"), style: "GUIButtonFreeScale") { Enabled = false };
|
||||
GUIButton resetButton = new GUIButton(new RectTransform(new Vector2(0.5f, 1f), centerButtonLayout.RectTransform), TextManager.Get("reset"), style: "GUIButtonFreeScale") { Enabled = false };
|
||||
// @formatter:on
|
||||
ImmutableArray<GUILayoutGroup> layoutGroups = ImmutableArray.Create(transferMenuLayout, paddedTransferMenuLayout, mainLayout, leftLayout, rightLayout);
|
||||
MedicalClinicUI.EnsureTextDoesntOverflow(character.Name, leftName, leftLayout.Rect, layoutGroups);
|
||||
transferMenuButton = new GUIButton(new RectTransform(new Vector2(0.5f, 0.2f), walletFrame.RectTransform, Anchor.BottomCenter, Pivot.TopCenter), style: "UIToggleButtonVertical")
|
||||
{
|
||||
ToolTip = TextManager.Get("crewwallet.transfer.tooltip"),
|
||||
OnClicked = (button, o) =>
|
||||
{
|
||||
isTransferMenuOpen = !isTransferMenuOpen;
|
||||
@@ -951,13 +960,15 @@ namespace Barotrauma
|
||||
break;
|
||||
}
|
||||
|
||||
MedicalClinicUI.EnsureTextDoesntOverflow(rightName.Text.ToString(), rightName, rightLayout.Rect, layoutGroups);
|
||||
|
||||
if (!hasPermissions)
|
||||
{
|
||||
centerButton.Enabled = centerButton.CanBeFocused = false;
|
||||
salarySlider.Enabled = salarySlider.CanBeFocused = false;
|
||||
}
|
||||
|
||||
leftBalance.Text = UpgradeStore.FormatCurrency(otherWallet.Balance);
|
||||
leftBalance.Text = TextManager.FormatCurrency(otherWallet.Balance);
|
||||
|
||||
UpdateAllInputs();
|
||||
|
||||
@@ -983,7 +994,7 @@ namespace Barotrauma
|
||||
{
|
||||
if (e.Wallet == targetWallet)
|
||||
{
|
||||
moneyBlock.Text = UpgradeStore.FormatCurrency(e.Info.Balance);
|
||||
moneyBlock.Text = TextManager.FormatCurrency(e.Info.Balance);
|
||||
salarySlider.BarScrollValue = e.Info.RewardDistribution / 100f;
|
||||
}
|
||||
UpdateAllInputs();
|
||||
@@ -1022,23 +1033,23 @@ namespace Barotrauma
|
||||
confirmButton.Enabled = resetButton.Enabled = transferAmountInput.IntValue > 0;
|
||||
if (transferAmountInput.IntValue == 0)
|
||||
{
|
||||
rightBalance.Text = UpgradeStore.FormatCurrency(otherWallet.Balance);
|
||||
rightBalance.Text = TextManager.FormatCurrency(otherWallet.Balance);
|
||||
rightBalance.TextColor = GUIStyle.TextColorNormal;
|
||||
leftBalance.Text = UpgradeStore.FormatCurrency(targetWallet.Balance);
|
||||
leftBalance.Text = TextManager.FormatCurrency(targetWallet.Balance);
|
||||
leftBalance.TextColor = GUIStyle.TextColorNormal;
|
||||
}
|
||||
else if (isSending)
|
||||
{
|
||||
rightBalance.Text = UpgradeStore.FormatCurrency(otherWallet.Balance + transferAmountInput.IntValue);
|
||||
rightBalance.Text = TextManager.FormatCurrency(otherWallet.Balance + transferAmountInput.IntValue);
|
||||
rightBalance.TextColor = GUIStyle.Blue;
|
||||
leftBalance.Text = UpgradeStore.FormatCurrency(targetWallet.Balance - transferAmountInput.IntValue);
|
||||
leftBalance.Text = TextManager.FormatCurrency(targetWallet.Balance - transferAmountInput.IntValue);
|
||||
leftBalance.TextColor = GUIStyle.Red;
|
||||
}
|
||||
else
|
||||
{
|
||||
rightBalance.Text = UpgradeStore.FormatCurrency(otherWallet.Balance - transferAmountInput.IntValue);
|
||||
rightBalance.Text = TextManager.FormatCurrency(otherWallet.Balance - transferAmountInput.IntValue);
|
||||
rightBalance.TextColor = GUIStyle.Red;
|
||||
leftBalance.Text = UpgradeStore.FormatCurrency(targetWallet.Balance + transferAmountInput.IntValue);
|
||||
leftBalance.Text = TextManager.FormatCurrency(targetWallet.Balance + transferAmountInput.IntValue);
|
||||
leftBalance.TextColor = GUIStyle.Blue;
|
||||
}
|
||||
}
|
||||
@@ -1073,14 +1084,14 @@ namespace Barotrauma
|
||||
Receiver = to.Select(option => option.ID),
|
||||
Amount = amount
|
||||
};
|
||||
IWriteMessage msg = new WriteOnlyMessage().WithHeader(ClientPacketHeader.MONEY);
|
||||
IWriteMessage msg = new WriteOnlyMessage().WithHeader(ClientPacketHeader.TRANSFER_MONEY);
|
||||
transfer.Write(msg);
|
||||
GameMain.Client?.ClientPeer?.Send(msg, DeliveryMethod.Reliable);
|
||||
}
|
||||
|
||||
static void SetRewardDistribution(Character character, int newValue)
|
||||
{
|
||||
INetSerializableStruct transfer = new NetWalletSalaryUpdate
|
||||
INetSerializableStruct transfer = new NetWalletSetSalaryUpdate
|
||||
{
|
||||
Target = character.ID,
|
||||
NewRewardDistribution = newValue
|
||||
@@ -1090,7 +1101,23 @@ namespace Barotrauma
|
||||
GameMain.Client?.ClientPeer?.Send(msg, DeliveryMethod.Reliable);
|
||||
}
|
||||
|
||||
string GetSharePercentage() => Mission.GetRewardShare(targetWallet.RewardDistribution, salaryCrew, Option<int>.None()).Percentage.ToString();
|
||||
void SetRewardText(int value, GUITextBlock block)
|
||||
{
|
||||
var (_, percentage, sum) = Mission.GetRewardShare(value, salaryCrew, Option<int>.None());
|
||||
LocalizedString tooltip = string.Empty;
|
||||
block.TextColor = GUIStyle.TextColorNormal;
|
||||
|
||||
if (sum > 100)
|
||||
{
|
||||
tooltip = TextManager.GetWithVariables("crewwallet.salary.over100toolitp", ("[sum]", $"{(int)sum}"), ("[newvalue]", $"{percentage}"));
|
||||
block.TextColor = GUIStyle.Orange;
|
||||
}
|
||||
|
||||
LocalizedString text = TextManager.GetWithVariable("percentageformat", "[value]", $"{value}");
|
||||
|
||||
block.Text = text;
|
||||
block.ToolTip = RichString.Rich(tooltip);
|
||||
}
|
||||
}
|
||||
|
||||
private GUIComponent CreateClientInfoFrame(GUIFrame frame, Client client, Sprite permissionIcon = null)
|
||||
|
||||
@@ -287,7 +287,7 @@ namespace Barotrauma
|
||||
GUILayoutGroup rightLayout = new GUILayoutGroup(rectT(0.5f, 1, topHeaderLayout), childAnchor: Anchor.TopRight);
|
||||
GUILayoutGroup priceLayout = new GUILayoutGroup(rectT(1, 0.8f, rightLayout), childAnchor: Anchor.Center) { RelativeSpacing = 0.08f };
|
||||
new GUITextBlock(rectT(1f, 0f, priceLayout), TextManager.Get("CampaignStore.Balance"), font: GUIStyle.SubHeadingFont, textAlignment: Alignment.Right);
|
||||
new GUITextBlock(rectT(1f, 0f, priceLayout), FormatCurrency(PlayerWallet.Balance, format: true), font: GUIStyle.SubHeadingFont, textAlignment: Alignment.Right) { TextGetter = () => FormatCurrency(PlayerWallet.Balance, format: true) };
|
||||
new GUITextBlock(rectT(1f, 0f, priceLayout), TextManager.FormatCurrency(PlayerWallet.Balance), font: GUIStyle.SubHeadingFont, textAlignment: Alignment.Right) { TextGetter = () => TextManager.FormatCurrency(PlayerWallet.Balance) };
|
||||
new GUIFrame(rectT(0.5f, 0.1f, rightLayout, Anchor.BottomRight), style: "HorizontalLine") { IgnoreLayoutGroups = true };
|
||||
|
||||
repairButton.OnClicked = upgradeButton.OnClicked = (button, o) =>
|
||||
@@ -571,7 +571,7 @@ namespace Barotrauma
|
||||
var repairIcon = new GUIFrame(rectT(new Point(contentLayout.Rect.Height, contentLayout.Rect.Height), contentLayout), style: imageStyle);
|
||||
GUILayoutGroup textLayout = new GUILayoutGroup(rectT(0.8f - repairIcon.RectTransform.RelativeSize.X, 1, contentLayout)) { Stretch = true };
|
||||
new GUITextBlock(rectT(1, 0, textLayout), title, font: GUIStyle.SubHeadingFont) { CanBeFocused = false, AutoScaleHorizontal = true };
|
||||
new GUITextBlock(rectT(1, 0, textLayout), FormatCurrency(price));
|
||||
new GUITextBlock(rectT(1, 0, textLayout), TextManager.FormatCurrency(price));
|
||||
GUILayoutGroup buyButtonLayout = new GUILayoutGroup(rectT(0.2f, 1, contentLayout), childAnchor: Anchor.Center) { UserData = "buybutton" };
|
||||
new GUIButton(rectT(0.7f, 0.5f, buyButtonLayout), string.Empty, style: "RepairBuyButton") { ClickSound = GUISoundType.HireRepairClick, Enabled = PlayerWallet.Balance >= price && !isDisabled, OnClicked = onPressed };
|
||||
contentLayout.Recalculate();
|
||||
@@ -1094,7 +1094,7 @@ namespace Barotrauma
|
||||
|
||||
if (addBuyButton)
|
||||
{
|
||||
var formattedPrice = FormatCurrency(Math.Abs(price));
|
||||
var formattedPrice = TextManager.FormatCurrency(Math.Abs(price));
|
||||
//negative price = refund
|
||||
if (price < 0) { formattedPrice = "+" + formattedPrice; }
|
||||
buyButtonLayout = new GUILayoutGroup(rectT(0.2f, 1, prefabLayout), childAnchor: Anchor.TopCenter) { UserData = "buybutton" };
|
||||
@@ -1577,7 +1577,7 @@ namespace Barotrauma
|
||||
|
||||
if (priceLabel != null && !WaitForServerUpdate)
|
||||
{
|
||||
priceLabel.Text = FormatCurrency(price);
|
||||
priceLabel.Text = TextManager.FormatCurrency(price);
|
||||
if (currentLevel >= prefab.MaxLevel)
|
||||
{
|
||||
priceLabel.Text = TextManager.Get("Upgrade.MaxedUpgrade");
|
||||
@@ -1695,11 +1695,6 @@ namespace Barotrauma
|
||||
|
||||
private bool HasPermission => campaignUI.Campaign.AllowedToManageCampaign();
|
||||
|
||||
public static LocalizedString FormatCurrency(int money, bool format = true)
|
||||
{
|
||||
return TextManager.GetWithVariable("CurrencyFormat", "[credits]", format ? string.Format(CultureInfo.InvariantCulture, "{0:N0}", money) : money.ToString());
|
||||
}
|
||||
|
||||
// just a shortcut to create new RectTransforms since all the new RectTransform and new Vector2 confuses my IDE (and me)
|
||||
private static RectTransform rectT(float x, float y, GUIComponent parentComponent, Anchor anchor = Anchor.TopLeft, ScaleBasis scaleBasis = ScaleBasis.Normal)
|
||||
{
|
||||
|
||||
@@ -1038,9 +1038,9 @@ namespace Barotrauma
|
||||
// Update store stock when saving and quitting in an outpost (normally updated when CampaignMode.End() is called)
|
||||
if (GameSession?.Campaign is SinglePlayerCampaign spCampaign && Level.IsLoadedOutpost && spCampaign.Map?.CurrentLocation != null && spCampaign.CargoManager != null)
|
||||
{
|
||||
spCampaign.Map.CurrentLocation.AddToStock(spCampaign.CargoManager.SoldItems);
|
||||
spCampaign.Map.CurrentLocation.AddStock(spCampaign.CargoManager.SoldItems);
|
||||
spCampaign.CargoManager.ClearSoldItemsProjSpecific();
|
||||
spCampaign.Map.CurrentLocation.RemoveFromStock(spCampaign.CargoManager.PurchasedItems);
|
||||
spCampaign.Map.CurrentLocation.RemoveStock(spCampaign.CargoManager.PurchasedItems);
|
||||
}
|
||||
|
||||
SaveUtil.SaveGame(GameSession.SavePath);
|
||||
|
||||
@@ -45,28 +45,37 @@ namespace Barotrauma
|
||||
return SoldEntities.Where(se => se.Status != SoldEntity.SellStatus.Unconfirmed);
|
||||
}
|
||||
|
||||
public void SetItemsInBuyCrate(List<PurchasedItem> items)
|
||||
public void SetItemsInBuyCrate(Dictionary<Identifier, List<PurchasedItem>> items)
|
||||
{
|
||||
ItemsInBuyCrate.Clear();
|
||||
ItemsInBuyCrate.AddRange(items);
|
||||
foreach (var entry in items)
|
||||
{
|
||||
ItemsInBuyCrate.Add(entry.Key, entry.Value);
|
||||
}
|
||||
OnItemsInBuyCrateChanged?.Invoke();
|
||||
}
|
||||
|
||||
public void SetItemsInSubSellCrate(List<PurchasedItem> items)
|
||||
public void SetItemsInSubSellCrate(Dictionary<Identifier, List<PurchasedItem>> items)
|
||||
{
|
||||
ItemsInSellFromSubCrate.Clear();
|
||||
ItemsInSellFromSubCrate.AddRange(items);
|
||||
foreach (var entry in items)
|
||||
{
|
||||
ItemsInSellFromSubCrate.Add(entry.Key, entry.Value);
|
||||
}
|
||||
OnItemsInSellFromSubCrateChanged?.Invoke();
|
||||
}
|
||||
|
||||
public void SetSoldItems(List<SoldItem> items)
|
||||
public void SetSoldItems(Dictionary<Identifier, List<SoldItem>> items)
|
||||
{
|
||||
SoldItems.Clear();
|
||||
SoldItems.AddRange(items);
|
||||
foreach (var entry in items)
|
||||
{
|
||||
SoldItems.Add(entry.Key, entry.Value);
|
||||
}
|
||||
foreach (var se in SoldEntities)
|
||||
{
|
||||
if (se.Status == SoldEntity.SellStatus.Confirmed) { continue; }
|
||||
if (SoldItems.Any(si => Match(si, se, true)))
|
||||
if (SoldItems.Any(si => si.Value.Any(si => Match(si, se, true))))
|
||||
{
|
||||
se.Status = SoldEntity.SellStatus.Confirmed;
|
||||
}
|
||||
@@ -75,13 +84,16 @@ namespace Barotrauma
|
||||
se.Status = SoldEntity.SellStatus.Unconfirmed;
|
||||
}
|
||||
}
|
||||
foreach (var si in SoldItems)
|
||||
foreach (var soldItems in SoldItems.Values)
|
||||
{
|
||||
if (si.Origin != SoldItem.SellOrigin.Submarine) { continue; }
|
||||
if (!(SoldEntities.FirstOrDefault(se => se.Item == null && Match(si, se, false)) is SoldEntity soldEntityMatch)) { continue; }
|
||||
if (!(Entity.FindEntityByID(si.ID) is Item item)) { continue; }
|
||||
soldEntityMatch.SetItem(item);
|
||||
soldEntityMatch.Status = SoldEntity.SellStatus.Confirmed;
|
||||
foreach (var si in soldItems)
|
||||
{
|
||||
if (si.Origin != SoldItem.SellOrigin.Submarine) { continue; }
|
||||
if (!(SoldEntities.FirstOrDefault(se => se.Item == null && Match(si, se, false)) is SoldEntity soldEntityMatch)) { continue; }
|
||||
if (!(Entity.FindEntityByID(si.ID) is Item item)) { continue; }
|
||||
soldEntityMatch.SetItem(item);
|
||||
soldEntityMatch.Status = SoldEntity.SellStatus.Confirmed;
|
||||
}
|
||||
}
|
||||
OnSoldItemsChanged?.Invoke();
|
||||
|
||||
@@ -94,45 +106,24 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public void ModifyItemQuantityInSellCrate(ItemPrefab itemPrefab, int changeInQuantity)
|
||||
public void ModifyItemQuantityInSellCrate(Identifier storeIdentifier, ItemPrefab itemPrefab, int changeInQuantity)
|
||||
{
|
||||
var itemToSell = ItemsInSellCrate.Find(i => i.ItemPrefab == itemPrefab);
|
||||
if (itemToSell != null)
|
||||
if (GetSellCrateItem(storeIdentifier, itemPrefab) is { } item)
|
||||
{
|
||||
itemToSell.Quantity += changeInQuantity;
|
||||
if (itemToSell.Quantity < 1)
|
||||
item.Quantity += changeInQuantity;
|
||||
if (item.Quantity < 1)
|
||||
{
|
||||
ItemsInSellCrate.Remove(itemToSell);
|
||||
GetSellCrateItems(storeIdentifier)?.Remove(item);
|
||||
}
|
||||
}
|
||||
else if (changeInQuantity > 0)
|
||||
{
|
||||
itemToSell = new PurchasedItem(itemPrefab, changeInQuantity);
|
||||
ItemsInSellCrate.Add(itemToSell);
|
||||
GetSellCrateItems(storeIdentifier, create: true).Add(new PurchasedItem(itemPrefab, changeInQuantity));
|
||||
}
|
||||
OnItemsInSellCrateChanged?.Invoke();
|
||||
}
|
||||
|
||||
public void ModifyItemQuantityInSellFromSubCrate(ItemPrefab itemPrefab, int changeInQuantity)
|
||||
{
|
||||
var itemToSell = ItemsInSellFromSubCrate.Find(i => i.ItemPrefab == itemPrefab);
|
||||
if (itemToSell != null)
|
||||
{
|
||||
itemToSell.Quantity += changeInQuantity;
|
||||
if (itemToSell.Quantity < 1)
|
||||
{
|
||||
ItemsInSellFromSubCrate.Remove(itemToSell);
|
||||
}
|
||||
}
|
||||
else if (changeInQuantity > 0)
|
||||
{
|
||||
itemToSell = new PurchasedItem(itemPrefab, changeInQuantity);
|
||||
ItemsInSellFromSubCrate.Add(itemToSell);
|
||||
}
|
||||
OnItemsInSellFromSubCrateChanged?.Invoke();
|
||||
}
|
||||
|
||||
public void SellItems(List<PurchasedItem> itemsToSell, Store.StoreTab sellingMode)
|
||||
public void SellItems(Identifier storeIdentifier, List<PurchasedItem> itemsToSell, Store.StoreTab sellingMode)
|
||||
{
|
||||
IEnumerable<Item> sellableItems;
|
||||
try
|
||||
@@ -146,19 +137,24 @@ namespace Barotrauma
|
||||
}
|
||||
catch (NotImplementedException e)
|
||||
{
|
||||
DebugConsole.ShowError($"Error selling items: Uknown store tab type. {e.StackTrace.CleanupStackTrace()}");
|
||||
DebugConsole.ShowError($"Error selling items: uknown store tab type \"{sellingMode}\".\n{e.StackTrace.CleanupStackTrace()}");
|
||||
return;
|
||||
}
|
||||
bool canAddToRemoveQueue = campaign.IsSinglePlayer && Entity.Spawner != null;
|
||||
byte sellerId = GameMain.Client?.ID ?? 0;
|
||||
// Check all the prices before starting the transaction
|
||||
// to make sure the modifiers stay the same for the whole transaction
|
||||
Dictionary<ItemPrefab, int> sellValues = GetSellValuesAtCurrentLocation(itemsToSell.Select(i => i.ItemPrefab));
|
||||
foreach (PurchasedItem item in itemsToSell)
|
||||
// Check all the prices before starting the transaction to make sure the modifiers stay the same for the whole transaction
|
||||
var sellValues = GetSellValuesAtCurrentLocation(storeIdentifier, itemsToSell.Select(i => i.ItemPrefab));
|
||||
if (!(Location.GetStore(storeIdentifier) is { } store))
|
||||
{
|
||||
DebugConsole.ShowError($"Error selling items at {Location}: no store with identifier \"{storeIdentifier}\" exists.\n{Environment.StackTrace.CleanupStackTrace()}");
|
||||
return;
|
||||
}
|
||||
var storeSpecificSoldItems = GetSoldItems(storeIdentifier, create: true);
|
||||
foreach (var item in itemsToSell)
|
||||
{
|
||||
int itemValue = item.Quantity * sellValues[item.ItemPrefab];
|
||||
// check if the store can afford the item
|
||||
if (Location.StoreCurrentBalance < itemValue) { continue; }
|
||||
if (store.Balance < itemValue) { continue; }
|
||||
// TODO: Write logic for prioritizing certain items over others (e.g. lone Battery Cell should be preferred over one inside a Stun Baton)
|
||||
var matchingItems = sellableItems.Where(i => i.Prefab == item.ItemPrefab);
|
||||
int count = Math.Min(item.Quantity, matchingItems.Count());
|
||||
@@ -168,7 +164,7 @@ namespace Barotrauma
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
var matchingItem = matchingItems.ElementAt(i);
|
||||
SoldItems.Add(new SoldItem(matchingItem.Prefab, matchingItem.ID, canAddToRemoveQueue, sellerId, origin));
|
||||
storeSpecificSoldItems.Add(new SoldItem(matchingItem.Prefab, matchingItem.ID, canAddToRemoveQueue, sellerId, origin));
|
||||
SoldEntities.Add(new SoldEntity(matchingItem, campaign.IsSinglePlayer ? SoldEntity.SellStatus.Confirmed : SoldEntity.SellStatus.Local));
|
||||
if (canAddToRemoveQueue) { Entity.Spawner.AddItemToRemoveQueue(matchingItem); }
|
||||
}
|
||||
@@ -178,22 +174,23 @@ namespace Barotrauma
|
||||
// When selling from the sub in multiplayer, the server will determine the items that are sold
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
SoldItems.Add(new SoldItem(item.ItemPrefab, Entity.NullEntityID, canAddToRemoveQueue, sellerId, origin));
|
||||
storeSpecificSoldItems.Add(new SoldItem(item.ItemPrefab, Entity.NullEntityID, canAddToRemoveQueue, sellerId, origin));
|
||||
SoldEntities.Add(new SoldEntity(item.ItemPrefab, SoldEntity.SellStatus.Local));
|
||||
}
|
||||
}
|
||||
// Exchange money
|
||||
Location.StoreCurrentBalance -= itemValue;
|
||||
store.Balance -= itemValue;
|
||||
campaign.Bank.Give(itemValue);
|
||||
GameAnalyticsManager.AddMoneyGainedEvent(itemValue, GameAnalyticsManager.MoneySource.Store, item.ItemPrefab.Identifier.Value);
|
||||
|
||||
// Remove from the sell crate
|
||||
if ((sellingMode == Store.StoreTab.Sell ? ItemsInSellCrate : ItemsInSellFromSubCrate)?.Find(pi => pi.ItemPrefab == item.ItemPrefab) is { } itemToSell)
|
||||
var sellCrate = (sellingMode == Store.StoreTab.Sell ? GetSellCrateItems(storeIdentifier) : GetSubCrateItems(storeIdentifier));
|
||||
if (sellCrate?.Find(pi => pi.ItemPrefab == item.ItemPrefab) is { } itemToSell)
|
||||
{
|
||||
itemToSell.Quantity -= item.Quantity;
|
||||
if (itemToSell.Quantity < 1)
|
||||
{
|
||||
(sellingMode == Store.StoreTab.Sell ? ItemsInSellCrate : ItemsInSellFromSubCrate)?.Remove(itemToSell);
|
||||
sellCrate.Remove(itemToSell);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,6 +63,10 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current personal wallet
|
||||
/// In singleplayer this is the campaign bank and in multiplayer this is the personal wallet
|
||||
/// </summary>
|
||||
public virtual Wallet Wallet => GetWallet();
|
||||
|
||||
public override void ShowStartMessage()
|
||||
@@ -301,7 +305,7 @@ namespace Barotrauma
|
||||
goto default;
|
||||
default:
|
||||
ShowCampaignUI = true;
|
||||
CampaignUI.SelectTab(npc.CampaignInteractionType);
|
||||
CampaignUI.SelectTab(npc.CampaignInteractionType, storeIdentifier: npc.MerchantIdentifier);
|
||||
CampaignUI.UpgradeStore?.RefreshAll();
|
||||
break;
|
||||
}
|
||||
|
||||
+24
-72
@@ -553,36 +553,10 @@ namespace Barotrauma
|
||||
msg.Write(PurchasedItemRepairs);
|
||||
msg.Write(PurchasedLostShuttles);
|
||||
|
||||
msg.Write((UInt16)CargoManager.ItemsInBuyCrate.Count);
|
||||
foreach (PurchasedItem pi in CargoManager.ItemsInBuyCrate)
|
||||
{
|
||||
msg.Write(pi.ItemPrefab.Identifier);
|
||||
msg.WriteRangedInteger(pi.Quantity, 0, CargoManager.MaxQuantity);
|
||||
}
|
||||
|
||||
msg.Write((UInt16)CargoManager.ItemsInSellFromSubCrate.Count);
|
||||
foreach (PurchasedItem pi in CargoManager.ItemsInSellFromSubCrate)
|
||||
{
|
||||
msg.Write(pi.ItemPrefab.Identifier);
|
||||
msg.WriteRangedInteger(pi.Quantity, 0, CargoManager.MaxQuantity);
|
||||
}
|
||||
|
||||
msg.Write((UInt16)CargoManager.PurchasedItems.Count);
|
||||
foreach (PurchasedItem pi in CargoManager.PurchasedItems)
|
||||
{
|
||||
msg.Write(pi.ItemPrefab.Identifier);
|
||||
msg.WriteRangedInteger(pi.Quantity, 0, CargoManager.MaxQuantity);
|
||||
}
|
||||
|
||||
msg.Write((UInt16)CargoManager.SoldItems.Count);
|
||||
foreach (SoldItem si in CargoManager.SoldItems)
|
||||
{
|
||||
msg.Write(si.ItemPrefab.Identifier);
|
||||
msg.Write((UInt16)si.ID);
|
||||
msg.Write(si.Removed);
|
||||
msg.Write(si.SellerID);
|
||||
msg.Write((byte)si.Origin);
|
||||
}
|
||||
WriteItems(msg, CargoManager.ItemsInBuyCrate);
|
||||
WriteItems(msg, CargoManager.ItemsInSellFromSubCrate);
|
||||
WriteItems(msg, CargoManager.PurchasedItems);
|
||||
WriteItems(msg, CargoManager.SoldItems);
|
||||
|
||||
msg.Write((ushort)UpgradeManager.PurchasedUpgrades.Count);
|
||||
foreach (var (prefab, category, level) in UpgradeManager.PurchasedUpgrades)
|
||||
@@ -644,50 +618,22 @@ namespace Barotrauma
|
||||
availableMissions.Add((missionIdentifier, connectionIndex));
|
||||
}
|
||||
|
||||
UInt16? storeBalance = null;
|
||||
var storeBalances = new Dictionary<Identifier, UInt16>();
|
||||
if (msg.ReadBoolean())
|
||||
{
|
||||
storeBalance = msg.ReadUInt16();
|
||||
byte storeCount = msg.ReadByte();
|
||||
for (int i = 0; i < storeCount; i++)
|
||||
{
|
||||
Identifier identifier = msg.ReadIdentifier();
|
||||
UInt16 storeBalance = msg.ReadUInt16();
|
||||
storeBalances.Add(identifier, storeBalance);
|
||||
}
|
||||
}
|
||||
|
||||
UInt16 buyCrateItemCount = msg.ReadUInt16();
|
||||
List<PurchasedItem> buyCrateItems = new List<PurchasedItem>();
|
||||
for (int i = 0; i < buyCrateItemCount; i++)
|
||||
{
|
||||
Identifier itemPrefabIdentifier = msg.ReadIdentifier();
|
||||
int itemQuantity = msg.ReadRangedInteger(0, CargoManager.MaxQuantity);
|
||||
buyCrateItems.Add(new PurchasedItem(ItemPrefab.Prefabs[itemPrefabIdentifier], itemQuantity));
|
||||
}
|
||||
|
||||
UInt16 subSellCrateItemCount = msg.ReadUInt16();
|
||||
List<PurchasedItem> subSellCrateItems = new List<PurchasedItem>();
|
||||
for (int i = 0; i < subSellCrateItemCount; i++)
|
||||
{
|
||||
string itemPrefabIdentifier = msg.ReadString();
|
||||
int itemQuantity = msg.ReadRangedInteger(0, CargoManager.MaxQuantity);
|
||||
subSellCrateItems.Add(new PurchasedItem(ItemPrefab.Prefabs[itemPrefabIdentifier], itemQuantity));
|
||||
}
|
||||
|
||||
UInt16 purchasedItemCount = msg.ReadUInt16();
|
||||
List<PurchasedItem> purchasedItems = new List<PurchasedItem>();
|
||||
for (int i = 0; i < purchasedItemCount; i++)
|
||||
{
|
||||
Identifier itemPrefabIdentifier = msg.ReadIdentifier();
|
||||
int itemQuantity = msg.ReadRangedInteger(0, CargoManager.MaxQuantity);
|
||||
purchasedItems.Add(new PurchasedItem(ItemPrefab.Prefabs[itemPrefabIdentifier], itemQuantity));
|
||||
}
|
||||
|
||||
UInt16 soldItemCount = msg.ReadUInt16();
|
||||
List<SoldItem> soldItems = new List<SoldItem>();
|
||||
for (int i = 0; i < soldItemCount; i++)
|
||||
{
|
||||
Identifier itemPrefabIdentifier = msg.ReadIdentifier();
|
||||
UInt16 id = msg.ReadUInt16();
|
||||
bool removed = msg.ReadBoolean();
|
||||
byte sellerId = msg.ReadByte();
|
||||
byte origin = msg.ReadByte();
|
||||
soldItems.Add(new SoldItem(ItemPrefab.Prefabs[itemPrefabIdentifier], id, removed, sellerId, (SoldItem.SellOrigin)origin));
|
||||
}
|
||||
var buyCrateItems = ReadPurchasedItems(msg, sender: null);
|
||||
var subSellCrateItems = ReadPurchasedItems(msg, sender: null);
|
||||
var purchasedItems = ReadPurchasedItems(msg, sender: null);
|
||||
var soldItems = ReadSoldItems(msg);
|
||||
|
||||
ushort pendingUpgradeCount = msg.ReadUInt16();
|
||||
List<PurchasedUpgrade> pendingUpgrades = new List<PurchasedUpgrade>();
|
||||
@@ -756,7 +702,13 @@ namespace Barotrauma
|
||||
campaign.CargoManager.SetItemsInSubSellCrate(subSellCrateItems);
|
||||
campaign.CargoManager.SetPurchasedItems(purchasedItems);
|
||||
campaign.CargoManager.SetSoldItems(soldItems);
|
||||
if (storeBalance.HasValue) { campaign.Map.CurrentLocation.StoreCurrentBalance = storeBalance.Value; }
|
||||
foreach (var balance in storeBalances)
|
||||
{
|
||||
if (campaign.Map.CurrentLocation.GetStore(balance.Key) is { } store)
|
||||
{
|
||||
store.Balance = balance.Value;
|
||||
}
|
||||
}
|
||||
campaign.UpgradeManager.SetPendingUpgrades(pendingUpgrades);
|
||||
campaign.UpgradeManager.PurchasedUpgrades.Clear();
|
||||
foreach (var purchasedItemSwap in purchasedItemSwaps)
|
||||
@@ -914,7 +866,7 @@ namespace Barotrauma
|
||||
WalletInfo info = transaction.Info;
|
||||
switch (transaction.CharacterID)
|
||||
{
|
||||
case Some<ushort> { Value: var charID}:
|
||||
case Some<ushort> { Value: var charID }:
|
||||
{
|
||||
Character targetCharacter = Character.CharacterList?.FirstOrDefault(c => c.ID == charID);
|
||||
if (targetCharacter is null) { break; }
|
||||
|
||||
+1
-1
@@ -121,7 +121,7 @@ namespace Barotrauma.Tutorials
|
||||
return new CharacterInfo(
|
||||
CharacterPrefab.HumanSpeciesName,
|
||||
jobOrJobPrefab: new Job(
|
||||
JobPrefab.Prefabs["medicaldoctor"], Rand.RandSync.Unsynced, 0,
|
||||
JobPrefab.Prefabs["engineer"], Rand.RandSync.Unsynced, 0,
|
||||
new Skill("medical".ToIdentifier(), 0),
|
||||
new Skill("weapons".ToIdentifier(), 0),
|
||||
new Skill("mechanical".ToIdentifier(), 20),
|
||||
|
||||
+1
-1
@@ -147,7 +147,7 @@ namespace Barotrauma.Tutorials
|
||||
return new CharacterInfo(
|
||||
CharacterPrefab.HumanSpeciesName,
|
||||
jobOrJobPrefab: new Job(
|
||||
JobPrefab.Prefabs["medicaldoctor"], Rand.RandSync.Unsynced, 0,
|
||||
JobPrefab.Prefabs["mechanic"], Rand.RandSync.Unsynced, 0,
|
||||
new Skill("medical".ToIdentifier(), 0),
|
||||
new Skill("weapons".ToIdentifier(), 0),
|
||||
new Skill("mechanical".ToIdentifier(), 50),
|
||||
|
||||
+1
-1
@@ -128,7 +128,7 @@ namespace Barotrauma.Tutorials
|
||||
return new CharacterInfo(
|
||||
CharacterPrefab.HumanSpeciesName,
|
||||
jobOrJobPrefab: new Job(
|
||||
JobPrefab.Prefabs["medicaldoctor"], Rand.RandSync.Unsynced, 0,
|
||||
JobPrefab.Prefabs["securityofficer"], Rand.RandSync.Unsynced, 0,
|
||||
new Skill("medical".ToIdentifier(), 20),
|
||||
new Skill("weapons".ToIdentifier(), 70),
|
||||
new Skill("mechanical".ToIdentifier(), 20),
|
||||
|
||||
@@ -318,7 +318,7 @@ namespace Barotrauma
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextContent.RectTransform), RichString.Rich(displayedMission.GetMissionRewardText(Submarine.MainSub)));
|
||||
if (GameMain.IsMultiplayer && Character.Controlled is { } controlled)
|
||||
{
|
||||
var (share, percentage) = Mission.GetRewardShare(controlled.Wallet.RewardDistribution, Mission.GetSalaryEligibleCrew(), Option<int>.Some(reward));
|
||||
var (share, percentage, _) = Mission.GetRewardShare(controlled.Wallet.RewardDistribution, Mission.GetSalaryEligibleCrew().Where(c => c != controlled), Option<int>.Some(reward));
|
||||
if (share > 0)
|
||||
{
|
||||
string shareFormatted = string.Format(CultureInfo.InvariantCulture, "{0:N0}", share);
|
||||
|
||||
@@ -966,7 +966,7 @@ namespace Barotrauma
|
||||
}
|
||||
else if (character.HeldItems.Any(i =>
|
||||
i.OwnInventory != null &&
|
||||
(i.OwnInventory.CanBePut(item) || (i.OwnInventory.Capacity == 1 && i.OwnInventory.AllowSwappingContainedItems && i.OwnInventory.Container.CanBeContained(item)))))
|
||||
((i.OwnInventory.CanBePut(item) && allowInventorySwap) || (i.OwnInventory.Capacity == 1 && i.OwnInventory.AllowSwappingContainedItems && i.OwnInventory.Container.CanBeContained(item)))))
|
||||
{
|
||||
return QuickUseAction.PutToEquippedItem;
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ namespace Barotrauma.Items.Components
|
||||
ContentXElement spriteElement = limbElement.GetChildElement("sprite");
|
||||
if (spriteElement == null) { continue; }
|
||||
|
||||
string spritePath = spriteElement.Attribute("texture").Value;
|
||||
string spritePath = spriteElement.GetAttribute("texture").Value;
|
||||
|
||||
spritePath = characterInfo.ReplaceVars(spritePath);
|
||||
|
||||
|
||||
@@ -462,7 +462,7 @@ namespace Barotrauma.Items.Components
|
||||
switch (subElement.Name.ToString().ToLowerInvariant())
|
||||
{
|
||||
case "guiframe":
|
||||
if (subElement.Attribute("rect") != null)
|
||||
if (subElement.GetAttribute("rect") != null)
|
||||
{
|
||||
DebugConsole.ThrowError($"Error in item config \"{item.ConfigFilePath}\" - GUIFrame defined as rect, use RectTransform instead.");
|
||||
break;
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
{
|
||||
|
||||
@@ -2,12 +2,14 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
{
|
||||
partial class ItemLabel : ItemComponent, IDrawableComponent
|
||||
partial class ItemLabel : ItemComponent, IDrawableComponent, IHasExtraTextPickerEntries
|
||||
{
|
||||
private GUITextBlock textBlock;
|
||||
|
||||
@@ -94,7 +96,15 @@ namespace Barotrauma.Items.Components
|
||||
get { return textBlock == null ? 1.0f : textBlock.TextScale; }
|
||||
set
|
||||
{
|
||||
if (textBlock != null) { textBlock.TextScale = MathHelper.Clamp(value, 0.1f, 10.0f); }
|
||||
if (textBlock != null)
|
||||
{
|
||||
float prevScale = TextBlock.TextScale;
|
||||
textBlock.TextScale = MathHelper.Clamp(value, 0.1f, 10.0f);
|
||||
if (!MathUtils.NearlyEqual(prevScale, TextBlock.TextScale))
|
||||
{
|
||||
SetScrollingText();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,7 +116,7 @@ namespace Barotrauma.Items.Components
|
||||
set
|
||||
{
|
||||
scrollable = value;
|
||||
IsActive = value;
|
||||
IsActive = value || parseSpecialTextTagOnStart;
|
||||
TextBlock.Wrap = !scrollable;
|
||||
TextBlock.TextAlignment = scrollable ? Alignment.CenterLeft : Alignment.Center;
|
||||
}
|
||||
@@ -136,18 +146,23 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
}
|
||||
|
||||
public IEnumerable<string> GetExtraTextPickerEntries()
|
||||
{
|
||||
return SpecialTextTags;
|
||||
}
|
||||
|
||||
private void SetScrollingText()
|
||||
{
|
||||
if (!scrollable) { return; }
|
||||
|
||||
float totalWidth = textBlock.Font.MeasureString(DisplayText).X;
|
||||
float totalWidth = textBlock.Font.MeasureString(DisplayText).X * TextBlock.TextScale;
|
||||
float textAreaWidth = Math.Max(textBlock.Rect.Width - textBlock.Padding.X - textBlock.Padding.Z, 0);
|
||||
if (totalWidth >= textAreaWidth)
|
||||
{
|
||||
//add enough spaces to fill the rect
|
||||
//(so the text can scroll entirely out of view before we reset it back to start)
|
||||
needsScrolling = true;
|
||||
float spaceWidth = textBlock.Font.MeasureChar(' ').X;
|
||||
float spaceWidth = textBlock.Font.MeasureChar(' ').X * TextBlock.TextScale;
|
||||
scrollingText = new string(' ', (int)Math.Ceiling(textAreaWidth / spaceWidth)) + DisplayText.Value;
|
||||
}
|
||||
else
|
||||
@@ -166,7 +181,7 @@ namespace Barotrauma.Items.Components
|
||||
charWidths = new float[scrollingText.Length];
|
||||
for (int i = 0; i < scrollingText.Length; i++)
|
||||
{
|
||||
float charWidth = TextBlock.Font.MeasureChar(scrollingText[i]).X;
|
||||
float charWidth = TextBlock.Font.MeasureChar(scrollingText[i]).X * TextBlock.TextScale;
|
||||
scrollPadding = Math.Max(charWidth, scrollPadding);
|
||||
charWidths[i] = charWidth;
|
||||
}
|
||||
@@ -174,9 +189,18 @@ namespace Barotrauma.Items.Components
|
||||
scrollIndex = MathHelper.Clamp(scrollIndex, 0, DisplayText.Length);
|
||||
}
|
||||
|
||||
private static readonly string[] SpecialTextTags = new string[] { "[CurrentLocationName]", "[CurrentBiomeName]", "[CurrentSubName]" };
|
||||
private bool parseSpecialTextTagOnStart;
|
||||
private void SetDisplayText(string value)
|
||||
{
|
||||
if (SpecialTextTags.Contains(value))
|
||||
{
|
||||
parseSpecialTextTagOnStart = true;
|
||||
IsActive = true;
|
||||
}
|
||||
|
||||
DisplayText = IgnoreLocalization ? value : TextManager.Get(value).Fallback(value);
|
||||
|
||||
TextBlock.Text = DisplayText;
|
||||
if (Screen.Selected == GameMain.SubEditorScreen && Scrollable)
|
||||
{
|
||||
@@ -198,9 +222,37 @@ namespace Barotrauma.Items.Components
|
||||
};
|
||||
}
|
||||
|
||||
private void ParseSpecialTextTag()
|
||||
{
|
||||
switch (text)
|
||||
{
|
||||
case "[CurrentLocationName]":
|
||||
SetDisplayText(Level.Loaded?.StartLocation?.Name ?? string.Empty);
|
||||
break;
|
||||
case "[CurrentBiomeName]":
|
||||
SetDisplayText(Level.Loaded?.LevelData?.Biome?.DisplayName.Value ?? string.Empty);
|
||||
break;
|
||||
case "[CurrentSubName]":
|
||||
SetDisplayText(item.Submarine?.Info?.DisplayName.Value ?? string.Empty);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Update(float deltaTime, Camera cam)
|
||||
{
|
||||
if (!scrollable) { return; }
|
||||
if (parseSpecialTextTagOnStart)
|
||||
{
|
||||
ParseSpecialTextTag();
|
||||
parseSpecialTextTagOnStart = false;
|
||||
}
|
||||
|
||||
if (!scrollable)
|
||||
{
|
||||
IsActive = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (scrollingText == null)
|
||||
{
|
||||
@@ -286,5 +338,6 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
Text = msg.ReadString();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Reflection.Metadata;
|
||||
|
||||
@@ -46,9 +47,12 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
private GUITextBlock requiredTimeBlock;
|
||||
|
||||
[Serialize("FabricatorCreate", IsPropertySaveable.Yes)]
|
||||
public string CreateButtonText { get; set; }
|
||||
|
||||
partial void InitProjSpecific()
|
||||
{
|
||||
CreateGUI();
|
||||
//CreateGUI();
|
||||
}
|
||||
|
||||
protected override void OnResolutionChanged()
|
||||
@@ -68,9 +72,11 @@ namespace Barotrauma.Items.Components
|
||||
AutoScaleVertical = true
|
||||
};
|
||||
|
||||
var mainFrame = new GUILayoutGroup(new RectTransform(new Vector2(1f, 1f), paddedFrame.RectTransform, Anchor.Center), childAnchor: Anchor.TopCenter)
|
||||
var mainFrame = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.95f), paddedFrame.RectTransform, Anchor.Center), childAnchor: Anchor.TopCenter)
|
||||
{
|
||||
RelativeSpacing = 0.02f
|
||||
RelativeSpacing = 0.02f,
|
||||
Stretch = true,
|
||||
CanBeFocused = true
|
||||
};
|
||||
|
||||
// === TOP AREA ===
|
||||
@@ -131,41 +137,55 @@ namespace Barotrauma.Items.Components
|
||||
// === BOTTOM AREA === //
|
||||
var bottomFrame = new GUIFrame(new RectTransform(new Vector2(1f, 0.3f), mainFrame.RectTransform), style: null);
|
||||
|
||||
if (inputContainer.Capacity > 0)
|
||||
{
|
||||
// === SEPARATOR === //
|
||||
var separatorArea = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.15f), bottomFrame.RectTransform, Anchor.TopCenter), childAnchor: Anchor.CenterLeft, isHorizontal: true)
|
||||
{
|
||||
Stretch = true,
|
||||
Stretch = true,
|
||||
RelativeSpacing = 0.03f
|
||||
};
|
||||
var inputLabel = new GUITextBlock(new RectTransform(Vector2.One, separatorArea.RectTransform), TextManager.Get("fabricator.input", "uilabel.input"), font: GUIStyle.SubHeadingFont) { Padding = Vector4.Zero };
|
||||
inputLabel.RectTransform.Resize(new Point((int) inputLabel.Font.MeasureString(inputLabel.Text).X, inputLabel.RectTransform.Rect.Height));
|
||||
new GUIFrame(new RectTransform(Vector2.One, separatorArea.RectTransform), style: "HorizontalLine");
|
||||
var inputLabel = new GUITextBlock(new RectTransform(Vector2.One, separatorArea.RectTransform), TextManager.Get("fabricator.input", "uilabel.input"), font: GUIStyle.SubHeadingFont) { Padding = Vector4.Zero };
|
||||
inputLabel.RectTransform.Resize(new Point((int)inputLabel.Font.MeasureString(inputLabel.Text).X, inputLabel.RectTransform.Rect.Height));
|
||||
new GUIFrame(new RectTransform(Vector2.One, separatorArea.RectTransform), style: "HorizontalLine");
|
||||
|
||||
// === INPUT AREA === //
|
||||
var inputArea = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 1f), bottomFrame.RectTransform, Anchor.BottomCenter), isHorizontal: true, childAnchor: Anchor.BottomLeft);
|
||||
|
||||
// === INPUT SLOTS === //
|
||||
inputInventoryHolder = new GUIFrame(new RectTransform(new Vector2(0.7f, 1f), inputArea.RectTransform), style: null);
|
||||
new GUICustomComponent(new RectTransform(Vector2.One, inputInventoryHolder.RectTransform), DrawInputOverLay) { CanBeFocused = false };
|
||||
|
||||
// === ACTIVATE BUTTON === //
|
||||
var buttonFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.3f, 0.8f), inputArea.RectTransform), childAnchor: Anchor.CenterRight);
|
||||
activateButton = new GUIButton(new RectTransform(new Vector2(1f, 0.6f), buttonFrame.RectTransform),
|
||||
TextManager.Get("FabricatorCreate"), style: "DeviceButton")
|
||||
{
|
||||
OnClicked = StartButtonClicked,
|
||||
UserData = selectedItem,
|
||||
Enabled = false
|
||||
};
|
||||
// === POWER WARNING === //
|
||||
inSufficientPowerWarning = new GUITextBlock(new RectTransform(Vector2.One, activateButton.RectTransform),
|
||||
TextManager.Get("FabricatorNoPower"), textColor: GUIStyle.Orange, textAlignment: Alignment.Center, color: Color.Black, style: "OuterGlow", wrap: true)
|
||||
{
|
||||
HoverColor = Color.Black,
|
||||
IgnoreLayoutGroups = true,
|
||||
Visible = false,
|
||||
CanBeFocused = false
|
||||
};
|
||||
// === INPUT SLOTS === //
|
||||
inputInventoryHolder = new GUIFrame(new RectTransform(new Vector2(0.7f, 1f), inputArea.RectTransform), style: null);
|
||||
new GUICustomComponent(new RectTransform(Vector2.One, inputInventoryHolder.RectTransform), DrawInputOverLay) { CanBeFocused = false };
|
||||
|
||||
// === ACTIVATE BUTTON === //
|
||||
var buttonFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.3f, 0.8f), inputArea.RectTransform), childAnchor: Anchor.CenterRight);
|
||||
activateButton = new GUIButton(new RectTransform(new Vector2(1f, 0.6f), buttonFrame.RectTransform),
|
||||
TextManager.Get(CreateButtonText), style: "DeviceButton")
|
||||
{
|
||||
OnClicked = StartButtonClicked,
|
||||
UserData = selectedItem,
|
||||
Enabled = false
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
bottomFrame.RectTransform.RelativeSize = new Vector2(1.0f, 0.1f);
|
||||
activateButton = new GUIButton(new RectTransform(new Vector2(0.3f, 1.0f), bottomFrame.RectTransform, Anchor.CenterRight),
|
||||
TextManager.Get(CreateButtonText), style: "DeviceButton")
|
||||
{
|
||||
OnClicked = StartButtonClicked,
|
||||
UserData = selectedItem,
|
||||
Enabled = false
|
||||
};
|
||||
}
|
||||
// === POWER WARNING === //
|
||||
inSufficientPowerWarning = new GUITextBlock(new RectTransform(Vector2.One, activateButton.RectTransform),
|
||||
TextManager.Get("FabricatorNoPower"), textColor: GUIStyle.Orange, textAlignment: Alignment.Center, color: Color.Black, style: "OuterGlow", wrap: true)
|
||||
{
|
||||
HoverColor = Color.Black,
|
||||
IgnoreLayoutGroups = true,
|
||||
Visible = false,
|
||||
CanBeFocused = false
|
||||
};
|
||||
CreateRecipes();
|
||||
}
|
||||
|
||||
@@ -222,8 +242,12 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
partial void OnItemLoadedProjSpecific()
|
||||
{
|
||||
inputContainer.AllowUIOverlap = true;
|
||||
inputContainer.Inventory.RectTransform = inputInventoryHolder.RectTransform;
|
||||
CreateGUI();
|
||||
if (inputInventoryHolder != null)
|
||||
{
|
||||
inputContainer.AllowUIOverlap = true;
|
||||
inputContainer.Inventory.RectTransform = inputInventoryHolder.RectTransform;
|
||||
}
|
||||
outputContainer.AllowUIOverlap = true;
|
||||
outputContainer.Inventory.RectTransform = outputInventoryHolder.RectTransform;
|
||||
}
|
||||
@@ -262,7 +286,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
var insufficientSkillsText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.15f), itemList.Content.RectTransform),
|
||||
TextManager.Get("fabricatorinsufficientskills"), textColor: Color.Orange, font: GUIStyle.SubHeadingFont)
|
||||
{
|
||||
{
|
||||
AutoScaleHorizontal = true,
|
||||
CanBeFocused = false
|
||||
};
|
||||
@@ -271,10 +295,14 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
insufficientSkillsText.RectTransform.RepositionChildInHierarchy(itemList.Content.RectTransform.GetChildIndex(firstinSufficient.RectTransform));
|
||||
}
|
||||
else
|
||||
{
|
||||
sufficientSkillsText.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
|
||||
};
|
||||
@@ -593,14 +621,28 @@ namespace Barotrauma.Items.Components
|
||||
float requiredTime = overrideRequiredTime ??
|
||||
(user == null ? selectedItem.RequiredTime : GetRequiredTime(selectedItem, user));
|
||||
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedReqFrame.RectTransform),
|
||||
TextManager.Get("FabricatorRequiredTime") , textColor: ToolBox.GradientLerp(degreeOfSuccess, GUIStyle.Red, Color.Yellow, GUIStyle.Green), font: GUIStyle.SubHeadingFont)
|
||||
if (requiredTime > 0.0f)
|
||||
{
|
||||
AutoScaleHorizontal = true,
|
||||
};
|
||||
|
||||
requiredTimeBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedReqFrame.RectTransform), ToolBox.SecondsToReadableTime(requiredTime),
|
||||
font: GUIStyle.SmallFont);
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedReqFrame.RectTransform),
|
||||
TextManager.Get("FabricatorRequiredTime") , textColor: ToolBox.GradientLerp(degreeOfSuccess, GUIStyle.Red, Color.Yellow, GUIStyle.Green), font: GUIStyle.SubHeadingFont)
|
||||
{
|
||||
AutoScaleHorizontal = true,
|
||||
};
|
||||
requiredTimeBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedReqFrame.RectTransform), ToolBox.SecondsToReadableTime(requiredTime),
|
||||
font: GUIStyle.SmallFont);
|
||||
}
|
||||
|
||||
if (SelectedItem.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)
|
||||
{
|
||||
AutoScaleHorizontal = true,
|
||||
};
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedReqFrame.RectTransform), TextManager.FormatCurrency(SelectedItem.RequiredMoney),
|
||||
font: GUIStyle.SmallFont);
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -34,6 +34,13 @@ namespace Barotrauma.Items.Components
|
||||
[Serialize("0.5,0.5)", IsPropertySaveable.No)]
|
||||
public Vector2 Origin { get; set; } = new Vector2(0.5f, 0.5f);
|
||||
|
||||
[Serialize(true, IsPropertySaveable.No, description: "")]
|
||||
public bool BreakFromMiddle
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public Vector2 DrawSize
|
||||
{
|
||||
get
|
||||
@@ -124,9 +131,14 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
int width = (int)(SpriteWidth * snapState);
|
||||
if (width > 0.0f)
|
||||
{
|
||||
DrawRope(spriteBatch, endPos - diff * snapState * 0.5f, endPos, width);
|
||||
DrawRope(spriteBatch, startPos, startPos + diff * snapState * 0.5f, width);
|
||||
{
|
||||
float positionMultiplier = snapState;
|
||||
if (BreakFromMiddle)
|
||||
{
|
||||
positionMultiplier /= 2;
|
||||
DrawRope(spriteBatch, endPos - diff * positionMultiplier, endPos, width);
|
||||
}
|
||||
DrawRope(spriteBatch, startPos, startPos + diff * positionMultiplier, width);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -143,7 +155,7 @@ namespace Barotrauma.Items.Components
|
||||
float depth = Math.Min(item.GetDrawDepth() + (startSprite.Depth - item.Sprite.Depth), 0.999f);
|
||||
startSprite?.Draw(spriteBatch, startPos, SpriteColor, angle, depth: depth);
|
||||
}
|
||||
if (endSprite != null)
|
||||
if (endSprite != null && (!Snapped || BreakFromMiddle))
|
||||
{
|
||||
float depth = Math.Min(item.GetDrawDepth() + (endSprite.Depth - item.Sprite.Depth), 0.999f);
|
||||
endSprite?.Draw(spriteBatch, endPos, SpriteColor, angle, depth: depth);
|
||||
|
||||
@@ -1846,7 +1846,7 @@ namespace Barotrauma
|
||||
yield return CoroutineStatus.Success;
|
||||
}
|
||||
|
||||
private void ApplyReceivedState()
|
||||
public void ApplyReceivedState()
|
||||
{
|
||||
if (receivedItemIDs == null || (Owner != null && Owner.Removed)) { return; }
|
||||
|
||||
|
||||
@@ -1198,9 +1198,9 @@ namespace Barotrauma
|
||||
Color color = Color.Gray;
|
||||
if (ic.HasRequiredItems(character, false))
|
||||
{
|
||||
if (ic is Repairable)
|
||||
if (ic is Repairable r)
|
||||
{
|
||||
if (!IsFullCondition) { color = Color.Cyan; }
|
||||
if (r.IsBelowRepairThreshold) { color = Color.Cyan; }
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -173,7 +173,7 @@ namespace Barotrauma
|
||||
|
||||
int groupID = 0;
|
||||
DecorativeSprite decorativeSprite = null;
|
||||
if (subElement.Attribute("texture") == null)
|
||||
if (subElement.GetAttribute("texture") == null)
|
||||
{
|
||||
groupID = subElement.GetAttributeInt("randomgroupid", 0);
|
||||
}
|
||||
|
||||
@@ -370,6 +370,7 @@ namespace Barotrauma.MapCreatures.Behavior
|
||||
private BallastFloraBranch ReadBranch(IReadMessage msg)
|
||||
{
|
||||
int id = msg.ReadInt32();
|
||||
bool isRootGrowth = msg.ReadBoolean();
|
||||
byte type = (byte)msg.ReadRangedInteger(0b0000, 0b1111);
|
||||
byte sides = (byte)msg.ReadRangedInteger(0b0000, 0b1111);
|
||||
int flowerConfig = msg.ReadRangedInteger(0, 0xFFF);
|
||||
@@ -385,7 +386,8 @@ namespace Barotrauma.MapCreatures.Behavior
|
||||
{
|
||||
ID = id,
|
||||
MaxHealth = maxHealth,
|
||||
Sides = (TileSide) sides
|
||||
Sides = (TileSide) sides,
|
||||
IsRootGrowth = isRootGrowth
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -217,8 +217,8 @@ namespace Barotrauma
|
||||
Vector2 mapTileSize = mapTile.size * generationParams.MapTileScale;
|
||||
int startX = (int)Math.Max(Math.Floor(location.MapPosition.X / mapTileSize.X - 0.25f), 0);
|
||||
int startY = (int)Math.Max(Math.Floor(location.MapPosition.Y / mapTileSize.Y - 0.25f), 0);
|
||||
int endX = (int)Math.Min(Math.Floor(location.MapPosition.X / mapTileSize.X + 0.25f), mapTiles.GetLength(0));
|
||||
int endY = (int)Math.Min(Math.Floor(location.MapPosition.Y / mapTileSize.Y + 0.25f), mapTiles.GetLength(1));
|
||||
int endX = (int)Math.Min(Math.Floor(location.MapPosition.X / mapTileSize.X + 0.25f), mapTiles.GetLength(0) - 1);
|
||||
int endY = (int)Math.Min(Math.Floor(location.MapPosition.Y / mapTileSize.Y + 0.25f), mapTiles.GetLength(1) - 1);
|
||||
for (int x = startX; x <= endX; x++)
|
||||
{
|
||||
for (int y = startY; y <= endY; y++)
|
||||
@@ -451,7 +451,7 @@ namespace Barotrauma
|
||||
SelectLocation(-1);
|
||||
if (GameMain.Client == null)
|
||||
{
|
||||
CurrentLocation.CreateStore();
|
||||
CurrentLocation.CreateStores();
|
||||
ProgressWorld();
|
||||
Radiation?.OnStep(1);
|
||||
}
|
||||
|
||||
@@ -272,11 +272,7 @@ namespace Barotrauma
|
||||
|
||||
private GUIComponent CreateEditingHUD()
|
||||
{
|
||||
int width = 500;
|
||||
int height = spawnType == SpawnType.Path ? 80 : 200;
|
||||
int x = GameMain.GraphicsWidth / 2 - width / 2, y = 30;
|
||||
|
||||
editingHUD = new GUIFrame(new RectTransform(new Point(width, height), GUI.Canvas) { ScreenSpaceOffset = new Point(x, y) })
|
||||
editingHUD = new GUIFrame(new RectTransform(new Vector2(0.3f, 0.15f), GUI.Canvas, Anchor.CenterRight) { MinSize = new Point(400, 0) })
|
||||
{
|
||||
UserData = this
|
||||
};
|
||||
@@ -284,7 +280,7 @@ namespace Barotrauma
|
||||
var paddedFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.85f), editingHUD.RectTransform, Anchor.Center))
|
||||
{
|
||||
Stretch = true,
|
||||
RelativeSpacing = 0.05f
|
||||
AbsoluteSpacing = (int)(GUI.Scale * 5)
|
||||
};
|
||||
|
||||
if (spawnType == SpawnType.Path)
|
||||
@@ -418,6 +414,10 @@ namespace Barotrauma
|
||||
};
|
||||
}
|
||||
|
||||
editingHUD.RectTransform.Resize(new Point(
|
||||
editingHUD.Rect.Width,
|
||||
(int)(paddedFrame.Children.Sum(c => c.Rect.Height + paddedFrame.AbsoluteSpacing) / paddedFrame.RectTransform.RelativeSize.Y)));
|
||||
|
||||
PositionEditingHUD();
|
||||
|
||||
return editingHUD;
|
||||
|
||||
@@ -155,8 +155,13 @@ namespace Barotrauma.Networking
|
||||
Dispose(true);
|
||||
}
|
||||
}
|
||||
|
||||
const int MaxFileSize = 50000000; //50 MB
|
||||
|
||||
private static int GetMaxFileSizeInBytes(FileTransferType fileTransferType) =>
|
||||
fileTransferType switch
|
||||
{
|
||||
FileTransferType.Mod => 500 * 1024 * 1024, //500 MiB should be good enough, right?
|
||||
_ => 50 * 1024 * 1024 //50 MiB for everything other than mods
|
||||
};
|
||||
|
||||
public delegate void TransferInDelegate(FileTransferIn fileStreamReceiver);
|
||||
public TransferInDelegate OnFinished;
|
||||
@@ -410,18 +415,18 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
errorMessage = "";
|
||||
|
||||
if (fileSize > MaxFileSize)
|
||||
{
|
||||
errorMessage = "File too large (" + MathUtils.GetBytesReadable(fileSize) + ")";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Enum.IsDefined(typeof(FileTransferType), (int)type))
|
||||
{
|
||||
errorMessage = "Unknown file type";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (fileSize > GetMaxFileSizeInBytes((FileTransferType)type))
|
||||
{
|
||||
errorMessage = $"File too large ({MathUtils.GetBytesReadable(fileSize)} > {MathUtils.GetBytesReadable(GetMaxFileSizeInBytes((FileTransferType)type))})";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(fileName) ||
|
||||
fileName.IndexOfAny(Path.GetInvalidFileNameChars().ToArray()) > -1)
|
||||
{
|
||||
|
||||
@@ -163,16 +163,11 @@ namespace Barotrauma.Networking
|
||||
|
||||
public static void ChangeCaptureDevice(string deviceName)
|
||||
{
|
||||
var config = GameSettings.CurrentConfig;
|
||||
config.Audio.VoiceCaptureDevice = deviceName;
|
||||
GameSettings.SetCurrentConfig(config);
|
||||
if (Instance == null) { return; }
|
||||
|
||||
if (Instance != null)
|
||||
{
|
||||
UInt16 storedBufferID = Instance.LatestBufferID;
|
||||
Instance.Dispose();
|
||||
Create(GameSettings.CurrentConfig.Audio.VoiceCaptureDevice, storedBufferID);
|
||||
}
|
||||
UInt16 storedBufferID = Instance.LatestBufferID;
|
||||
Instance.Dispose();
|
||||
Create(GameSettings.CurrentConfig.Audio.VoiceCaptureDevice, storedBufferID);
|
||||
}
|
||||
|
||||
IntPtr nativeBuffer;
|
||||
|
||||
@@ -54,7 +54,17 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
else
|
||||
{
|
||||
if (VoipCapture.Instance == null) { VoipCapture.Create(GameSettings.CurrentConfig.Audio.VoiceCaptureDevice, storedBufferID); }
|
||||
try
|
||||
{
|
||||
if (VoipCapture.Instance == null) { VoipCapture.Create(GameSettings.CurrentConfig.Audio.VoiceCaptureDevice, storedBufferID); }
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
DebugConsole.ThrowError($"VoipCature.Create failed: {e.Message} {e.StackTrace.CleanupStackTrace()}");
|
||||
var config = GameSettings.CurrentConfig;
|
||||
config.Audio.VoiceSetting = VoiceMode.Disabled;
|
||||
GameSettings.SetCurrentConfig(config);
|
||||
}
|
||||
if (VoipCapture.Instance == null || VoipCapture.Instance.EnqueuedTotalLength <= 0) { return; }
|
||||
}
|
||||
|
||||
@@ -146,7 +156,7 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
var soundIconStyle = GUIStyle.GetComponentStyle("GUISoundIcon");
|
||||
Rectangle sourceRect = soundIconStyle.Sprites.First().Value.First().Sprite.SourceRect;
|
||||
var indexPieces = soundIconStyle.Element.Attribute("sheetindices").Value.Split(';');
|
||||
var indexPieces = soundIconStyle.Element.GetAttribute("sheetindices").Value.Split(';');
|
||||
voiceIconSheetRects = new Rectangle[indexPieces.Length];
|
||||
for (int i = 0; i < indexPieces.Length; i++)
|
||||
{
|
||||
|
||||
@@ -242,30 +242,30 @@ namespace Barotrauma.Particles
|
||||
}
|
||||
|
||||
//if velocity change in water is not given, it defaults to the normal velocity change
|
||||
if (element.Attribute("velocitychangewater") == null)
|
||||
if (element.GetAttribute("velocitychangewater") == null)
|
||||
{
|
||||
VelocityChangeWater = VelocityChange;
|
||||
}
|
||||
|
||||
if (element.Attribute("angularvelocity") != null)
|
||||
if (element.GetAttribute("angularvelocity") != null)
|
||||
{
|
||||
AngularVelocityMin = element.GetAttributeFloat("angularvelocity", 0.0f);
|
||||
AngularVelocityMax = AngularVelocityMin;
|
||||
}
|
||||
|
||||
if (element.Attribute("startsize") != null)
|
||||
if (element.GetAttribute("startsize") != null)
|
||||
{
|
||||
StartSizeMin = element.GetAttributeVector2("startsize", Vector2.One);
|
||||
StartSizeMax = StartSizeMin;
|
||||
}
|
||||
|
||||
if (element.Attribute("sizechange") != null)
|
||||
if (element.GetAttribute("sizechange") != null)
|
||||
{
|
||||
SizeChangeMin = element.GetAttributeVector2("sizechange", Vector2.Zero);
|
||||
SizeChangeMax = SizeChangeMin;
|
||||
}
|
||||
|
||||
if (element.Attribute("startrotation") != null)
|
||||
if (element.GetAttribute("startrotation") != null)
|
||||
{
|
||||
StartRotationMin = element.GetAttributeFloat("startrotation", 0.0f);
|
||||
StartRotationMax = StartRotationMin;
|
||||
|
||||
@@ -680,7 +680,7 @@ namespace Barotrauma
|
||||
//locationInfoPanel?.UpdateAuto(1.0f);
|
||||
}
|
||||
|
||||
public void SelectTab(CampaignMode.InteractionType tab)
|
||||
public void SelectTab(CampaignMode.InteractionType tab, Identifier storeIdentifier = default)
|
||||
{
|
||||
if (Campaign.ShowCampaignUI || (Campaign.ForceMapUI && tab == CampaignMode.InteractionType.Map))
|
||||
{
|
||||
@@ -724,8 +724,7 @@ namespace Barotrauma
|
||||
}
|
||||
break;
|
||||
case CampaignMode.InteractionType.Store:
|
||||
Store.RefreshItemsToSell();
|
||||
Store.Refresh();
|
||||
Store.SelectStore(storeIdentifier);
|
||||
break;
|
||||
case CampaignMode.InteractionType.Crew:
|
||||
CrewManagement.UpdateCrew();
|
||||
|
||||
+2
-1
@@ -2805,7 +2805,8 @@ namespace Barotrauma.CharacterEditor
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
if (!character.IsHuman && !string.IsNullOrEmpty(RagdollParams.Texture) && !File.Exists(RagdollParams.Texture))
|
||||
ContentPath texturePath = ContentPath.FromRaw(character.Prefab.ContentPackage, RagdollParams.Texture);
|
||||
if (!character.IsHuman && (texturePath.IsNullOrWhiteSpace() || !File.Exists(texturePath.Value)))
|
||||
{
|
||||
DebugConsole.ThrowError($"Invalid texture path: {RagdollParams.Texture}");
|
||||
return false;
|
||||
|
||||
@@ -248,18 +248,24 @@ namespace Barotrauma
|
||||
}
|
||||
spriteBatch.End();
|
||||
|
||||
//draw characters with deformable limbs last, because they can't be batched into SpriteBatch
|
||||
//pretty hacky way of preventing draw order issues between normal and deformable sprites
|
||||
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied, null, DepthStencilState.None, null, null, cam.Transform);
|
||||
//backwards order to render the most recently spawned characters in front (characters spawned later have a larger sprite depth)
|
||||
for (int i = Character.CharacterList.Count - 1; i >= 0; i--)
|
||||
{
|
||||
Character c = Character.CharacterList[i];
|
||||
if (!c.IsVisible || c.AnimController.Limbs.All(l => l.DeformSprite == null)) { continue; }
|
||||
c.Draw(spriteBatch, Cam);
|
||||
}
|
||||
DrawDeformed(firstPass: true);
|
||||
DrawDeformed(firstPass: false);
|
||||
spriteBatch.End();
|
||||
|
||||
void DrawDeformed(bool firstPass)
|
||||
{
|
||||
//backwards order to render the most recently spawned characters in front (characters spawned later have a larger sprite depth)
|
||||
for (int i = Character.CharacterList.Count - 1; i >= 0; i--)
|
||||
{
|
||||
Character c = Character.CharacterList[i];
|
||||
if (!c.IsVisible) { continue; }
|
||||
if (c.Params.DrawLast == firstPass) { continue; }
|
||||
if (c.AnimController.Limbs.All(l => l.DeformSprite == null)) { continue; }
|
||||
c.Draw(spriteBatch, Cam);
|
||||
}
|
||||
}
|
||||
|
||||
Level.Loaded?.DrawFront(spriteBatch, cam);
|
||||
|
||||
//draw the rendertarget and particles that are only supposed to be drawn in water into renderTargetWater
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace Barotrauma
|
||||
|
||||
private readonly GUITextBox seedBox;
|
||||
|
||||
private readonly GUITickBox lightingEnabled, cursorLightEnabled, mirrorLevel;
|
||||
private readonly GUITickBox lightingEnabled, cursorLightEnabled, allowInvalidOutpost, mirrorLevel;
|
||||
|
||||
private Sprite editingSprite;
|
||||
|
||||
@@ -126,6 +126,7 @@ namespace Barotrauma
|
||||
OnClicked = (btn, obj) =>
|
||||
{
|
||||
SerializeAll();
|
||||
GUI.AddMessage(TextManager.Get("leveleditor.allsaved"), GUIStyle.Green);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@@ -169,6 +170,12 @@ namespace Barotrauma
|
||||
|
||||
mirrorLevel = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.02f), paddedRightPanel.RectTransform), TextManager.Get("mirrorentityx"));
|
||||
|
||||
allowInvalidOutpost = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.025f), paddedRightPanel.RectTransform),
|
||||
TextManager.Get("leveleditor.allowinvalidoutpost"))
|
||||
{
|
||||
ToolTip = TextManager.Get("leveleditor.allowinvalidoutpost.tooltip")
|
||||
};
|
||||
|
||||
new GUIButton(new RectTransform(new Vector2(1.0f, 0.05f), paddedRightPanel.RectTransform),
|
||||
TextManager.Get("leveleditor.generate"))
|
||||
{
|
||||
@@ -179,6 +186,7 @@ namespace Barotrauma
|
||||
GameMain.LightManager.ClearLights();
|
||||
LevelData levelData = LevelData.CreateRandom(seedBox.Text, generationParams: selectedParams);
|
||||
levelData.ForceOutpostGenerationParams = outpostParamsList.SelectedData as OutpostGenerationParams;
|
||||
levelData.AllowInvalidOutpost = allowInvalidOutpost.Selected;
|
||||
Level.Generate(levelData, mirror: mirrorLevel.Selected);
|
||||
GameMain.LightManager.AddLight(pointerLightSource);
|
||||
if (!wasLevelLoaded || Cam.Position.X < 0 || Cam.Position.Y < 0 || Cam.Position.Y > Level.Loaded.Size.X || Cam.Position.Y > Level.Loaded.Size.Y)
|
||||
|
||||
@@ -46,6 +46,7 @@ namespace Barotrauma
|
||||
|
||||
private GUITextBox serverNameBox, passwordBox, maxPlayersBox;
|
||||
private GUITickBox isPublicBox, wrongPasswordBanBox, karmaBox;
|
||||
private GUIDropDown serverExecutableDropdown;
|
||||
private readonly GUIButton joinServerButton, hostServerButton, steamWorkshopButton;
|
||||
private readonly GameMain game;
|
||||
|
||||
@@ -418,7 +419,14 @@ namespace Barotrauma
|
||||
//PLACEHOLDER
|
||||
var tutorialList = new GUIListBox(
|
||||
new RectTransform(new Vector2(0.95f, 0.85f), menuTabs[Tab.Tutorials].RectTransform, Anchor.TopCenter) { RelativeOffset = new Vector2(0.0f, 0.1f) });
|
||||
var tutorialTypes = ReflectionUtils.GetDerivedNonAbstract<Tutorial>();
|
||||
var tutorialTypes = new List<Type>()
|
||||
{
|
||||
typeof(MechanicTutorial),
|
||||
typeof(EngineerTutorial),
|
||||
typeof(DoctorTutorial),
|
||||
typeof(OfficerTutorial),
|
||||
typeof(CaptainTutorial),
|
||||
};
|
||||
foreach (Type tutorialType in tutorialTypes)
|
||||
{
|
||||
Tutorial tutorial = (Tutorial)Activator.CreateInstance(tutorialType);
|
||||
@@ -557,6 +565,35 @@ namespace Barotrauma
|
||||
GameMain.Instance.ShowCampaignDisclaimer(() => { SelectTab(null, Tab.HostServer); });
|
||||
return true;
|
||||
}
|
||||
|
||||
serverExecutableDropdown.ListBox.Content.Children.ToArray()
|
||||
.Where(c => c.UserData is ServerExecutableFile f && !ContentPackageManager.EnabledPackages.All.Contains(f.ContentPackage))
|
||||
.ForEach(serverExecutableDropdown.ListBox.RemoveChild);
|
||||
var newServerExes
|
||||
= ContentPackageManager.EnabledPackages.All.SelectMany(p => p.GetFiles<ServerExecutableFile>())
|
||||
.Where(f => serverExecutableDropdown.ListBox.Content.Children.None(c => c.UserData == f))
|
||||
.ToArray();
|
||||
foreach (var newServerExe in newServerExes)
|
||||
{
|
||||
serverExecutableDropdown.AddItem($"{newServerExe.ContentPackage.Name} - {Path.GetFileNameWithoutExtension(newServerExe.Path.Value)}", userData: newServerExe);
|
||||
}
|
||||
serverExecutableDropdown.ListBox.Content.Children.ForEach(c =>
|
||||
{
|
||||
c.RectTransform.RelativeSize = (1.0f, c.RectTransform.RelativeSize.Y);
|
||||
c.ForceLayoutRecalculation();
|
||||
});
|
||||
bool serverExePickable = serverExecutableDropdown.ListBox.Content.CountChildren > 1;
|
||||
serverExecutableDropdown.Parent.Visible
|
||||
= serverExePickable;
|
||||
serverExecutableDropdown.Parent.RectTransform.RelativeSize
|
||||
= (1.0f, serverExePickable ? 0.1f : 0.0f);
|
||||
serverExecutableDropdown.Parent.ForceLayoutRecalculation();
|
||||
(serverExecutableDropdown.Parent.Parent as GUILayoutGroup)?.Recalculate();
|
||||
if (serverExecutableDropdown.SelectedComponent is null)
|
||||
{
|
||||
serverExecutableDropdown.Select(0);
|
||||
}
|
||||
|
||||
break;
|
||||
case Tab.Tutorials:
|
||||
if (!GameSettings.CurrentConfig.CampaignDisclaimerShown)
|
||||
@@ -784,7 +821,7 @@ namespace Barotrauma
|
||||
GameMain.ResetNetLobbyScreen();
|
||||
try
|
||||
{
|
||||
string exeName = "DedicatedServer.exe";
|
||||
string exeName = serverExecutableDropdown.SelectedComponent?.UserData is ServerExecutableFile f ? f.Path.Value : "DedicatedServer";
|
||||
|
||||
string arguments = "-name \"" + ToolBox.EscapeCharacters(name) + "\"" +
|
||||
" -public " + isPublicBox.Selected.ToString() +
|
||||
@@ -814,15 +851,20 @@ namespace Barotrauma
|
||||
arguments += " -ownerkey " + ownerKey;
|
||||
}
|
||||
|
||||
string filename = exeName;
|
||||
#if LINUX || OSX
|
||||
filename = "./" + Path.GetFileNameWithoutExtension(exeName);
|
||||
//arguments = ToolBox.EscapeCharacters(arguments);
|
||||
string filename = Path.Combine(
|
||||
Path.GetDirectoryName(exeName),
|
||||
Path.GetFileNameWithoutExtension(exeName));
|
||||
#if WINDOWS
|
||||
filename += ".exe";
|
||||
#else
|
||||
filename = "./" + exeName;
|
||||
#endif
|
||||
|
||||
var processInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = filename,
|
||||
Arguments = arguments,
|
||||
WorkingDirectory = Directory.GetCurrentDirectory(),
|
||||
#if !DEBUG
|
||||
CreateNoWindow = true,
|
||||
UseShellExecute = false,
|
||||
@@ -1184,12 +1226,12 @@ namespace Barotrauma
|
||||
label.RectTransform.MaxSize = serverNameBox.RectTransform.MaxSize;
|
||||
|
||||
var maxPlayersLabel = new GUITextBlock(new RectTransform(textLabelSize, parent.RectTransform), TextManager.Get("MaxPlayers"), textAlignment: textAlignment);
|
||||
var buttonContainer = new GUILayoutGroup(new RectTransform(textFieldSize, maxPlayersLabel.RectTransform, Anchor.CenterRight), isHorizontal: true)
|
||||
var buttonContainer = new GUILayoutGroup(new RectTransform(textFieldSize, maxPlayersLabel.RectTransform, Anchor.CenterRight), isHorizontal: true, childAnchor: Anchor.CenterLeft)
|
||||
{
|
||||
Stretch = true,
|
||||
RelativeSpacing = 0.1f
|
||||
};
|
||||
new GUIButton(new RectTransform(new Vector2(0.2f, 1.0f), buttonContainer.RectTransform, scaleBasis: ScaleBasis.BothHeight), style: "GUIMinusButton", textAlignment: Alignment.Center)
|
||||
new GUIButton(new RectTransform(Vector2.One, buttonContainer.RectTransform, scaleBasis: ScaleBasis.BothHeight), style: "GUIMinusButton", textAlignment: Alignment.Center)
|
||||
{
|
||||
UserData = -1,
|
||||
OnClicked = ChangeMaxPlayers
|
||||
@@ -1209,7 +1251,7 @@ namespace Barotrauma
|
||||
currMaxPlayers = (int)MathHelper.Clamp(currMaxPlayers, 1, NetConfig.MaxPlayers);
|
||||
maxPlayersBox.Text = currMaxPlayers.ToString();
|
||||
};
|
||||
new GUIButton(new RectTransform(new Vector2(0.2f, 1.0f), buttonContainer.RectTransform, scaleBasis: ScaleBasis.BothHeight), style: "GUIPlusButton", textAlignment: Alignment.Center)
|
||||
new GUIButton(new RectTransform(Vector2.One, buttonContainer.RectTransform, scaleBasis: ScaleBasis.BothHeight), style: "GUIPlusButton", textAlignment: Alignment.Center)
|
||||
{
|
||||
UserData = 1,
|
||||
OnClicked = ChangeMaxPlayers
|
||||
@@ -1223,6 +1265,41 @@ namespace Barotrauma
|
||||
};
|
||||
label.RectTransform.MaxSize = passwordBox.RectTransform.MaxSize;
|
||||
|
||||
var serverExecutableLabel = new GUITextBlock(new RectTransform(textLabelSize, parent.RectTransform),
|
||||
TextManager.Get("ServerExecutable"), textAlignment: textAlignment);
|
||||
const string vanillaServerOption = "Vanilla";
|
||||
serverExecutableDropdown
|
||||
= new GUIDropDown(new RectTransform(textFieldSize, serverExecutableLabel.RectTransform, Anchor.CenterRight),
|
||||
vanillaServerOption);
|
||||
var listBoxSize = serverExecutableDropdown.ListBox.RectTransform.RelativeSize;
|
||||
serverExecutableDropdown.ListBox.RectTransform.RelativeSize = new Vector2(listBoxSize.X * 1.5f, listBoxSize.Y);
|
||||
serverExecutableDropdown.AddItem(vanillaServerOption, userData: null);
|
||||
serverExecutableDropdown.OnSelected = (selected, userData) =>
|
||||
{
|
||||
if (userData != null)
|
||||
{
|
||||
var warningBox = new GUIMessageBox(headerText: TextManager.Get("Warning"),
|
||||
text: TextManager.GetWithVariable("ModServerExesAtYourOwnRisk", "[exename]", serverExecutableDropdown.Text),
|
||||
new LocalizedString[] { TextManager.Get("Yes"), TextManager.Get("No") });
|
||||
warningBox.Buttons[0].OnClicked = (_, __) =>
|
||||
{
|
||||
warningBox.Close();
|
||||
return false;
|
||||
};
|
||||
warningBox.Buttons[1].OnClicked = (_, __) =>
|
||||
{
|
||||
serverExecutableDropdown.Select(0);
|
||||
warningBox.Close();
|
||||
return false;
|
||||
};
|
||||
}
|
||||
|
||||
serverExecutableDropdown.Text = ToolBox.LimitString(serverExecutableDropdown.Text,
|
||||
serverExecutableDropdown.Font, serverExecutableDropdown.Rect.Width * 8 / 10);
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
// tickbox upper ---------------
|
||||
|
||||
var tickboxAreaUpper = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, tickBoxSize.Y), parent.RectTransform), isHorizontal: true);
|
||||
@@ -1312,8 +1389,8 @@ namespace Barotrauma
|
||||
{
|
||||
var client = new RestClient(RemoteContentUrl);
|
||||
var request = new RestRequest("MenuContent.xml", Method.GET);
|
||||
client.ExecuteAsync(request, RemoteContentReceived);
|
||||
CoroutineManager.StartCoroutine(WairForRemoteContentReceived());
|
||||
TaskPool.Add("RequestMainMenuRemoteContent", client.ExecuteAsync(request),
|
||||
RemoteContentReceived);
|
||||
}
|
||||
|
||||
catch (Exception e)
|
||||
@@ -1327,58 +1404,31 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerable<CoroutineStatus> WairForRemoteContentReceived()
|
||||
private void RemoteContentReceived(Task t)
|
||||
{
|
||||
while (true)
|
||||
try
|
||||
{
|
||||
lock (remoteContentLock)
|
||||
if (!t.TryGetResult(out IRestResponse remoteContentResponse)) { throw new Exception("Task did not return a valid result"); }
|
||||
string xml = remoteContentResponse.Content;
|
||||
int index = xml.IndexOf('<');
|
||||
if (index > 0) { xml = xml.Substring(index, xml.Length - index); }
|
||||
if (!string.IsNullOrWhiteSpace(xml))
|
||||
{
|
||||
if (remoteContentResponse != null) { break; }
|
||||
}
|
||||
yield return new WaitForSeconds(0.1f);
|
||||
}
|
||||
lock (remoteContentLock)
|
||||
{
|
||||
if (remoteContentResponse.ResponseStatus != ResponseStatus.Completed || remoteContentResponse.StatusCode != HttpStatusCode.OK)
|
||||
{
|
||||
yield return CoroutineStatus.Success;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
string xml = remoteContentResponse.Content;
|
||||
int index = xml.IndexOf('<');
|
||||
if (index > 0) { xml = xml.Substring(index, xml.Length - index); }
|
||||
if (!string.IsNullOrWhiteSpace(xml))
|
||||
remoteContentDoc = XDocument.Parse(xml);
|
||||
foreach (var subElement in remoteContentDoc?.Root.Elements())
|
||||
{
|
||||
remoteContentDoc = XDocument.Parse(xml);
|
||||
foreach (var subElement in remoteContentDoc?.Root.Elements())
|
||||
{
|
||||
GUIComponent.FromXML(subElement.FromPackage(null), remoteContentContainer.RectTransform);
|
||||
}
|
||||
GUIComponent.FromXML(subElement.FromPackage(null), remoteContentContainer.RectTransform);
|
||||
}
|
||||
}
|
||||
|
||||
catch (Exception e)
|
||||
{
|
||||
#if DEBUG
|
||||
DebugConsole.ThrowError("Reading received remote main menu content failed.", e);
|
||||
#endif
|
||||
GameAnalyticsManager.AddErrorEventOnce("MainMenuScreen.WairForRemoteContentReceived:Exception", GameAnalyticsManager.ErrorSeverity.Error,
|
||||
"Reading received remote main menu content failed. " + e.Message);
|
||||
}
|
||||
}
|
||||
yield return CoroutineStatus.Success;
|
||||
}
|
||||
|
||||
private readonly object remoteContentLock = new object();
|
||||
private IRestResponse remoteContentResponse;
|
||||
|
||||
private void RemoteContentReceived(IRestResponse response, RestRequestAsyncHandle handle)
|
||||
{
|
||||
lock (remoteContentLock)
|
||||
catch (Exception e)
|
||||
{
|
||||
remoteContentResponse = response;
|
||||
#if DEBUG
|
||||
DebugConsole.ThrowError("Reading received remote main menu content failed.", e);
|
||||
#endif
|
||||
GameAnalyticsManager.AddErrorEventOnce("MainMenuScreen.RemoteContentReceived:Exception", GameAnalyticsManager.ErrorSeverity.Error,
|
||||
"Reading received remote main menu content failed. " + e.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Barotrauma.Extensions;
|
||||
using Barotrauma.IO;
|
||||
using Barotrauma.Networking;
|
||||
using Microsoft.Xna.Framework;
|
||||
@@ -29,10 +30,19 @@ namespace Barotrauma
|
||||
currentDownload = null;
|
||||
confirmDownload = false;
|
||||
}
|
||||
|
||||
private void DeletePrevDownloads()
|
||||
{
|
||||
if (Directory.Exists(ModReceiver.DownloadFolder))
|
||||
{
|
||||
Directory.Delete(ModReceiver.DownloadFolder, recursive: true);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Select()
|
||||
{
|
||||
base.Select();
|
||||
DeletePrevDownloads();
|
||||
Reset();
|
||||
|
||||
Frame.ClearChildren();
|
||||
@@ -67,6 +77,18 @@ namespace Barotrauma
|
||||
.Where(sp => sp.ContentPackage is null).ToArray();
|
||||
if (!missingPackages.Any())
|
||||
{
|
||||
if (!GameMain.Client.IsServerOwner)
|
||||
{
|
||||
ContentPackageManager.EnabledPackages.BackUp();
|
||||
ContentPackageManager.EnabledPackages.SetCore(
|
||||
GameMain.Client.ClientPeer.ServerContentPackages
|
||||
.Select(p => p.CorePackage)
|
||||
.First(p => p != null));
|
||||
ContentPackageManager.EnabledPackages.SetRegular(
|
||||
GameMain.Client.ClientPeer.ServerContentPackages
|
||||
.Select(p => p.RegularPackage)
|
||||
.Where(p => p != null).ToArray());
|
||||
}
|
||||
GameMain.NetLobbyScreen.Select();
|
||||
return;
|
||||
}
|
||||
@@ -201,7 +223,7 @@ namespace Barotrauma
|
||||
|
||||
if (!pendingDownloads.Contains(p))
|
||||
{
|
||||
downloadProgress.ClearChildren();
|
||||
downloadProgress.GetAllChildren<GUITextBlock>().ToArray().ForEach(c => downloadProgress.RemoveChild(c));
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
|
||||
@@ -3786,7 +3786,7 @@ namespace Barotrauma
|
||||
RelativeSpacing = 0.02f
|
||||
};
|
||||
|
||||
var dragIndicator = new GUIButton(new RectTransform(new Vector2(0.1f, 0.5f), frameContent.RectTransform, scaleBasis: ScaleBasis.BothHeight),
|
||||
var dragIndicator = new GUIButton(new RectTransform(new Vector2(0.5f, 0.5f), frameContent.RectTransform, scaleBasis: ScaleBasis.BothHeight),
|
||||
style: "GUIDragIndicator")
|
||||
{
|
||||
CanBeFocused = false
|
||||
|
||||
@@ -380,7 +380,7 @@ namespace Barotrauma
|
||||
string spriteFolder = "";
|
||||
ContentPath texturePath = null;
|
||||
|
||||
if (element.Attribute("texture") != null)
|
||||
if (element.GetAttribute("texture") != null)
|
||||
{
|
||||
texturePath = element.GetAttributeContentPath("texture");
|
||||
}
|
||||
|
||||
@@ -9,11 +9,7 @@ using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Xml.Linq;
|
||||
using Microsoft.Xna.Framework.Input;
|
||||
#if DEBUG
|
||||
using System.IO;
|
||||
#else
|
||||
using Barotrauma.IO;
|
||||
#endif
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
@@ -1262,7 +1258,9 @@ namespace Barotrauma
|
||||
}
|
||||
textBlock.Text = ToolBox.LimitString(textBlock.Text, textBlock.Font, textBlock.Rect.Width);
|
||||
|
||||
if (ep.Category == MapEntityCategory.ItemAssembly)
|
||||
if (ep.Category == MapEntityCategory.ItemAssembly
|
||||
&& ep.ContentPackage?.Files.Length == 1
|
||||
&& ContentPackageManager.LocalPackages.Contains(ep.ContentPackage))
|
||||
{
|
||||
var deleteButton = new GUIButton(new RectTransform(new Vector2(1.0f, 0.2f), paddedFrame.RectTransform, Anchor.BottomCenter) { MinSize = new Point(0, 20) },
|
||||
TextManager.Get("Delete"), style: "GUIButtonSmall")
|
||||
@@ -1978,6 +1976,7 @@ namespace Barotrauma
|
||||
if (newPackage is RegularPackage regular)
|
||||
{
|
||||
ContentPackageManager.EnabledPackages.EnableRegular(regular);
|
||||
GameSettings.SaveCurrentConfig();
|
||||
}
|
||||
}
|
||||
SubmarineInfo.RefreshSavedSub(savePath);
|
||||
@@ -2164,12 +2163,12 @@ namespace Barotrauma
|
||||
|
||||
var allowAttachDropDown = new GUIDropDown(new RectTransform(new Vector2(0.5f, 1f), allowAttachGroup.RectTransform),
|
||||
text: LocalizedString.Join(", ", MainSub?.Info?.OutpostModuleInfo?.AllowAttachToModules.Select(s => TextManager.Capitalize(s.Value)) ?? ((LocalizedString)"Any").ToEnumerable()), selectMultiple: true);
|
||||
allowAttachDropDown.AddItem(TextManager.Capitalize("any"), "any");
|
||||
allowAttachDropDown.AddItem(TextManager.Capitalize("any"), "any".ToIdentifier());
|
||||
if (MainSub.Info.OutpostModuleInfo == null ||
|
||||
!MainSub.Info.OutpostModuleInfo.AllowAttachToModules.Any() ||
|
||||
MainSub.Info.OutpostModuleInfo.AllowAttachToModules.All(s => s == "any"))
|
||||
{
|
||||
allowAttachDropDown.SelectItem("any");
|
||||
allowAttachDropDown.SelectItem("any".ToIdentifier());
|
||||
}
|
||||
foreach (Identifier flag in availableFlags)
|
||||
{
|
||||
@@ -2211,7 +2210,7 @@ namespace Barotrauma
|
||||
locationTypeDropDown.SelectItem(locationType);
|
||||
}
|
||||
}
|
||||
if (!MainSub.Info?.OutpostModuleInfo?.AllowedLocationTypes?.Any() ?? true) { locationTypeDropDown.SelectItem("any"); }
|
||||
if (!MainSub.Info?.OutpostModuleInfo?.AllowedLocationTypes?.Any() ?? true) { locationTypeDropDown.SelectItem("any".ToIdentifier()); }
|
||||
|
||||
locationTypeDropDown.OnSelected += (_, __) =>
|
||||
{
|
||||
@@ -2225,9 +2224,7 @@ namespace Barotrauma
|
||||
// gap positions ---------------------
|
||||
|
||||
var gapPositionGroup = new GUILayoutGroup(new RectTransform(new Vector2(.975f, 0.1f), outpostSettingsContainer.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterLeft);
|
||||
|
||||
new GUITextBlock(new RectTransform(new Vector2(0.5f, 1f), gapPositionGroup.RectTransform), TextManager.Get("outpostmodulegappositions"), textAlignment: Alignment.CenterLeft);
|
||||
|
||||
var gapPositionDropDown = new GUIDropDown(new RectTransform(new Vector2(0.5f, 1f), gapPositionGroup.RectTransform),
|
||||
text: "", selectMultiple: true);
|
||||
|
||||
@@ -2238,11 +2235,11 @@ namespace Barotrauma
|
||||
{
|
||||
outpostModuleInfo.DetermineGapPositions(MainSub);
|
||||
}
|
||||
foreach (var gapPos in Enum.GetValues(typeof(OutpostModuleInfo.GapPosition)))
|
||||
foreach (OutpostModuleInfo.GapPosition gapPos in Enum.GetValues(typeof(OutpostModuleInfo.GapPosition)))
|
||||
{
|
||||
if ((OutpostModuleInfo.GapPosition)gapPos == OutpostModuleInfo.GapPosition.None) { continue; }
|
||||
if (gapPos == OutpostModuleInfo.GapPosition.None) { continue; }
|
||||
gapPositionDropDown.AddItem(TextManager.Capitalize(gapPos.ToString()), gapPos);
|
||||
if (outpostModuleInfo.GapPositions.HasFlag((OutpostModuleInfo.GapPosition)gapPos))
|
||||
if (outpostModuleInfo.GapPositions.HasFlag(gapPos))
|
||||
{
|
||||
gapPositionDropDown.SelectItem(gapPos);
|
||||
}
|
||||
@@ -2271,6 +2268,49 @@ namespace Barotrauma
|
||||
};
|
||||
gapPositionGroup.RectTransform.MinSize = new Point(0, gapPositionGroup.RectTransform.Children.Max(c => c.MinSize.Y));
|
||||
|
||||
var canAttachToPrevGroup = new GUILayoutGroup(new RectTransform(new Vector2(.975f, 0.1f), outpostSettingsContainer.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterLeft);
|
||||
new GUITextBlock(new RectTransform(new Vector2(0.5f, 1f), canAttachToPrevGroup.RectTransform), TextManager.Get("canattachtoprevious"), textAlignment: Alignment.CenterLeft)
|
||||
{
|
||||
ToolTip = TextManager.Get("canattachtoprevious.tooltip")
|
||||
};
|
||||
var canAttachToPrevDropDown = new GUIDropDown(new RectTransform(new Vector2(0.5f, 1f), canAttachToPrevGroup.RectTransform),
|
||||
text: "", selectMultiple: true);
|
||||
if (outpostModuleInfo != null)
|
||||
{
|
||||
foreach (OutpostModuleInfo.GapPosition gapPos in Enum.GetValues(typeof(OutpostModuleInfo.GapPosition)))
|
||||
{
|
||||
if (gapPos == OutpostModuleInfo.GapPosition.None) { continue; }
|
||||
canAttachToPrevDropDown.AddItem(TextManager.Capitalize(gapPos.ToString()), gapPos);
|
||||
if (outpostModuleInfo.CanAttachToPrevious.HasFlag(gapPos))
|
||||
{
|
||||
canAttachToPrevDropDown.SelectItem(gapPos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
canAttachToPrevDropDown.OnSelected += (_, __) =>
|
||||
{
|
||||
if (Submarine.MainSub.Info?.OutpostModuleInfo == null) { return false; }
|
||||
Submarine.MainSub.Info.OutpostModuleInfo.CanAttachToPrevious = OutpostModuleInfo.GapPosition.None;
|
||||
if (canAttachToPrevDropDown.SelectedDataMultiple.Any())
|
||||
{
|
||||
List<string> gapPosTexts = new List<string>();
|
||||
foreach (OutpostModuleInfo.GapPosition gapPos in canAttachToPrevDropDown.SelectedDataMultiple)
|
||||
{
|
||||
Submarine.MainSub.Info.OutpostModuleInfo.CanAttachToPrevious |= gapPos;
|
||||
gapPosTexts.Add(TextManager.Capitalize(gapPos.ToString()).Value);
|
||||
}
|
||||
canAttachToPrevDropDown.Text = ToolBox.LimitString(string.Join(", ", gapPosTexts), canAttachToPrevDropDown.Font, canAttachToPrevDropDown.Rect.Width);
|
||||
}
|
||||
else
|
||||
{
|
||||
canAttachToPrevDropDown.Text = ToolBox.LimitString("None", canAttachToPrevDropDown.Font, canAttachToPrevDropDown.Rect.Width);
|
||||
}
|
||||
return true;
|
||||
};
|
||||
canAttachToPrevGroup.RectTransform.MinSize = new Point(0, gapPositionGroup.RectTransform.Children.Max(c => c.MinSize.Y));
|
||||
|
||||
|
||||
// -------------------
|
||||
|
||||
var maxModuleCountGroup = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.5f), outpostSettingsContainer.RectTransform), isHorizontal: true)
|
||||
@@ -2583,7 +2623,18 @@ namespace Barotrauma
|
||||
//don't show content packages that only define submarine files
|
||||
//(it doesn't make sense to require another sub to be installed to install this one)
|
||||
if (contentPack.Files.All(f => f is SubmarineFile)) { continue; }
|
||||
if (!contentPacks.Contains(contentPack.Name)) { contentPacks.Add(contentPack.Name); }
|
||||
|
||||
if (!contentPacks.Contains(contentPack.Name))
|
||||
{
|
||||
string altName = contentPack.AltNames.FirstOrDefault(n => contentPacks.Contains(n));
|
||||
if (!string.IsNullOrEmpty(altName))
|
||||
{
|
||||
MainSub.Info.RequiredContentPackages.Remove(altName);
|
||||
MainSub.Info.RequiredContentPackages.Add(contentPack.Name);
|
||||
contentPacks.Remove(altName);
|
||||
}
|
||||
contentPacks.Add(contentPack.Name);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (string contentPackageName in contentPacks)
|
||||
@@ -2749,11 +2800,7 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
bool hideInMenus = nameBox.Parent.GetChildByUserData("hideinmenus") is GUITickBox hideInMenusTickBox && hideInMenusTickBox.Selected;
|
||||
#if DEBUG
|
||||
string saveFolder = ItemAssemblyPrefab.VanillaSaveFolder;
|
||||
#else
|
||||
string saveFolder = Path.Combine(ContentPackage.LocalModsDir, nameBox.Text);
|
||||
#endif
|
||||
string filePath = Path.Combine(saveFolder, $"{nameBox.Text}.xml").CleanUpPathCrossPlatform();
|
||||
if (File.Exists(filePath))
|
||||
{
|
||||
@@ -2782,26 +2829,27 @@ namespace Barotrauma
|
||||
|
||||
void Save()
|
||||
{
|
||||
XDocument doc = new XDocument(ItemAssemblyPrefab.Save(MapEntity.SelectedList.ToList(), nameBox.Text, descriptionBox.Text, hideInMenus));
|
||||
#if DEBUG
|
||||
doc.Save(filePath);
|
||||
#else
|
||||
doc.SaveSafe(filePath);
|
||||
#endif
|
||||
ContentPackage existingContentPackage = ContentPackageManager.LocalPackages.FirstOrDefault(p => p.Files.Any(f => f.Path == filePath));
|
||||
ContentPackage existingContentPackage = ContentPackageManager.LocalPackages.Regular.FirstOrDefault(p => p.Files.Any(f => f.Path == filePath));
|
||||
if (existingContentPackage == null)
|
||||
{
|
||||
//content package doesn't exist, create one
|
||||
ModProject modProject = new ModProject() { Name = nameBox.Text };
|
||||
var newFile = ModProject.File.FromPath<ItemAssemblyFile>(filePath);
|
||||
var newFile = ModProject.File.FromPath<ItemAssemblyFile>(Path.Combine(ContentPath.ModDirStr, $"{nameBox.Text}.xml"));
|
||||
modProject.AddFile(newFile);
|
||||
ContentPackageManager.LocalPackages.SaveAndEnableRegularMod(modProject);
|
||||
}
|
||||
else
|
||||
{
|
||||
EnqueueForReload(existingContentPackage);
|
||||
string newPackagePath = ContentPackageManager.LocalPackages.SaveRegularMod(modProject);
|
||||
existingContentPackage = ContentPackageManager.LocalPackages.GetRegularModByPath(newPackagePath);
|
||||
}
|
||||
|
||||
XDocument doc = new XDocument(ItemAssemblyPrefab.Save(MapEntity.SelectedList.ToList(), nameBox.Text, descriptionBox.Text, hideInMenus));
|
||||
doc.SaveSafe(filePath);
|
||||
|
||||
var resultPackage = ContentPackageManager.ReloadContentPackage(existingContentPackage) as RegularPackage;
|
||||
if (!ContentPackageManager.EnabledPackages.Regular.Contains(resultPackage))
|
||||
{
|
||||
ContentPackageManager.EnabledPackages.EnableRegular(resultPackage);
|
||||
GameSettings.SaveCurrentConfig();
|
||||
}
|
||||
|
||||
UpdateEntityList();
|
||||
}
|
||||
|
||||
@@ -2884,11 +2932,8 @@ namespace Barotrauma
|
||||
{
|
||||
if (deleteButtonHolder.FindChild("delete") is GUIButton deleteBtn)
|
||||
{
|
||||
#if DEBUG
|
||||
deleteBtn.Enabled = true;
|
||||
#else
|
||||
deleteBtn.Enabled = userData is SubmarineInfo subInfo && !subInfo.IsVanillaSubmarine();
|
||||
#endif
|
||||
deleteBtn.Enabled = userData is SubmarineInfo subInfo
|
||||
&& (GetContentPackageIntrinsicallyTiedToSub(subInfo) != null || Path.GetDirectoryName(subInfo.FilePath) == SubmarineInfo.SavePath);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -3141,18 +3186,10 @@ namespace Barotrauma
|
||||
ReconstructLayers();
|
||||
}
|
||||
|
||||
private RegularPackage GetContentPackageIntrinsicallyTiedToSub(SubmarineInfo sub)
|
||||
{
|
||||
foreach (RegularPackage regularPackage in ContentPackageManager.RegularPackages)
|
||||
{
|
||||
if (regularPackage.Files.Length == 1 && regularPackage.Files[0].Path == sub.FilePath)
|
||||
{
|
||||
return regularPackage;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
private static RegularPackage GetContentPackageIntrinsicallyTiedToSub(SubmarineInfo sub)
|
||||
=> ContentPackageManager.LocalPackages.Regular
|
||||
.Where(p => p.Files.Length == 1)
|
||||
.FirstOrDefault(regularPackage => regularPackage.Files[0].Path == sub.FilePath);
|
||||
|
||||
private void TryDeleteSub(SubmarineInfo sub)
|
||||
{
|
||||
@@ -3160,8 +3197,10 @@ namespace Barotrauma
|
||||
|
||||
//If the sub is included in a content package that only defines that one sub,
|
||||
//check that it's a local content package and only allow deletion if it is.
|
||||
//(deleting from the Submarines folder is also currently allowed, but this is temporary)
|
||||
var subPackage = GetContentPackageIntrinsicallyTiedToSub(sub);
|
||||
if (!ContentPackageManager.LocalPackages.Regular.Contains(subPackage)) { return; }
|
||||
bool isInOldSavePath = Path.GetDirectoryName(sub.FilePath) == SubmarineInfo.SavePath;
|
||||
if (!ContentPackageManager.LocalPackages.Regular.Contains(subPackage) && !isInOldSavePath) { return; }
|
||||
|
||||
var msgBox = new GUIMessageBox(
|
||||
TextManager.Get("DeleteDialogLabel"),
|
||||
@@ -3171,10 +3210,18 @@ namespace Barotrauma
|
||||
{
|
||||
try
|
||||
{
|
||||
Directory.Delete(Path.GetDirectoryName(subPackage.Path), true);
|
||||
if (subPackage != null)
|
||||
{
|
||||
Directory.Delete(Path.GetDirectoryName(subPackage.Path), recursive: true);
|
||||
ContentPackageManager.LocalPackages.Refresh();
|
||||
ContentPackageManager.EnabledPackages.DisableRemovedMods();
|
||||
}
|
||||
else if (isInOldSavePath && File.Exists(sub.FilePath))
|
||||
{
|
||||
File.Delete(sub.FilePath);
|
||||
}
|
||||
|
||||
sub.Dispose();
|
||||
File.Delete(sub.FilePath);
|
||||
SubmarineInfo.RefreshSavedSubs();
|
||||
CreateLoadScreen();
|
||||
}
|
||||
|
||||
@@ -390,13 +390,13 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
GUIComponent propertyField = null;
|
||||
if (value is bool)
|
||||
if (value is bool boolVal)
|
||||
{
|
||||
propertyField = CreateBoolField(entity, property, (bool)value, displayName, toolTip);
|
||||
propertyField = CreateBoolField(entity, property, boolVal, displayName, toolTip);
|
||||
}
|
||||
else if (value is string)
|
||||
else if (value is string stringVal)
|
||||
{
|
||||
propertyField = CreateStringField(entity, property, (string)value, displayName, toolTip);
|
||||
propertyField = CreateStringField(entity, property, stringVal, displayName, toolTip);
|
||||
}
|
||||
else if (value.GetType().IsEnum)
|
||||
{
|
||||
@@ -1277,7 +1277,7 @@ namespace Barotrauma
|
||||
|
||||
public void CreateTextPicker(string textTag, ISerializableEntity entity, SerializableProperty property, GUITextBox textBox)
|
||||
{
|
||||
var msgBox = new GUIMessageBox("", "", new LocalizedString[] { TextManager.Get("Cancel") }, new Vector2(0.2f, 0.5f), new Point(300, 400));
|
||||
var msgBox = new GUIMessageBox("", "", new LocalizedString[] { TextManager.Get("Ok") }, new Vector2(0.2f, 0.5f), new Point(300, 400));
|
||||
msgBox.Buttons[0].OnClicked = msgBox.Close;
|
||||
|
||||
var textList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.8f), msgBox.Content.RectTransform, Anchor.TopCenter))
|
||||
@@ -1307,6 +1307,18 @@ namespace Barotrauma
|
||||
UserData = tagTextPair.Key.ToString()
|
||||
};
|
||||
}
|
||||
|
||||
if (entity is IHasExtraTextPickerEntries hasExtraTextPickerEntries)
|
||||
{
|
||||
foreach (string extraEntry in hasExtraTextPickerEntries.GetExtraTextPickerEntries())
|
||||
{
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), textList.Content.RectTransform) { MinSize = new Point(0, 20) },
|
||||
ToolBox.LimitString(extraEntry, GUIStyle.Font, textList.Content.Rect.Width), GUIStyle.Green)
|
||||
{
|
||||
UserData = extraEntry
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void TrySendNetworkUpdate(ISerializableEntity entity, SerializableProperty property)
|
||||
@@ -1445,4 +1457,12 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implement this interface to insert extra entires to the text pickers created for the SerializableEntityEditors of the entity
|
||||
/// </summary>
|
||||
interface IHasExtraTextPickerEntries
|
||||
{
|
||||
public IEnumerable<string> GetExtraTextPickerEntries();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ namespace Barotrauma
|
||||
if (sound?.Sound != null)
|
||||
{
|
||||
loopSound = subElement.GetAttributeBool("loop", false);
|
||||
if (subElement.Attribute("selectionmode") != null)
|
||||
if (subElement.GetAttribute("selectionmode") != null)
|
||||
{
|
||||
if (Enum.TryParse(subElement.GetAttributeString("selectionmode", "Random"), out SoundSelectionMode selectionMode))
|
||||
{
|
||||
|
||||
@@ -533,6 +533,9 @@ namespace Barotrauma.Steam
|
||||
private void PopulateFrameWithItemInfo(Steamworks.Ugc.Item workshopItem, GUIFrame parentFrame)
|
||||
{
|
||||
taskCancelSrc = taskCancelSrc.IsCancellationRequested ? new CancellationTokenSource() : taskCancelSrc;
|
||||
|
||||
var contentPackage
|
||||
= ContentPackageManager.WorkshopPackages.FirstOrDefault(p => p.SteamWorkshopId == workshopItem.Id);
|
||||
|
||||
var verticalLayout = new GUILayoutGroup(new RectTransform(Vector2.One, parentFrame.RectTransform));
|
||||
|
||||
@@ -567,34 +570,74 @@ namespace Barotrauma.Steam
|
||||
|
||||
RectTransform rightSideButtonRectT()
|
||||
=> new RectTransform(Vector2.One, headerLayout.RectTransform, scaleBasis: ScaleBasis.BothHeight);
|
||||
|
||||
bool reinstallAction(GUIButton button, object o)
|
||||
{
|
||||
TaskPool.Add($"Reinstall{workshopItem.Id}", SteamManager.Workshop.Reinstall(workshopItem), t =>
|
||||
{
|
||||
ContentPackageManager.WorkshopPackages.Refresh();
|
||||
ContentPackageManager.EnabledPackages.RefreshUpdatedMods();
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
var (updateButton, updateSprite) = CreatePaddedButton(
|
||||
rightSideButtonRectT(),
|
||||
"GUIUpdateButton",
|
||||
spriteScale: 0.8f);
|
||||
updateButton.ToolTip = TextManager.Get("WorkshopItemUpdate");
|
||||
updateButton.Visible = false;
|
||||
updateButton.OnClicked = reinstallAction;
|
||||
|
||||
if (contentPackage != null)
|
||||
{
|
||||
TaskPool.Add(
|
||||
$"DetermineUpdateRequired{contentPackage.SteamWorkshopId}",
|
||||
contentPackage.IsUpToDate(),
|
||||
t =>
|
||||
{
|
||||
if (!t.TryGetResult(out bool isUpToDate)) { return; }
|
||||
|
||||
updateButton.Visible = !isUpToDate;
|
||||
});
|
||||
}
|
||||
|
||||
var (reinstallButton, reinstallSprite) = CreatePaddedButton(
|
||||
rightSideButtonRectT(),
|
||||
"GUIReloadButton",
|
||||
spriteScale: 0.8f);
|
||||
reinstallButton.ToolTip = TextManager.Get("WorkshopItemReinstall");
|
||||
reinstallButton.OnClicked += (button, o) =>
|
||||
{
|
||||
SteamManager.Workshop.Uninstall(workshopItem);
|
||||
TaskPool.Add($"Reinstall{workshopItem.Id}", SteamManager.Workshop.ForceRedownload(workshopItem), t => { });
|
||||
return false;
|
||||
};
|
||||
reinstallButton.OnClicked = reinstallAction;
|
||||
var reinstallButtonUpdater = new GUICustomComponent(
|
||||
new RectTransform(Vector2.Zero, reinstallButton.RectTransform),
|
||||
onUpdate: (f, component) =>
|
||||
{
|
||||
reinstallButton.Visible = workshopItem.IsSubscribed;
|
||||
reinstallButton.Visible = workshopItem.IsSubscribed || workshopItem.Owner.Id == SteamManager.GetSteamID();
|
||||
reinstallButton.Enabled = !workshopItem.IsDownloading && !workshopItem.IsDownloadPending &&
|
||||
!SteamManager.Workshop.IsInstalling(workshopItem);
|
||||
|
||||
reinstallSprite.Color = reinstallButton.Enabled
|
||||
? reinstallSprite.Style.Color
|
||||
: Color.DimGray;
|
||||
updateButton.Enabled = reinstallButton.Enabled && contentPackage != null && ContentPackageManager.WorkshopPackages.Contains(contentPackage);
|
||||
updateSprite.Color = reinstallSprite.Color;
|
||||
|
||||
if (contentPackage != null
|
||||
&& !ContentPackageManager.WorkshopPackages.Contains(contentPackage)
|
||||
&& ContentPackageManager.WorkshopPackages.Any(p => p.SteamWorkshopId == workshopItem.Id))
|
||||
{
|
||||
updateButton.Visible = false;
|
||||
}
|
||||
});
|
||||
CreateSubscribeButton(workshopItem,
|
||||
rightSideButtonRectT(),
|
||||
spriteScale: 0.8f);
|
||||
|
||||
var padding = new GUIFrame(
|
||||
new RectTransform((0.15f, 1.0f), headerLayout.RectTransform, scaleBasis: ScaleBasis.BothHeight),
|
||||
style: null);
|
||||
|
||||
var padding = new GUIFrame(new RectTransform((1.0f, 0.015f), verticalLayout.RectTransform), style: null);
|
||||
padding = new GUIFrame(new RectTransform((1.0f, 0.015f), verticalLayout.RectTransform), style: null);
|
||||
|
||||
var horizontalLayout = new GUILayoutGroup(new RectTransform((1.0f, 0.45f), verticalLayout.RectTransform),
|
||||
isHorizontal: true)
|
||||
@@ -638,7 +681,7 @@ namespace Barotrauma.Steam
|
||||
isHorizontal: true,
|
||||
childAnchor: Anchor.CenterLeft) { Stretch = true };
|
||||
var starColor = Color.Lerp(
|
||||
Color.Lerp(Color.Red, Color.Yellow, Math.Min(workshopItem.Score * 2.0f, 1.0f)),
|
||||
Color.Lerp(Color.White, Color.Yellow, Math.Min(workshopItem.Score * 2.0f, 1.0f)),
|
||||
Color.Lime, Math.Max(0.0f, (workshopItem.Score - 0.5f) * 2.0f));
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
@@ -652,12 +695,23 @@ namespace Barotrauma.Steam
|
||||
star.SelectedColor = starColor;
|
||||
}
|
||||
}
|
||||
var scoreVoteCountPadding = new GUIFrame(new RectTransform((0.5f, 1.0f), scoreStarContainer.RectTransform, scaleBasis: ScaleBasis.BothHeight),
|
||||
var scoreTextPadding = new GUIFrame(new RectTransform((0.5f, 1.0f), scoreStarContainer.RectTransform, scaleBasis: ScaleBasis.BothHeight),
|
||||
style: null);
|
||||
|
||||
var scoreTextContainer = new GUIFrame(new RectTransform(Vector2.One, scoreStarContainer.RectTransform),
|
||||
style: null);
|
||||
|
||||
var scoreVoteCount = new GUITextBlock(
|
||||
new RectTransform(Vector2.One, scoreStarContainer.RectTransform),
|
||||
new RectTransform((1.0f, 1.5f), scoreTextContainer.RectTransform, Anchor.Center),
|
||||
TextManager.GetWithVariable("WorkshopItemVotes", "[VoteCount]",
|
||||
(workshopItem.VotesUp + workshopItem.VotesDown).ToString()), textAlignment: Alignment.CenterLeft)
|
||||
(workshopItem.VotesUp + workshopItem.VotesDown).ToString()), textAlignment: Alignment.BottomLeft)
|
||||
{
|
||||
Padding = Vector4.Zero
|
||||
};
|
||||
var subscriptionCount = new GUITextBlock(
|
||||
new RectTransform((1.0f, 1.5f), scoreTextContainer.RectTransform, Anchor.Center),
|
||||
TextManager.GetWithVariable("WorkshopItemSubscriptions", "[SubscriptionCount]",
|
||||
workshopItem.NumUniqueSubscriptions.ToString()), textAlignment: Alignment.TopLeft)
|
||||
{
|
||||
Padding = Vector4.Zero
|
||||
};
|
||||
|
||||
@@ -89,23 +89,22 @@ namespace Barotrauma.Steam
|
||||
|
||||
return (fileCount, byteCount);
|
||||
}
|
||||
|
||||
private void DeselectPublishedItem()
|
||||
{
|
||||
var deselectCarrier = selfModsList.Parent.FindChild(c => c.UserData is ActionCarrier { Id: var id } && id == "deselect");
|
||||
Action? deselectAction = deselectCarrier.UserData is ActionCarrier { Action: var action }
|
||||
? action
|
||||
: null;
|
||||
deselectAction?.Invoke();
|
||||
SelectTab(Tab.Publish);
|
||||
}
|
||||
|
||||
private void PopulatePublishTab(ItemOrPackage itemOrPackage, GUIFrame parentFrame)
|
||||
{
|
||||
ContentPackageManager.LocalPackages.Refresh();
|
||||
ContentPackageManager.WorkshopPackages.Refresh();
|
||||
|
||||
var deselectCarrier = selfModsList.Parent.FindChild(c => c.UserData is ActionCarrier { Id: var id } && id == "deselect");
|
||||
Action? deselectAction = deselectCarrier.UserData is ActionCarrier { Action: var action }
|
||||
? action
|
||||
: null;
|
||||
|
||||
void deselectItem()
|
||||
{
|
||||
deselectAction?.Invoke();
|
||||
SelectTab(Tab.Publish);
|
||||
}
|
||||
|
||||
parentFrame.ClearChildren();
|
||||
GUILayoutGroup mainLayout = new GUILayoutGroup(new RectTransform(Vector2.One, parentFrame.RectTransform),
|
||||
childAnchor: Anchor.TopCenter);
|
||||
@@ -146,7 +145,7 @@ namespace Barotrauma.Steam
|
||||
{
|
||||
OnClicked = (button, o) =>
|
||||
{
|
||||
deselectItem();
|
||||
DeselectPublishedItem();
|
||||
return false;
|
||||
}
|
||||
};
|
||||
@@ -285,7 +284,7 @@ namespace Barotrauma.Steam
|
||||
RectTransform newButtonRectT()
|
||||
=> new RectTransform((0.4f, 1.0f), buttonLayout.RectTransform);
|
||||
|
||||
var publishItemButton = new GUIButton(newButtonRectT(), TextManager.Get("WorkshopItemPublish"))
|
||||
var publishItemButton = new GUIButton(newButtonRectT(), TextManager.Get(workshopItem.Id != 0 ? "WorkshopItemUpdate" : "WorkshopItemPublish"))
|
||||
{
|
||||
OnClicked = (button, o) =>
|
||||
{
|
||||
@@ -333,8 +332,9 @@ namespace Barotrauma.Steam
|
||||
TaskPool.Add($"Delete{workshopItem.Id}", Steamworks.SteamUGC.DeleteFileAsync(workshopItem.Id),
|
||||
t =>
|
||||
{
|
||||
SteamManager.Workshop.Uninstall(workshopItem);
|
||||
confirmDeletion.Close();
|
||||
deselectItem();
|
||||
DeselectPublishedItem();
|
||||
});
|
||||
return false;
|
||||
};
|
||||
@@ -364,24 +364,10 @@ namespace Barotrauma.Steam
|
||||
return false;
|
||||
};
|
||||
|
||||
var coroutineEval = subcoroutine(messageBox.Text, messageBox);
|
||||
var coroutineEval = subcoroutine(messageBox.Text, messageBox).GetEnumerator();
|
||||
while (true)
|
||||
{
|
||||
bool moveNext = true;
|
||||
try
|
||||
{
|
||||
moveNext = coroutineEval.GetEnumerator().MoveNext();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
DebugConsole.ThrowError($"{e.Message} {e.StackTrace.CleanupStackTrace()}");
|
||||
messageBox.Close();
|
||||
}
|
||||
if (!moveNext)
|
||||
{
|
||||
messageBox.Close();
|
||||
}
|
||||
var status = coroutineEval.GetEnumerator().Current;
|
||||
var status = coroutineEval.Current;
|
||||
if (messageBox.Closed)
|
||||
{
|
||||
yield return CoroutineStatus.Success;
|
||||
@@ -397,6 +383,20 @@ namespace Barotrauma.Steam
|
||||
{
|
||||
yield return status;
|
||||
}
|
||||
bool moveNext = true;
|
||||
try
|
||||
{
|
||||
moveNext = coroutineEval.MoveNext();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
DebugConsole.ThrowError($"{e.Message} {e.StackTrace.CleanupStackTrace()}");
|
||||
messageBox.Close();
|
||||
}
|
||||
if (!moveNext)
|
||||
{
|
||||
messageBox.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -408,26 +408,9 @@ namespace Barotrauma.Steam
|
||||
{
|
||||
if (!SteamManager.Workshop.CanBeInstalled(workshopItem))
|
||||
{
|
||||
//Must download!
|
||||
while (!SteamManager.Workshop.CanBeInstalled(workshopItem))
|
||||
{
|
||||
bool shouldForceInstall = workshopItem.IsInstalled
|
||||
&& Directory.Exists(workshopItem.Directory)
|
||||
&& !SteamManager.Workshop.IsItemDirectoryUpToDate(workshopItem);
|
||||
shouldForceInstall |= workshopItem is
|
||||
{ IsDownloading: false, IsDownloadPending: false, IsInstalled: false };
|
||||
if (shouldForceInstall)
|
||||
{
|
||||
SteamManager.Workshop.ForceRedownload(workshopItem);
|
||||
}
|
||||
currentStepText.Text = TextManager.GetWithVariable("PublishPopupDownload", "[percentage]", Percentage(workshopItem.DownloadAmount));
|
||||
yield return new WaitForSeconds(0.5f);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SteamManager.Workshop.DownloadModThenEnqueueInstall(workshopItem);
|
||||
SteamManager.Workshop.NukeDownload(workshopItem);
|
||||
}
|
||||
SteamManager.Workshop.DownloadModThenEnqueueInstall(workshopItem);
|
||||
TaskPool.Add($"Install {workshopItem.Title}",
|
||||
SteamManager.Workshop.WaitForInstall(workshopItem),
|
||||
(t) =>
|
||||
@@ -436,7 +419,9 @@ namespace Barotrauma.Steam
|
||||
});
|
||||
while (!ContentPackageManager.WorkshopPackages.Any(p => p.SteamWorkshopId == workshopItem.Id))
|
||||
{
|
||||
currentStepText.Text = TextManager.Get("PublishPopupInstall");
|
||||
currentStepText.Text = SteamManager.Workshop.CanBeInstalled(workshopItem)
|
||||
? TextManager.Get("PublishPopupInstall")
|
||||
: TextManager.GetWithVariable("PublishPopupDownload", "[percentage]", Percentage(workshopItem.DownloadAmount));
|
||||
yield return new WaitForSeconds(0.5f);
|
||||
}
|
||||
|
||||
@@ -457,7 +442,6 @@ namespace Barotrauma.Steam
|
||||
currentStepText.Text = TextManager.Get("PublishPopupCreateLocal");
|
||||
yield return new WaitForSeconds(0.5f);
|
||||
}
|
||||
|
||||
PopulatePublishTab(workshopItem, parentFrame);
|
||||
|
||||
yield return CoroutineStatus.Success;
|
||||
@@ -500,7 +484,10 @@ namespace Barotrauma.Steam
|
||||
editor.SubmitAsync(),
|
||||
t =>
|
||||
{
|
||||
t.TryGetResult(out result);
|
||||
if (t.TryGetResult(out Steamworks.Ugc.PublishResult publishResult))
|
||||
{
|
||||
result = publishResult;
|
||||
}
|
||||
resultException = t.Exception?.GetInnermost();
|
||||
});
|
||||
currentStepText.Text = TextManager.Get("PublishPopupSubmit");
|
||||
@@ -523,6 +510,14 @@ namespace Barotrauma.Steam
|
||||
$"exception was {downloadTask.Exception?.GetInnermost()?.ToString().CleanupStackTrace() ?? "[NULL]"}");
|
||||
}
|
||||
|
||||
ContentPackage? pkgToNuke
|
||||
= ContentPackageManager.WorkshopPackages.FirstOrDefault(p => p.SteamWorkshopId == resultId);
|
||||
if (pkgToNuke != null)
|
||||
{
|
||||
Directory.Delete(pkgToNuke.Dir, recursive: true);
|
||||
ContentPackageManager.WorkshopPackages.Refresh();
|
||||
}
|
||||
|
||||
bool installed = false;
|
||||
TaskPool.Add(
|
||||
"InstallNewlyPublished",
|
||||
@@ -537,13 +532,17 @@ namespace Barotrauma.Steam
|
||||
yield return new WaitForSeconds(0.5f);
|
||||
}
|
||||
|
||||
ContentPackageManager.WorkshopPackages.Refresh();
|
||||
ContentPackageManager.EnabledPackages.RefreshUpdatedMods();
|
||||
|
||||
var localModProject = new ModProject(localPackage)
|
||||
{
|
||||
SteamWorkshopId = resultId
|
||||
};
|
||||
localModProject.DiscardHashAndInstallTime();
|
||||
localModProject.Save(localPackage.Path);
|
||||
ContentPackageManager.ReloadContentPackage(localPackage);
|
||||
ContentPackageManager.WorkshopPackages.Refresh();
|
||||
DeselectPublishedItem();
|
||||
|
||||
if (result.Value.NeedsWorkshopAgreement)
|
||||
{
|
||||
|
||||
@@ -8,6 +8,7 @@ using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Barotrauma.Extensions;
|
||||
|
||||
namespace Barotrauma.Steam
|
||||
{
|
||||
@@ -117,7 +118,7 @@ namespace Barotrauma.Steam
|
||||
if (thumbnailUrl.IsNullOrWhiteSpace()) { return null; }
|
||||
var client = new RestClient(thumbnailUrl);
|
||||
var request = new RestRequest(".", Method.GET);
|
||||
IRestResponse response = await client.ExecuteTaskAsync(request, cancellationToken);
|
||||
IRestResponse response = await client.ExecuteAsync(request, cancellationToken);
|
||||
if (response is { StatusCode: System.Net.HttpStatusCode.OK, ResponseStatus: ResponseStatus.Completed })
|
||||
{
|
||||
using var dataStream = new System.IO.MemoryStream();
|
||||
@@ -207,6 +208,11 @@ namespace Barotrauma.Steam
|
||||
}
|
||||
|
||||
string newPath = $"{ContentPackage.LocalModsDir}/{sanitizedName}";
|
||||
if (File.Exists(newPath) || Directory.Exists(newPath))
|
||||
{
|
||||
newPath += $"_{contentPackage.SteamWorkshopId}";
|
||||
}
|
||||
|
||||
if (File.Exists(newPath) || Directory.Exists(newPath))
|
||||
{
|
||||
throw new Exception($"{newPath} already exists");
|
||||
@@ -256,6 +262,18 @@ namespace Barotrauma.Steam
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task Reinstall(Steamworks.Ugc.Item workshopItem)
|
||||
{
|
||||
NukeDownload(workshopItem);
|
||||
var toUninstall
|
||||
= ContentPackageManager.WorkshopPackages.Where(p => p.SteamWorkshopId == workshopItem.Id)
|
||||
.ToHashSet();
|
||||
toUninstall.Select(p => p.Dir).ForEach(d => Directory.Delete(d));
|
||||
CrossThread.RequestExecutionOnMainThread(() => ContentPackageManager.WorkshopPackages.Refresh());
|
||||
DownloadModThenEnqueueInstall(workshopItem);
|
||||
await WaitForInstall(workshopItem);
|
||||
}
|
||||
|
||||
public static async Task WaitForInstall(Steamworks.Ugc.Item item)
|
||||
=> await WaitForInstall(item.Id);
|
||||
|
||||
@@ -263,6 +281,7 @@ namespace Barotrauma.Steam
|
||||
{
|
||||
var installWaiter = new InstallWaiter(item);
|
||||
while (installWaiter.Waiting) { await Task.Delay(500); }
|
||||
await Task.Delay(500);
|
||||
}
|
||||
|
||||
public static void OnItemDownloadComplete(ulong id, bool forceInstall = false)
|
||||
@@ -276,7 +295,8 @@ namespace Barotrauma.Steam
|
||||
return;
|
||||
}
|
||||
else if (CanBeInstalled(id)
|
||||
&& !ContentPackageManager.WorkshopPackages.Any(p => p.SteamWorkshopId == id))
|
||||
&& !ContentPackageManager.WorkshopPackages.Any(p => p.SteamWorkshopId == id)
|
||||
&& !InstallTaskCounter.IsInstalling(id))
|
||||
{
|
||||
TaskPool.Add($"InstallItem{id}", InstallMod(id), t => InstallWaiter.StopWaiting(id));
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ namespace Barotrauma.Steam
|
||||
private readonly GUIListBox enabledRegularModsList;
|
||||
private readonly GUIListBox disabledRegularModsList;
|
||||
private readonly Action<ItemOrPackage> onInstalledInfoButtonHit;
|
||||
private readonly GUITextBox modsListFilter;
|
||||
|
||||
private CancellationTokenSource taskCancelSrc = new CancellationTokenSource();
|
||||
private readonly HashSet<SteamManager.Workshop.ItemThumbnail> itemThumbnails = new HashSet<SteamManager.Workshop.ItemThumbnail>();
|
||||
@@ -47,7 +48,12 @@ namespace Barotrauma.Steam
|
||||
|
||||
contentFrame = new GUIFrame(new RectTransform((1.0f, 0.95f), mainLayout.RectTransform), style: null);
|
||||
|
||||
CreateInstalledModsTab(out enabledCoreDropdown, out enabledRegularModsList, out disabledRegularModsList, out onInstalledInfoButtonHit);
|
||||
CreateInstalledModsTab(
|
||||
out enabledCoreDropdown,
|
||||
out enabledRegularModsList,
|
||||
out disabledRegularModsList,
|
||||
out onInstalledInfoButtonHit,
|
||||
out modsListFilter);
|
||||
CreatePopularModsTab(out popularModsList);
|
||||
CreatePublishTab(out selfModsList);
|
||||
|
||||
@@ -176,7 +182,8 @@ namespace Barotrauma.Steam
|
||||
out GUIDropDown enabledCoreDropdown,
|
||||
out GUIListBox enabledRegularModsList,
|
||||
out GUIListBox disabledRegularModsList,
|
||||
out Action<ItemOrPackage> onInstalledInfoButtonHit)
|
||||
out Action<ItemOrPackage> onInstalledInfoButtonHit,
|
||||
out GUITextBox modsListFilter)
|
||||
{
|
||||
GUIFrame content = CreateNewContentFrame(Tab.InstalledMods);
|
||||
|
||||
@@ -287,7 +294,7 @@ namespace Barotrauma.Steam
|
||||
var searchRectT = NewItemRectT(mainLayout, heightScale: 1.0f);
|
||||
searchRectT.RelativeSize = (0.5f, searchRectT.RelativeSize.Y);
|
||||
var searchHolder = new GUIFrame(searchRectT, style: null);
|
||||
var searchBox = new GUITextBox(new RectTransform(Vector2.One, searchHolder.RectTransform), "");
|
||||
var searchBox = new GUITextBox(new RectTransform(Vector2.One, searchHolder.RectTransform), "", createClearButton: true);
|
||||
var searchTitle = new GUITextBlock(new RectTransform(Vector2.One, searchHolder.RectTransform) {Anchor = Anchor.TopLeft},
|
||||
textColor: Color.DarkGray * 0.6f,
|
||||
text: TextManager.Get("Search") + "...",
|
||||
@@ -300,12 +307,10 @@ namespace Barotrauma.Steam
|
||||
|
||||
searchBox.OnTextChanged += (sender, str) =>
|
||||
{
|
||||
enabledModsList.Content.Children.Concat(disabledModsList.Content.Children)
|
||||
.ForEach(c => c.Visible = str.IsNullOrWhiteSpace()
|
||||
|| (c.UserData is ContentPackage p
|
||||
&& p.Name.Contains(str, StringComparison.OrdinalIgnoreCase)));
|
||||
UpdateModListItemVisibility();
|
||||
return true;
|
||||
};
|
||||
modsListFilter = searchBox;
|
||||
|
||||
new GUICustomComponent(new RectTransform(Vector2.Zero, content.RectTransform),
|
||||
onUpdate: (f, component) =>
|
||||
@@ -320,6 +325,15 @@ namespace Barotrauma.Steam
|
||||
});
|
||||
}
|
||||
|
||||
private void UpdateModListItemVisibility()
|
||||
{
|
||||
string str = modsListFilter.Text;
|
||||
enabledRegularModsList.Content.Children.Concat(disabledRegularModsList.Content.Children)
|
||||
.ForEach(c => c.Visible = str.IsNullOrWhiteSpace()
|
||||
|| (c.UserData is ContentPackage p
|
||||
&& p.Name.Contains(str, StringComparison.OrdinalIgnoreCase)));
|
||||
}
|
||||
|
||||
private void PopulateInstalledModLists()
|
||||
{
|
||||
ContentPackageManager.UpdateContentPackageList();
|
||||
@@ -344,15 +358,21 @@ namespace Barotrauma.Steam
|
||||
RelativeSpacing = 0.02f
|
||||
};
|
||||
|
||||
var dragIndicator = new GUIButton(new RectTransform((0.1f, 0.5f), frameContent.RectTransform, scaleBasis: ScaleBasis.BothHeight),
|
||||
var dragIndicator = new GUIButton(new RectTransform((0.5f, 0.5f), frameContent.RectTransform, scaleBasis: ScaleBasis.BothHeight),
|
||||
style: "GUIDragIndicator")
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
|
||||
var modNameScissor
|
||||
= new GUIScissorComponent(new RectTransform((0.8f, 1.0f), frameContent.RectTransform));
|
||||
var modName = new GUITextBlock(new RectTransform(Vector2.One, modNameScissor.Content.RectTransform), text: mod.Name);
|
||||
var modNameScissor = new GUIScissorComponent(new RectTransform((0.8f, 1.0f), frameContent.RectTransform))
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
var modName = new GUITextBlock(new RectTransform(Vector2.One, modNameScissor.Content.RectTransform),
|
||||
text: mod.Name)
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
if (ContentPackageManager.LocalPackages.Contains(mod))
|
||||
{
|
||||
var editButton = new GUIButton(new RectTransform(Vector2.One, frameContent.RectTransform, scaleBasis: ScaleBasis.Smallest), "",
|
||||
@@ -418,6 +438,8 @@ namespace Barotrauma.Steam
|
||||
if (ContentPackageManager.EnabledPackages.Regular.Contains(mod)) { continue; }
|
||||
addRegularModToList(mod, disabledRegularModsList);
|
||||
}
|
||||
|
||||
UpdateModListItemVisibility();
|
||||
}
|
||||
|
||||
private void CreatePopularModsTab(out GUIListBox popularModsList)
|
||||
|
||||
Reference in New Issue
Block a user