Unstable 0.1500.4.0 (Shrek edition)
This commit is contained in:
@@ -23,12 +23,30 @@ namespace Barotrauma
|
||||
private Sprite disguisedJobIcon;
|
||||
private Color disguisedJobColor;
|
||||
|
||||
private Sprite tintMask;
|
||||
private float tintHighlightThreshold;
|
||||
private float tintHighlightMultiplier;
|
||||
|
||||
public static void Init()
|
||||
{
|
||||
infoAreaPortraitBG = GUI.Style.GetComponentStyle("InfoAreaPortraitBG")?.GetDefaultSprite();
|
||||
new Sprite("Content/UI/InventoryUIAtlas.png", new Rectangle(833, 298, 142, 98), null, 0);
|
||||
}
|
||||
|
||||
partial void LoadHeadSpriteProjectSpecific(XElement limbElement)
|
||||
{
|
||||
XElement maskElement = limbElement.Element("tintmask");
|
||||
if (maskElement != null)
|
||||
{
|
||||
string tintMaskPath = maskElement.GetAttributeString("texture", "");
|
||||
if (!string.IsNullOrWhiteSpace(tintMaskPath))
|
||||
{
|
||||
tintMask = new Sprite(maskElement, file: Limb.GetSpritePath(tintMaskPath, this));
|
||||
tintHighlightThreshold = maskElement.GetAttributeFloat("highlightthreshold", 0.6f);
|
||||
tintHighlightMultiplier = maskElement.GetAttributeFloat("highlightmultiplier", 0.8f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public GUIComponent CreateInfoFrame(GUIFrame frame, bool returnParent, Sprite permissionIcon = null)
|
||||
{
|
||||
@@ -458,6 +476,7 @@ namespace Barotrauma
|
||||
}
|
||||
else
|
||||
{
|
||||
//TODO: disguise skin and hair colors
|
||||
sheetIndex = disguisedSheetIndex;
|
||||
portraitToDraw = disguisedPortrait;
|
||||
attachmentsToDraw = disguisedAttachmentSprites;
|
||||
@@ -465,22 +484,74 @@ namespace Barotrauma
|
||||
|
||||
if (portraitToDraw != null)
|
||||
{
|
||||
var currEffect = spriteBatch.GetCurrentEffect();
|
||||
// Scale down the head sprite 10%
|
||||
float scale = targetWidth * 0.9f / Portrait.size.X;
|
||||
if (sheetIndex.HasValue)
|
||||
{
|
||||
SetHeadEffect(spriteBatch);
|
||||
portraitToDraw.SourceRect = new Rectangle(CalculateOffset(portraitToDraw, sheetIndex.Value.ToPoint()), portraitToDraw.SourceRect.Size);
|
||||
}
|
||||
portraitToDraw.Draw(spriteBatch, screenPos + offset, Color.White, portraitToDraw.Origin, scale: scale, spriteEffect: flip ? SpriteEffects.FlipHorizontally : SpriteEffects.None);
|
||||
portraitToDraw.Draw(spriteBatch, screenPos + offset, SkinColor, portraitToDraw.Origin, scale: scale, spriteEffect: flip ? SpriteEffects.FlipHorizontally : SpriteEffects.None);
|
||||
if (attachmentsToDraw != null)
|
||||
{
|
||||
float depthStep = 0.000001f;
|
||||
foreach (var attachment in attachmentsToDraw)
|
||||
{
|
||||
DrawAttachmentSprite(spriteBatch, attachment, portraitToDraw, sheetIndex, screenPos + offset, scale, depthStep, flip ? SpriteEffects.FlipHorizontally : SpriteEffects.None);
|
||||
SetAttachmentEffect(spriteBatch, attachment);
|
||||
DrawAttachmentSprite(spriteBatch, attachment, portraitToDraw, sheetIndex, screenPos + offset, scale, depthStep, GetAttachmentColor(attachment), flip ? SpriteEffects.FlipHorizontally : SpriteEffects.None);
|
||||
depthStep += depthStep;
|
||||
}
|
||||
}
|
||||
spriteBatch.SwapEffect(currEffect);
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: I hate this so much :(
|
||||
private SpriteBatch.EffectWithParams headEffectParameters;
|
||||
private Dictionary<WearableType, SpriteBatch.EffectWithParams> attachmentEffectParameters
|
||||
= new Dictionary<WearableType, SpriteBatch.EffectWithParams>();
|
||||
|
||||
private void SetHeadEffect(SpriteBatch spriteBatch)
|
||||
{
|
||||
headEffectParameters.Effect ??= GameMain.GameScreen.ThresholdTintEffect;
|
||||
headEffectParameters.Params ??= new Dictionary<string, object>();
|
||||
headEffectParameters.Params["xBaseTexture"] = headSprite.Texture;
|
||||
headEffectParameters.Params["xTintMaskTexture"] = tintMask?.Texture ?? GUI.WhiteTexture;
|
||||
headEffectParameters.Params["xCutoffTexture"] = GUI.WhiteTexture;
|
||||
headEffectParameters.Params["baseToCutoffSizeRatio"] = 1.0f;
|
||||
headEffectParameters.Params["highlightThreshold"] = tintHighlightThreshold;
|
||||
headEffectParameters.Params["highlightMultiplier"] = tintHighlightMultiplier;
|
||||
spriteBatch.SwapEffect(headEffectParameters);
|
||||
}
|
||||
|
||||
private void SetAttachmentEffect(SpriteBatch spriteBatch, WearableSprite attachment)
|
||||
{
|
||||
if (!attachmentEffectParameters.ContainsKey(attachment.Type))
|
||||
{
|
||||
attachmentEffectParameters.Add(attachment.Type, new SpriteBatch.EffectWithParams(GameMain.GameScreen.ThresholdTintEffect, new Dictionary<string, object>()));
|
||||
}
|
||||
var parameters = attachmentEffectParameters[attachment.Type].Params;
|
||||
parameters["xBaseTexture"] = attachment.Sprite.Texture;
|
||||
parameters["xTintMaskTexture"] = GUI.WhiteTexture;
|
||||
parameters["xCutoffTexture"] = GUI.WhiteTexture;
|
||||
parameters["baseToCutoffSizeRatio"] = 1.0f;
|
||||
parameters["highlightThreshold"] = tintHighlightThreshold;
|
||||
parameters["highlightMultiplier"] = tintHighlightMultiplier;
|
||||
spriteBatch.SwapEffect(attachmentEffectParameters[attachment.Type]);
|
||||
}
|
||||
|
||||
private Color GetAttachmentColor(WearableSprite attachment)
|
||||
{
|
||||
switch (attachment.Type)
|
||||
{
|
||||
case WearableType.Hair:
|
||||
return HairColor;
|
||||
case WearableType.Beard:
|
||||
case WearableType.Moustache:
|
||||
return FacialHairColor;
|
||||
default:
|
||||
return Color.White;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -489,34 +560,28 @@ namespace Barotrauma
|
||||
var headSprite = HeadSprite;
|
||||
if (headSprite != null)
|
||||
{
|
||||
var currEffect = spriteBatch.GetCurrentEffect();
|
||||
float scale = Math.Min(targetAreaSize.X / headSprite.size.X, targetAreaSize.Y / headSprite.size.Y);
|
||||
if (Head.SheetIndex.HasValue)
|
||||
{
|
||||
headSprite.SourceRect = new Rectangle(CalculateOffset(headSprite, Head.SheetIndex.Value.ToPoint()), headSprite.SourceRect.Size);
|
||||
}
|
||||
headSprite.Draw(spriteBatch, screenPos, scale: scale);
|
||||
SetHeadEffect(spriteBatch);
|
||||
headSprite.Draw(spriteBatch, screenPos, scale: scale, color: SkinColor);
|
||||
if (AttachmentSprites != null)
|
||||
{
|
||||
float depthStep = 0.000001f;
|
||||
foreach (var attachment in AttachmentSprites)
|
||||
{
|
||||
DrawAttachmentSprite(spriteBatch, attachment, headSprite, Head.SheetIndex, screenPos, scale, depthStep);
|
||||
SetAttachmentEffect(spriteBatch, attachment);
|
||||
DrawAttachmentSprite(spriteBatch, attachment, headSprite, Head.SheetIndex, screenPos, scale, depthStep, GetAttachmentColor(attachment));
|
||||
depthStep += depthStep;
|
||||
}
|
||||
}
|
||||
spriteBatch.SwapEffect(currEffect);
|
||||
}
|
||||
}
|
||||
|
||||
public void DrawJobIcon(SpriteBatch spriteBatch, Vector2 pos, float scale = 1.0f, bool evaluateDisguise = false)
|
||||
{
|
||||
if (evaluateDisguise && IsDisguised) return;
|
||||
var icon = !IsDisguisedAsAnother || !evaluateDisguise ? Job?.Prefab?.Icon : disguisedJobIcon;
|
||||
if (icon == null) { return; }
|
||||
Color iconColor = !IsDisguisedAsAnother || !evaluateDisguise ? Job.Prefab.UIColor : disguisedJobColor;
|
||||
|
||||
icon.Draw(spriteBatch, pos, iconColor, scale: scale);
|
||||
}
|
||||
|
||||
public void DrawJobIcon(SpriteBatch spriteBatch, Rectangle area, bool evaluateDisguise = false)
|
||||
{
|
||||
if (evaluateDisguise && IsDisguised) return;
|
||||
@@ -527,7 +592,7 @@ namespace Barotrauma
|
||||
icon.Draw(spriteBatch, area.Center.ToVector2(), iconColor, scale: Math.Min(area.Width / (float)icon.SourceRect.Width, area.Height / (float)icon.SourceRect.Height));
|
||||
}
|
||||
|
||||
private void DrawAttachmentSprite(SpriteBatch spriteBatch, WearableSprite attachment, Sprite head, Vector2? sheetIndex, Vector2 drawPos, float scale, float depthStep, SpriteEffects spriteEffects = SpriteEffects.None)
|
||||
private void DrawAttachmentSprite(SpriteBatch spriteBatch, WearableSprite attachment, Sprite head, Vector2? sheetIndex, Vector2 drawPos, float scale, float depthStep, Color? color = null, SpriteEffects spriteEffects = SpriteEffects.None)
|
||||
{
|
||||
if (attachment.InheritSourceRect)
|
||||
{
|
||||
@@ -544,7 +609,7 @@ namespace Barotrauma
|
||||
attachment.Sprite.SourceRect = head.SourceRect;
|
||||
}
|
||||
}
|
||||
Vector2 origin = attachment.Sprite.Origin;
|
||||
Vector2 origin;
|
||||
if (attachment.InheritOrigin)
|
||||
{
|
||||
origin = head.Origin;
|
||||
@@ -559,7 +624,7 @@ namespace Barotrauma
|
||||
{
|
||||
depth = head.Depth - depthStep;
|
||||
}
|
||||
attachment.Sprite.Draw(spriteBatch, drawPos, Color.White, origin, rotate: 0, scale: scale, depth: depth, spriteEffect: spriteEffects);
|
||||
attachment.Sprite.Draw(spriteBatch, drawPos, color ?? Color.White, origin, rotate: 0, scale: scale, depth: depth, spriteEffect: spriteEffects);
|
||||
}
|
||||
|
||||
public static CharacterInfo ClientRead(string speciesName, IReadMessage inc)
|
||||
@@ -574,6 +639,9 @@ namespace Barotrauma
|
||||
int beardIndex = inc.ReadByte();
|
||||
int moustacheIndex = inc.ReadByte();
|
||||
int faceAttachmentIndex = inc.ReadByte();
|
||||
Color skinColor = inc.ReadColorR8G8B8();
|
||||
Color hairColor = inc.ReadColorR8G8B8();
|
||||
Color facialHairColor = inc.ReadColorR8G8B8();
|
||||
string ragdollFile = inc.ReadString();
|
||||
|
||||
string jobIdentifier = inc.ReadString();
|
||||
@@ -599,6 +667,9 @@ namespace Barotrauma
|
||||
ID = infoID,
|
||||
};
|
||||
ch.RecreateHead(headSpriteID,(Race)race, (Gender)gender, hairIndex, beardIndex, moustacheIndex, faceAttachmentIndex);
|
||||
ch.SkinColor = skinColor;
|
||||
ch.HairColor = hairColor;
|
||||
ch.FacialHairColor = facialHairColor;
|
||||
if (ch.Job != null)
|
||||
{
|
||||
foreach (KeyValuePair<string, float> skill in skillLevels)
|
||||
@@ -627,5 +698,384 @@ namespace Barotrauma
|
||||
ch.AdditionalTalentPoints = inc.ReadUInt16();
|
||||
return ch;
|
||||
}
|
||||
|
||||
public void CreateIcon(RectTransform rectT)
|
||||
{
|
||||
LoadHeadAttachments();
|
||||
new GUICustomComponent(rectT,
|
||||
onDraw: (sb, component) => DrawIcon(sb, component.Rect.Center.ToVector2(), targetAreaSize: component.Rect.Size.ToVector2()));
|
||||
}
|
||||
|
||||
public class AppearanceCustomizationMenu : IDisposable
|
||||
{
|
||||
public readonly CharacterInfo CharacterInfo;
|
||||
public GUIListBox HeadSelectionList = null;
|
||||
public bool HasIcon = true;
|
||||
|
||||
public GUIScrollBar.OnMovedHandler OnSliderMoved = null;
|
||||
public GUIScrollBar.OnMovedHandler OnSliderReleased = null;
|
||||
public Action<AppearanceCustomizationMenu> OnHeadSwitch = null;
|
||||
|
||||
private readonly GUIComponent parentComponent;
|
||||
private readonly List<Sprite> characterSprites = new List<Sprite>();
|
||||
|
||||
public AppearanceCustomizationMenu(CharacterInfo info, GUIComponent parent, bool hasIcon = true)
|
||||
{
|
||||
CharacterInfo = info;
|
||||
parentComponent = parent;
|
||||
HasIcon = hasIcon;
|
||||
|
||||
RecreateFrameContents();
|
||||
}
|
||||
|
||||
public void RecreateFrameContents()
|
||||
{
|
||||
var info = CharacterInfo;
|
||||
|
||||
HeadSelectionList = null;
|
||||
parentComponent.ClearChildren();
|
||||
ClearSprites();
|
||||
|
||||
float contentWidth = HasIcon ? 0.75f : 1.0f;
|
||||
var content =
|
||||
new GUIListBox(
|
||||
new RectTransform(new Vector2(contentWidth, 1.0f), parentComponent.RectTransform,
|
||||
Anchor.CenterLeft))
|
||||
{ CanBeFocused = false, CanTakeKeyBoardFocus = false }
|
||||
.Content;
|
||||
|
||||
info.LoadHeadAttachments();
|
||||
if (HasIcon)
|
||||
{
|
||||
info.CreateIcon(
|
||||
new RectTransform(new Vector2(0.25f, 1.0f), parentComponent.RectTransform, Anchor.CenterRight)
|
||||
{ RelativeOffset = new Vector2(-0.01f, 0.0f) });
|
||||
}
|
||||
|
||||
RectTransform createItemRectTransform(string labelTag, float width = 0.6f)
|
||||
{
|
||||
var layoutGroup = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.2f), content.RectTransform));
|
||||
|
||||
var label = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), layoutGroup.RectTransform),
|
||||
TextManager.Get(labelTag), font: GUI.SubHeadingFont);
|
||||
|
||||
var bottomItem = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.5f), layoutGroup.RectTransform),
|
||||
style: null);
|
||||
|
||||
return new RectTransform(new Vector2(width, 1.0f), bottomItem.RectTransform, Anchor.Center);
|
||||
}
|
||||
|
||||
RectTransform genderItemRT = createItemRectTransform("Gender", 1.0f);
|
||||
|
||||
GUILayoutGroup genderContainer =
|
||||
new GUILayoutGroup(genderItemRT, isHorizontal: true)
|
||||
{
|
||||
Stretch = true,
|
||||
RelativeSpacing = 0.05f
|
||||
};
|
||||
|
||||
void createGenderButton(Gender gender)
|
||||
{
|
||||
new GUIButton(new RectTransform(new Vector2(1.0f, 1.0f), genderContainer.RectTransform),
|
||||
TextManager.Get(gender.ToString()), style: "ListBoxElement")
|
||||
{
|
||||
UserData = gender,
|
||||
OnClicked = OpenHeadSelection,
|
||||
Selected = info.Gender == gender
|
||||
};
|
||||
}
|
||||
|
||||
createGenderButton(Gender.Male);
|
||||
createGenderButton(Gender.Female);
|
||||
|
||||
int countAttachmentsOfType(WearableType wearableType)
|
||||
=> info.FilterByTypeAndHeadID(
|
||||
info.FilterElementsByGenderAndRace(info.Wearables, info.Head.gender, info.Head.race),
|
||||
wearableType, info.HeadSpriteId).Count();
|
||||
|
||||
void createAttachmentSlider(int initialValue, WearableType wearableType)
|
||||
{
|
||||
int attachmentCount = countAttachmentsOfType(wearableType);
|
||||
if (attachmentCount > 0)
|
||||
{
|
||||
var labelTag = wearableType == WearableType.FaceAttachment
|
||||
? "FaceAttachment.Accessories"
|
||||
: $"FaceAttachment.{wearableType}";
|
||||
var sliderItemRT = createItemRectTransform(labelTag);
|
||||
var slider =
|
||||
new GUIScrollBar(sliderItemRT, style: "GUISlider")
|
||||
{
|
||||
Range = new Vector2(0, attachmentCount),
|
||||
StepValue = 1,
|
||||
OnMoved = (bar, scroll) => SwitchAttachment(bar, wearableType),
|
||||
OnReleased = OnSliderReleased,
|
||||
BarSize = 1.0f / (float)(attachmentCount + 1)
|
||||
};
|
||||
slider.BarScrollValue = initialValue;
|
||||
}
|
||||
}
|
||||
|
||||
createAttachmentSlider(info.HairIndex, WearableType.Hair);
|
||||
createAttachmentSlider(info.BeardIndex, WearableType.Beard);
|
||||
createAttachmentSlider(info.MoustacheIndex, WearableType.Moustache);
|
||||
createAttachmentSlider(info.FaceAttachmentIndex, WearableType.FaceAttachment);
|
||||
|
||||
void createColorSelector(string labelTag, IEnumerable<Color> options, Func<Color> getter,
|
||||
Action<Color> setter)
|
||||
{
|
||||
var selectorItemRT = createItemRectTransform(labelTag, 0.4f);
|
||||
var dropdown =
|
||||
new GUIDropDown(selectorItemRT)
|
||||
{ AllowNonText = true };
|
||||
|
||||
var listBoxSize = dropdown.ListBox.RectTransform.RelativeSize;
|
||||
dropdown.ListBox.RectTransform.RelativeSize = new Vector2(listBoxSize.X * 1.75f, listBoxSize.Y);
|
||||
var dropdownButton = dropdown.GetChild<GUIButton>();
|
||||
var buttonFrame =
|
||||
new GUIFrame(
|
||||
new RectTransform(Vector2.One * 0.7f, dropdownButton.RectTransform, Anchor.CenterLeft)
|
||||
{ RelativeOffset = new Vector2(0.05f, 0.0f) }, style: null);
|
||||
dropdown.OnSelected = (component, color) =>
|
||||
{
|
||||
setter((Color)color);
|
||||
buttonFrame.Color = getter();
|
||||
buttonFrame.HoverColor = getter();
|
||||
return true;
|
||||
};
|
||||
buttonFrame.Color = getter();
|
||||
buttonFrame.HoverColor = getter();
|
||||
|
||||
dropdown.ListBox.UseGridLayout = true;
|
||||
foreach (var option in options)
|
||||
{
|
||||
var optionElement =
|
||||
new GUIFrame(
|
||||
new RectTransform(new Vector2(0.25f, 1.0f / 3.0f),
|
||||
dropdown.ListBox.Content.RectTransform),
|
||||
style: "ListBoxElement")
|
||||
{
|
||||
UserData = option,
|
||||
CanBeFocused = true
|
||||
};
|
||||
var colorElement =
|
||||
new GUIFrame(
|
||||
new RectTransform(Vector2.One * 0.75f, optionElement.RectTransform, Anchor.Center,
|
||||
scaleBasis: ScaleBasis.Smallest),
|
||||
style: null)
|
||||
{
|
||||
Color = option,
|
||||
HoverColor = option,
|
||||
OutlineColor = Color.Lerp(Color.Black, option, 0.5f),
|
||||
CanBeFocused = false
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if (countAttachmentsOfType(WearableType.Hair) > 0)
|
||||
{
|
||||
createColorSelector($"Customization.{nameof(info.HairColor)}", info.HairColors,
|
||||
() => info.HairColor, (color) => info.HairColor = color);
|
||||
}
|
||||
|
||||
if (countAttachmentsOfType(WearableType.Moustache) > 0 ||
|
||||
countAttachmentsOfType(WearableType.Beard) > 0)
|
||||
{
|
||||
createColorSelector($"Customization.{nameof(info.FacialHairColor)}", info.FacialHairColors,
|
||||
() => info.FacialHairColor, (color) => info.FacialHairColor = color);
|
||||
}
|
||||
|
||||
createColorSelector($"Customization.{nameof(info.SkinColor)}", info.SkinColors, () => info.SkinColor,
|
||||
(color) => info.SkinColor = color);
|
||||
}
|
||||
|
||||
private bool OpenHeadSelection(GUIButton button, object userData)
|
||||
{
|
||||
Gender selectedGender = (Gender)userData;
|
||||
if (HeadSelectionList != null)
|
||||
{
|
||||
HeadSelectionList.Visible = true;
|
||||
foreach (GUIComponent child in HeadSelectionList.Content.Children)
|
||||
{
|
||||
child.Visible = (Gender)child.UserData == selectedGender;
|
||||
child.Children.ForEach(c =>
|
||||
c.Visible = ((Tuple<Gender, Race, int>)c.UserData).Item1 == selectedGender);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
var info = CharacterInfo;
|
||||
|
||||
float characterHeightWidthRatio = info.HeadSprite.size.Y / info.HeadSprite.size.X;
|
||||
HeadSelectionList = new GUIListBox(
|
||||
new RectTransform(
|
||||
new Point(parentComponent.Rect.Width,
|
||||
(int)(parentComponent.Rect.Width * characterHeightWidthRatio * 0.6f)), GUI.Canvas)
|
||||
{
|
||||
AbsoluteOffset = new Point(parentComponent.Rect.Right - parentComponent.Rect.Width,
|
||||
button.Rect.Bottom)
|
||||
});
|
||||
|
||||
parentComponent.RectTransform.SizeChanged += () =>
|
||||
{
|
||||
if (parentComponent == null || HeadSelectionList?.RectTransform == null || button == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
HeadSelectionList.RectTransform.Resize(new Point(parentComponent.Rect.Width,
|
||||
(int)(parentComponent.Rect.Width * characterHeightWidthRatio * 0.6f)));
|
||||
HeadSelectionList.RectTransform.AbsoluteOffset =
|
||||
new Point(parentComponent.Rect.Right - parentComponent.Rect.Width, button.Rect.Bottom);
|
||||
};
|
||||
|
||||
new GUIFrame(
|
||||
new RectTransform(new Vector2(1.25f, 1.25f), HeadSelectionList.RectTransform, Anchor.Center),
|
||||
style: "OuterGlow", color: Color.Black)
|
||||
{
|
||||
UserData = "outerglow",
|
||||
CanBeFocused = false
|
||||
};
|
||||
|
||||
GUILayoutGroup row = null;
|
||||
int itemsInRow = 0;
|
||||
|
||||
XElement headElement = info.Ragdoll.MainElement.Elements().FirstOrDefault(e =>
|
||||
e.GetAttributeString("type", "").Equals("head", StringComparison.OrdinalIgnoreCase));
|
||||
XElement headSpriteElement = headElement.Element("sprite");
|
||||
string spritePathWithTags = headSpriteElement.Attribute("texture").Value;
|
||||
|
||||
var characterConfigElement = info.CharacterConfigElement;
|
||||
|
||||
var heads = info.Heads;
|
||||
if (heads != null)
|
||||
{
|
||||
row = null;
|
||||
itemsInRow = 0;
|
||||
foreach (var head in heads)
|
||||
{
|
||||
var headPreset = head.Key;
|
||||
Gender gender = headPreset.Gender;
|
||||
Race race = headPreset.Race;
|
||||
int headIndex = headPreset.ID;
|
||||
|
||||
string spritePath = spritePathWithTags
|
||||
.Replace("[GENDER]", gender.ToString().ToLowerInvariant())
|
||||
.Replace("[RACE]", race.ToString().ToLowerInvariant());
|
||||
|
||||
if (!File.Exists(spritePath))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Sprite headSprite = new Sprite(headSpriteElement, "", spritePath);
|
||||
headSprite.SourceRect =
|
||||
new Rectangle(CharacterInfo.CalculateOffset(headSprite, head.Value.ToPoint()),
|
||||
headSprite.SourceRect.Size);
|
||||
characterSprites.Add(headSprite);
|
||||
|
||||
if (itemsInRow >= 4 || row == null || gender != (Gender)row.UserData)
|
||||
{
|
||||
row = new GUILayoutGroup(
|
||||
new RectTransform(new Vector2(1.0f, 0.333f), HeadSelectionList.Content.RectTransform),
|
||||
true)
|
||||
{
|
||||
UserData = gender,
|
||||
Visible = gender == selectedGender
|
||||
};
|
||||
itemsInRow = 0;
|
||||
}
|
||||
|
||||
var btn = new GUIButton(new RectTransform(new Vector2(0.25f, 1.0f), row.RectTransform),
|
||||
style: "ListBoxElementSquare")
|
||||
{
|
||||
OutlineColor = Color.White * 0.5f,
|
||||
PressedColor = Color.White * 0.5f,
|
||||
UserData = new Tuple<Gender, Race, int>(gender, race, headIndex),
|
||||
OnClicked = SwitchHead,
|
||||
Selected = gender == info.Gender && race == info.Race && headIndex == info.HeadSpriteId,
|
||||
Visible = gender == selectedGender
|
||||
};
|
||||
|
||||
new GUIImage(new RectTransform(Vector2.One, btn.RectTransform), headSprite, scaleToFit: true);
|
||||
itemsInRow++;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool SwitchHead(GUIButton button, object obj)
|
||||
{
|
||||
var info = CharacterInfo;
|
||||
Gender gender = ((Tuple<Gender, Race, int>)obj).Item1;
|
||||
Race race = ((Tuple<Gender, Race, int>)obj).Item2;
|
||||
int id = ((Tuple<Gender, Race, int>)obj).Item3;
|
||||
info.Gender = gender;
|
||||
info.Race = race;
|
||||
info.HeadSpriteId = id;
|
||||
RecreateFrameContents();
|
||||
OnHeadSwitch?.Invoke(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool SwitchAttachment(GUIScrollBar scrollBar, WearableType type)
|
||||
{
|
||||
var info = CharacterInfo;
|
||||
int index = (int)scrollBar.BarScrollValue;
|
||||
switch (type)
|
||||
{
|
||||
case WearableType.Beard:
|
||||
info.BeardIndex = index;
|
||||
break;
|
||||
case WearableType.FaceAttachment:
|
||||
info.FaceAttachmentIndex = index;
|
||||
break;
|
||||
case WearableType.Hair:
|
||||
info.HairIndex = index;
|
||||
break;
|
||||
case WearableType.Moustache:
|
||||
info.MoustacheIndex = index;
|
||||
break;
|
||||
default:
|
||||
DebugConsole.ThrowError($"Wearable type not implemented: {type}");
|
||||
return false;
|
||||
}
|
||||
|
||||
info.RefreshHead();
|
||||
OnSliderMoved?.Invoke(scrollBar, scrollBar.BarScroll);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
if (HeadSelectionList != null && PlayerInput.PrimaryMouseButtonDown() &&
|
||||
!GUI.IsMouseOn(HeadSelectionList))
|
||||
{
|
||||
HeadSelectionList.Visible = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void AddToGUIUpdateList()
|
||||
{
|
||||
HeadSelectionList?.AddToGUIUpdateList();
|
||||
}
|
||||
|
||||
private void ClearSprites()
|
||||
{
|
||||
foreach (Sprite sprite in characterSprites) { sprite.Remove(); }
|
||||
characterSprites.Clear();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
ClearSprites();
|
||||
}
|
||||
|
||||
~AppearanceCustomizationMenu()
|
||||
{
|
||||
Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -601,8 +601,13 @@ namespace Barotrauma
|
||||
.FindAll(a => a.ShouldShowIcon(Character) && a.Prefab.Icon != null);
|
||||
currentDisplayedAfflictions.Sort((a1, a2) =>
|
||||
{
|
||||
int dmgPerSecond = Math.Sign(a2.DamagePerSecond - a1.DamagePerSecond);
|
||||
return dmgPerSecond != 0 ? dmgPerSecond : Math.Sign(a1.Strength - a1.Strength);
|
||||
int dmgPerSecond = Math.Sign(a1.DamagePerSecond - a2.DamagePerSecond);
|
||||
if (dmgPerSecond != 0) { return dmgPerSecond; }
|
||||
return Math.Sign(GetStr(a1) - GetStr(a2));
|
||||
static float GetStr(Affliction affliction)
|
||||
{
|
||||
return affliction.Strength / affliction.Prefab.MaxStrength * (affliction.Prefab.IsBuff ? 1.0f : 10.0f);
|
||||
}
|
||||
});
|
||||
HintManager.OnAfflictionDisplayed(Character, currentDisplayedAfflictions);
|
||||
updateDisplayedAfflictionsTimer = UpdateDisplayedAfflictionsInterval;
|
||||
@@ -1131,6 +1136,8 @@ namespace Barotrauma
|
||||
|
||||
public static Color GetAfflictionIconColor(Affliction affliction) => GetAfflictionIconColor(affliction.Prefab, affliction);
|
||||
|
||||
private readonly List<(Affliction affliction, float strength)> displayedAfflictions = new List<(Affliction affliction, float strength)>();
|
||||
|
||||
private void UpdateAfflictionContainer(LimbHealth selectedLimb)
|
||||
{
|
||||
if (selectedLimb == null)
|
||||
@@ -1139,45 +1146,33 @@ namespace Barotrauma
|
||||
return;
|
||||
}
|
||||
var currentAfflictions = GetMatchingAfflictions(selectedLimb, a => a.ShouldShowIcon(Character));
|
||||
var displayedAfflictions = afflictionIconContainer.Content.Children.Select(c => c.UserData as Affliction);
|
||||
if (currentAfflictions.Any(a => !displayedAfflictions.Contains(a)) ||
|
||||
displayedAfflictions.Any(a => !currentAfflictions.Contains(a)))
|
||||
if (currentAfflictions.Any(a => !displayedAfflictions.Any(d => d.affliction == a)) ||
|
||||
displayedAfflictions.Any(a => !currentAfflictions.Contains(a.affliction)))
|
||||
{
|
||||
CreateAfflictionInfos(currentAfflictions);
|
||||
CreateRecommendedTreatments();
|
||||
}
|
||||
//update recommended treatments if the strength of some displayed affliction has changed by > 1
|
||||
else if (displayedAfflictions.Any(d => Math.Abs(d.strength - currentAfflictions.First(a => a == d.affliction).Strength) > 1.0f))
|
||||
{
|
||||
CreateRecommendedTreatments();
|
||||
}
|
||||
|
||||
UpdateAfflictionInfos(displayedAfflictions);
|
||||
UpdateAfflictionInfos(displayedAfflictions.Select(d => d.affliction));
|
||||
}
|
||||
|
||||
private void CreateAfflictionInfos(IEnumerable<Affliction> afflictions)
|
||||
{
|
||||
afflictionIconContainer.ClearChildren();
|
||||
recommendedTreatmentContainer.Content.ClearChildren();
|
||||
|
||||
float characterSkillLevel = Character.Controlled == null ? 0.0f : Character.Controlled.GetSkillLevel("medical");
|
||||
|
||||
//key = item identifier
|
||||
//float = suitability
|
||||
Dictionary<string, float> treatmentSuitability = new Dictionary<string, float>();
|
||||
GetSuitableTreatments(treatmentSuitability,
|
||||
normalize: true,
|
||||
ignoreHiddenAfflictions: true,
|
||||
limb: selectedLimbIndex == -1 ? null : Character.AnimController.Limbs.Find(l => l.HealthIndex == selectedLimbIndex));
|
||||
|
||||
foreach (string treatment in treatmentSuitability.Keys.ToList())
|
||||
{
|
||||
//prefer suggestions for items the player has
|
||||
if (Character.Controlled.Inventory.FindItemByIdentifier(treatment) != null)
|
||||
{
|
||||
treatmentSuitability[treatment] *= 10.0f;
|
||||
}
|
||||
}
|
||||
displayedAfflictions.Clear();
|
||||
|
||||
Affliction mostSevereAffliction = SortAfflictionsBySeverity(afflictions).FirstOrDefault();
|
||||
GUIButton buttonToSelect = null;
|
||||
|
||||
foreach (Affliction affliction in afflictions)
|
||||
{
|
||||
displayedAfflictions.Add((affliction, affliction.Strength));
|
||||
|
||||
var child = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.3f), afflictionIconContainer.Content.RectTransform, Anchor.TopCenter))
|
||||
{
|
||||
Stretch = true,
|
||||
@@ -1233,6 +1228,39 @@ namespace Barotrauma
|
||||
child.Recalculate();
|
||||
}
|
||||
|
||||
buttonToSelect?.OnClicked(buttonToSelect, "selectaffliction");
|
||||
afflictionIconContainer.RecalculateChildren();
|
||||
}
|
||||
|
||||
private void CreateRecommendedTreatments()
|
||||
{
|
||||
ItemPrefab prevHighlightedItem = null;
|
||||
if (GUI.MouseOn?.UserData is ItemPrefab && recommendedTreatmentContainer.Content.IsParentOf(GUI.MouseOn))
|
||||
{
|
||||
prevHighlightedItem = (ItemPrefab)GUI.MouseOn.UserData;
|
||||
}
|
||||
|
||||
recommendedTreatmentContainer.Content.ClearChildren();
|
||||
|
||||
float characterSkillLevel = Character.Controlled == null ? 0.0f : Character.Controlled.GetSkillLevel("medical");
|
||||
|
||||
//key = item identifier
|
||||
//float = suitability
|
||||
Dictionary<string, float> treatmentSuitability = new Dictionary<string, float>();
|
||||
GetSuitableTreatments(treatmentSuitability,
|
||||
normalize: true,
|
||||
ignoreHiddenAfflictions: true,
|
||||
limb: selectedLimbIndex == -1 ? null : Character.AnimController.Limbs.Find(l => l.HealthIndex == selectedLimbIndex));
|
||||
|
||||
foreach (string treatment in treatmentSuitability.Keys.ToList())
|
||||
{
|
||||
//prefer suggestions for items the player has
|
||||
if (Character.Controlled.Inventory.FindItemByIdentifier(treatment) != null)
|
||||
{
|
||||
treatmentSuitability[treatment] *= 10.0f;
|
||||
}
|
||||
}
|
||||
|
||||
if (!treatmentSuitability.Any())
|
||||
{
|
||||
new GUITextBlock(new RectTransform(Vector2.One, recommendedTreatmentContainer.Content.RectTransform), TextManager.Get("none"), textAlignment: Alignment.Center)
|
||||
@@ -1248,10 +1276,6 @@ namespace Barotrauma
|
||||
recommendedTreatmentContainer.AutoHideScrollBar = true;
|
||||
}
|
||||
|
||||
buttonToSelect?.OnClicked(buttonToSelect, "selectaffliction");
|
||||
|
||||
afflictionIconContainer.RecalculateChildren();
|
||||
|
||||
List<KeyValuePair<string, float>> treatmentSuitabilities = treatmentSuitability.OrderByDescending(t => t.Value).ToList();
|
||||
|
||||
int count = 0;
|
||||
@@ -1286,7 +1310,7 @@ namespace Barotrauma
|
||||
new GUIImage(new RectTransform(Vector2.One, innerFrame.RectTransform, Anchor.Center), style: "TalentBackgroundGlow")
|
||||
{
|
||||
CanBeFocused = false,
|
||||
Color = Color.White * 0.7f,
|
||||
Color = GUI.Style.Green,
|
||||
HoverColor = Color.White,
|
||||
PressedColor = Color.DarkGray,
|
||||
SelectedColor = Color.Transparent,
|
||||
@@ -1304,6 +1328,12 @@ namespace Barotrauma
|
||||
SelectedColor = itemColor,
|
||||
DisabledColor = itemColor * 0.8f
|
||||
};
|
||||
|
||||
if (item == prevHighlightedItem)
|
||||
{
|
||||
innerFrame.State = GUIComponent.ComponentState.Hover;
|
||||
innerFrame.Children.ForEach(c => c.State = GUIComponent.ComponentState.Hover);
|
||||
}
|
||||
}
|
||||
|
||||
recommendedTreatmentContainer.RecalculateChildren();
|
||||
@@ -1315,6 +1345,19 @@ namespace Barotrauma
|
||||
int dmgPerSecond = Math.Sign(second.DamagePerSecond - first.DamagePerSecond);
|
||||
return dmgPerSecond != 0 ? dmgPerSecond : Math.Sign(second.Strength - first.Strength);
|
||||
});
|
||||
|
||||
if (count > 0)
|
||||
{
|
||||
var treatmentIconSize = recommendedTreatmentContainer.Content.Children.Sum(c => c.Rect.Width + recommendedTreatmentContainer.Spacing);
|
||||
if (treatmentIconSize < recommendedTreatmentContainer.Content.Rect.Width)
|
||||
{
|
||||
var spacing = new GUIFrame(new RectTransform(new Point((recommendedTreatmentContainer.Content.Rect.Width - treatmentIconSize) / 2, 0), recommendedTreatmentContainer.Content.RectTransform), style: null)
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
spacing.RectTransform.SetAsFirstChild();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void CreateAfflictionInfoElements(GUIComponent parent, Affliction affliction)
|
||||
|
||||
@@ -120,6 +120,15 @@ namespace Barotrauma
|
||||
public List<SpriteDeformation> ActiveDeformations { get; set; } = new List<SpriteDeformation>();
|
||||
|
||||
public Sprite Sprite { get; protected set; }
|
||||
public Sprite TintMask { get; protected set; }
|
||||
|
||||
public Sprite HuskMask { get; protected set; }
|
||||
public float TintHighlightThreshold { get; protected set; }
|
||||
public float TintHighlightMultiplier { get; protected set; }
|
||||
|
||||
private SpriteBatch.EffectWithParams tintEffectParams;
|
||||
private SpriteBatch.EffectWithParams huskSpriteParams;
|
||||
|
||||
|
||||
protected DeformableSprite _deformSprite;
|
||||
|
||||
@@ -273,6 +282,7 @@ namespace Barotrauma
|
||||
DecorativeSpriteGroups[groupID].Add(decorativeSprite);
|
||||
spriteAnimState.Add(decorativeSprite, new SpriteState());
|
||||
}
|
||||
TintMask = null;
|
||||
foreach (XElement subElement in element.Elements())
|
||||
{
|
||||
switch (subElement.Name.ToString().ToLowerInvariant())
|
||||
@@ -308,6 +318,22 @@ namespace Barotrauma
|
||||
InitialLightSourceColor = LightSource.Color;
|
||||
InitialLightSpriteAlpha = LightSource.OverrideLightSpriteAlpha;
|
||||
break;
|
||||
case "tintmask":
|
||||
string tintMaskPath = subElement.GetAttributeString("texture", "");
|
||||
if (!string.IsNullOrWhiteSpace(tintMaskPath))
|
||||
{
|
||||
TintMask = new Sprite(subElement, file: GetSpritePath(tintMaskPath));
|
||||
TintHighlightThreshold = subElement.GetAttributeFloat("highlightthreshold", 0.6f);
|
||||
TintHighlightMultiplier = subElement.GetAttributeFloat("highlightmultiplier", 0.8f);
|
||||
}
|
||||
break;
|
||||
case "huskmask":
|
||||
string huskMaskPath = subElement.GetAttributeString("texture", "");
|
||||
if (!string.IsNullOrWhiteSpace(huskMaskPath))
|
||||
{
|
||||
HuskMask = new Sprite(subElement, file: GetSpritePath(huskMaskPath));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
ISerializableEntity GetConditionalTarget()
|
||||
@@ -449,20 +475,20 @@ namespace Barotrauma
|
||||
/// <summary>
|
||||
/// Get the full path of a limb sprite, taking into account tags, gender and head id
|
||||
/// </summary>
|
||||
private string GetSpritePath(string texturePath)
|
||||
public static string GetSpritePath(string texturePath, CharacterInfo characterInfo)
|
||||
{
|
||||
string spritePath = texturePath;
|
||||
string spritePathWithTags = spritePath;
|
||||
if (character.Info != null && character.IsHumanoid)
|
||||
if (characterInfo != null)
|
||||
{
|
||||
spritePath = spritePath.Replace("[GENDER]", (character.Info.Gender == Gender.Female) ? "female" : "male");
|
||||
spritePath = spritePath.Replace("[RACE]", character.Info.Race.ToString().ToLowerInvariant());
|
||||
spritePath = spritePath.Replace("[HEADID]", character.Info.HeadSpriteId.ToString());
|
||||
spritePath = spritePath.Replace("[GENDER]", (characterInfo.Gender == Gender.Female) ? "female" : "male");
|
||||
spritePath = spritePath.Replace("[RACE]", characterInfo.Race.ToString().ToLowerInvariant());
|
||||
spritePath = spritePath.Replace("[HEADID]", characterInfo.HeadSpriteId.ToString());
|
||||
|
||||
if (character.Info.HeadSprite != null && character.Info.SpriteTags.Any())
|
||||
if (characterInfo.HeadSprite != null && characterInfo.SpriteTags.Any())
|
||||
{
|
||||
string tags = "";
|
||||
character.Info.SpriteTags.ForEach(tag => tags += "[" + tag + "]");
|
||||
characterInfo.SpriteTags.ForEach(tag => tags += "[" + tag + "]");
|
||||
|
||||
spritePathWithTags = Path.Combine(
|
||||
Path.GetDirectoryName(spritePath),
|
||||
@@ -472,6 +498,13 @@ namespace Barotrauma
|
||||
return File.Exists(spritePathWithTags) ? spritePathWithTags : spritePath;
|
||||
}
|
||||
|
||||
|
||||
private string GetSpritePath(string texturePath)
|
||||
{
|
||||
if (!character.IsHumanoid) { return texturePath; }
|
||||
return GetSpritePath(texturePath, character?.Info);
|
||||
}
|
||||
|
||||
partial void LoadParamsProjSpecific()
|
||||
{
|
||||
bool isFlipped = dir == Direction.Left;
|
||||
@@ -638,13 +671,24 @@ namespace Barotrauma
|
||||
var spriteParams = Params.GetSprite();
|
||||
if (spriteParams == null) { return; }
|
||||
|
||||
Color color = new Color(spriteParams.Color.R / 255f * brightness, spriteParams.Color.G / 255f * brightness, spriteParams.Color.B / 255f * brightness, spriteParams.Color.A / 255f);
|
||||
Color clr = spriteParams.Color;
|
||||
if (!spriteParams.IgnoreTint)
|
||||
{
|
||||
clr = clr.Multiply(ragdoll.RagdollParams.Color);
|
||||
if (character.Info != null)
|
||||
{
|
||||
clr = clr.Multiply(character.Info.SkinColor);
|
||||
}
|
||||
}
|
||||
Color color = new Color((byte)(clr.R * brightness), (byte)(clr.G * brightness), (byte)(clr.B * brightness), clr.A);
|
||||
Color blankColor = new Color(brightness, brightness, brightness, 1);
|
||||
if (deadTimer > 0)
|
||||
{
|
||||
color = Color.Lerp(color, spriteParams.DeadColor, MathUtils.InverseLerp(0, spriteParams.DeadColorTime, deadTimer));
|
||||
}
|
||||
|
||||
color = overrideColor ?? color;
|
||||
blankColor = overrideColor ?? blankColor;
|
||||
|
||||
if (isSevered)
|
||||
{
|
||||
@@ -667,6 +711,8 @@ namespace Barotrauma
|
||||
OtherWearables.Any(w => w.HideLimb) ||
|
||||
wearingItems.Any(w => w != null && w.HideLimb);
|
||||
|
||||
bool drawHuskSprite = HuskSprite != null && !wearableTypesToHide.Contains(WearableType.Husk);
|
||||
|
||||
var activeSprite = ActiveSprite;
|
||||
if (type == LimbType.Head)
|
||||
{
|
||||
@@ -698,7 +744,33 @@ namespace Barotrauma
|
||||
}
|
||||
else
|
||||
{
|
||||
bool useTintMask = TintMask != null && spriteBatch.GetCurrentEffect() is null;
|
||||
if (useTintMask)
|
||||
{
|
||||
tintEffectParams.Effect ??= GameMain.GameScreen.ThresholdTintEffect;
|
||||
tintEffectParams.Params ??= new Dictionary<string, object>();
|
||||
var parameters = tintEffectParams.Params;
|
||||
parameters["xBaseTexture"] = Sprite.Texture;
|
||||
parameters["xTintMaskTexture"] = TintMask.Texture;
|
||||
if (drawHuskSprite && HuskMask != null)
|
||||
{
|
||||
parameters["xCutoffTexture"] = HuskMask.Texture;
|
||||
parameters["baseToCutoffSizeRatio"] = (float)Sprite.Texture.Width / (float)HuskMask.Texture.Width;
|
||||
}
|
||||
else
|
||||
{
|
||||
parameters["xCutoffTexture"] = GUI.WhiteTexture;
|
||||
parameters["baseToCutoffSizeRatio"] = 1.0f;
|
||||
}
|
||||
parameters["highlightThreshold"] = TintHighlightThreshold;
|
||||
parameters["highlightMultiplier"] = TintHighlightMultiplier;
|
||||
spriteBatch.SwapEffect(tintEffectParams);
|
||||
}
|
||||
body.Draw(spriteBatch, activeSprite, color, null, Scale * TextureScale, Params.MirrorHorizontally, Params.MirrorVertically);
|
||||
if (useTintMask)
|
||||
{
|
||||
spriteBatch.SwapEffect(null);
|
||||
}
|
||||
}
|
||||
// Handle non-exlusive, i.e. additional conditional sprites
|
||||
foreach (var conditionalSprite in ConditionalSprites)
|
||||
@@ -770,15 +842,36 @@ namespace Barotrauma
|
||||
}
|
||||
if (onlyDrawable == null)
|
||||
{
|
||||
if (HerpesSprite != null && !wearableTypesToHide.Contains(WearableType.Herpes))
|
||||
if (HerpesSprite != null && !wearableTypesToHide.Contains(WearableType.Herpes) && herpesStrength > 0)
|
||||
{
|
||||
DrawWearable(HerpesSprite, depthStep, spriteBatch, color * Math.Min(herpesStrength / 10.0f, 1.0f), spriteEffect);
|
||||
float alpha = Math.Min(herpesStrength * 2 / 100.0f, 1.0f);
|
||||
DrawWearable(HerpesSprite, depthStep, spriteBatch, blankColor, alpha: alpha, spriteEffect);
|
||||
depthStep += step;
|
||||
}
|
||||
if (drawHuskSprite)
|
||||
{
|
||||
bool useTintEffect = HuskMask != null && spriteBatch.GetCurrentEffect() is null;
|
||||
if (useTintEffect)
|
||||
{
|
||||
huskSpriteParams.Effect ??= GameMain.GameScreen.ThresholdTintEffect;
|
||||
huskSpriteParams.Params ??= new Dictionary<string, object>();
|
||||
var parameters = huskSpriteParams.Params;
|
||||
parameters["xCutoffTexture"] = GUI.WhiteTexture;
|
||||
parameters["baseToCutoffSizeRatio"] = 1.0f;
|
||||
spriteBatch.SwapEffect(huskSpriteParams);
|
||||
}
|
||||
DrawWearable(HuskSprite, depthStep, spriteBatch, color, alpha: color.A / 255f, spriteEffect);
|
||||
if (useTintEffect)
|
||||
{
|
||||
spriteBatch.SwapEffect(null);
|
||||
}
|
||||
depthStep += step;
|
||||
}
|
||||
foreach (WearableSprite wearable in OtherWearables)
|
||||
{
|
||||
if (wearable.Type == WearableType.Husk) { continue; }
|
||||
if (wearableTypesToHide.Contains(wearable.Type)) { continue; }
|
||||
DrawWearable(wearable, depthStep, spriteBatch, color, spriteEffect);
|
||||
DrawWearable(wearable, depthStep, spriteBatch, blankColor, alpha: color.A / 255f, spriteEffect);
|
||||
//if there are multiple sprites on this limb, make the successive ones be drawn in front
|
||||
depthStep += step;
|
||||
}
|
||||
@@ -786,7 +879,7 @@ namespace Barotrauma
|
||||
foreach (WearableSprite wearable in WearingItems)
|
||||
{
|
||||
if (onlyDrawable != null && onlyDrawable != wearable) continue;
|
||||
DrawWearable(wearable, depthStep, spriteBatch, color, spriteEffect);
|
||||
DrawWearable(wearable, depthStep, spriteBatch, blankColor, alpha: color.A / 255f, spriteEffect);
|
||||
//if there are multiple sprites on this limb, make the successive ones be drawn in front
|
||||
depthStep += step;
|
||||
}
|
||||
@@ -936,7 +1029,7 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawWearable(WearableSprite wearable, float depthStep, SpriteBatch spriteBatch, Color color, SpriteEffects spriteEffect)
|
||||
private void DrawWearable(WearableSprite wearable, float depthStep, SpriteBatch spriteBatch, Color color, float alpha, SpriteEffects spriteEffect)
|
||||
{
|
||||
var sprite = ActiveSprite;
|
||||
if (wearable.InheritSourceRect)
|
||||
@@ -955,7 +1048,7 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
Vector2 origin = wearable.Sprite.Origin;
|
||||
Vector2 origin;
|
||||
if (wearable.InheritOrigin)
|
||||
{
|
||||
origin = sprite.Origin;
|
||||
@@ -986,7 +1079,7 @@ namespace Barotrauma
|
||||
Color wearableColor = Color.White;
|
||||
if (wearableItemComponent != null)
|
||||
{
|
||||
// Draw outer cloths on top of inner cloths.
|
||||
// Draw outer clothes on top of inner clothes.
|
||||
if (wearableItemComponent.AllowedSlots.Contains(InvSlotType.OuterClothes))
|
||||
{
|
||||
depth -= depthStep;
|
||||
@@ -997,15 +1090,38 @@ namespace Barotrauma
|
||||
}
|
||||
wearableColor = wearableItemComponent.Item.GetSpriteColor();
|
||||
}
|
||||
float textureScale = wearable.InheritTextureScale ? TextureScale : wearable.Scale;
|
||||
|
||||
else if (character.Info != null)
|
||||
{
|
||||
if (wearable.Type == WearableType.Hair)
|
||||
{
|
||||
wearableColor = character.Info.HairColor;
|
||||
}
|
||||
else if (wearable.Type == WearableType.Beard || wearable.Type == WearableType.Moustache)
|
||||
{
|
||||
wearableColor = character.Info.FacialHairColor;
|
||||
}
|
||||
}
|
||||
float scale = wearable.Scale;
|
||||
if (wearable.InheritScale)
|
||||
{
|
||||
if (!wearable.IgnoreTextureScale)
|
||||
{
|
||||
scale *= TextureScale;
|
||||
}
|
||||
if (!wearable.IgnoreLimbScale)
|
||||
{
|
||||
scale *= Params.Scale;
|
||||
}
|
||||
if (!wearable.IgnoreRagdollScale)
|
||||
{
|
||||
scale *= ragdoll.RagdollParams.LimbScale;
|
||||
}
|
||||
}
|
||||
float rotation = -body.DrawRotation - wearable.Rotation * Dir;
|
||||
|
||||
wearable.Sprite.Draw(spriteBatch,
|
||||
new Vector2(body.DrawPosition.X, -body.DrawPosition.Y),
|
||||
new Color((color.R * wearableColor.R) / (255.0f * 255.0f), (color.G * wearableColor.G) / (255.0f * 255.0f), (color.B * wearableColor.B) / (255.0f * 255.0f)) * ((color.A * wearableColor.A) / (255.0f * 255.0f)),
|
||||
origin, rotation,
|
||||
Scale * textureScale, spriteEffect, depth);
|
||||
float finalAlpha = alpha * wearableColor.A;
|
||||
Color finalColor = color.Multiply(wearableColor);
|
||||
finalColor = new Color(finalColor.R, finalColor.G, finalColor.B, (byte)finalAlpha);
|
||||
wearable.Sprite.Draw(spriteBatch, new Vector2(body.DrawPosition.X, -body.DrawPosition.Y), finalColor, origin, rotation, scale, spriteEffect, depth);
|
||||
}
|
||||
|
||||
private WearableSprite GetWearableSprite(WearableType type, bool random = false)
|
||||
@@ -1056,6 +1172,9 @@ namespace Barotrauma
|
||||
|
||||
HerpesSprite?.Sprite.Remove();
|
||||
HerpesSprite = null;
|
||||
|
||||
TintMask?.Remove();
|
||||
TintMask = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < ResourceClusters.Count; i++)
|
||||
for (int i = 0; i < resourceClusters.Count; i++)
|
||||
{
|
||||
var amount = msg.ReadByte();
|
||||
var rotation = msg.ReadSingle();
|
||||
@@ -41,20 +41,20 @@ namespace Barotrauma
|
||||
h.AttachToWall();
|
||||
item.Rotation = rotation;
|
||||
}
|
||||
if (SpawnedResources.TryGetValue(item.Prefab.Identifier, out var resources))
|
||||
if (spawnedResources.TryGetValue(item.Prefab.Identifier, out var resources))
|
||||
{
|
||||
resources.Add(item);
|
||||
}
|
||||
else
|
||||
{
|
||||
SpawnedResources.Add(item.Prefab.Identifier, new List<Item>() { item });
|
||||
spawnedResources.Add(item.Prefab.Identifier, new List<Item>() { item });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CalculateMissionClusterPositions();
|
||||
|
||||
for(int i = 0; i < ResourceClusters.Count; i++)
|
||||
for(int i = 0; i < resourceClusters.Count; i++)
|
||||
{
|
||||
var identifier = msg.ReadString();
|
||||
var count = msg.ReadByte();
|
||||
@@ -66,7 +66,7 @@ namespace Barotrauma
|
||||
if (!(entity is Item item)) { continue; }
|
||||
resources[j] = item;
|
||||
}
|
||||
RelevantLevelResources.Add(identifier, resources);
|
||||
relevantLevelResources.Add(identifier, resources);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
|
||||
namespace Barotrauma.Extensions
|
||||
{
|
||||
public static class ColorExtensions
|
||||
{
|
||||
public static Color Multiply(this Color color, float value, bool onlyAlpha = false)
|
||||
{
|
||||
return onlyAlpha ?
|
||||
new Color(color.R, color.G, color.B, (byte)(color.A * value)) :
|
||||
new Color((byte)(color.R * value), (byte)(color.G * value), (byte)(color.B * value), (byte)(color.A * value));
|
||||
}
|
||||
|
||||
public static Color Opaque(this Color color)
|
||||
{
|
||||
return new Color(color.R, color.G, color.B, (byte)255);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -130,6 +130,7 @@ namespace Barotrauma
|
||||
public static GUIStyle Style;
|
||||
|
||||
private static Texture2D t;
|
||||
public static Texture2D WhiteTexture => t;
|
||||
private static Sprite[] MouseCursorSprites => Style.CursorSprite;
|
||||
|
||||
private static bool debugDrawSounds, debugDrawEvents, debugDrawMetadata;
|
||||
@@ -862,11 +863,10 @@ namespace Barotrauma
|
||||
int index = 0;
|
||||
if (updateList.Count > 0)
|
||||
{
|
||||
index = updateList.Count - 1;
|
||||
while (updateList[index].UpdateOrder > item.UpdateOrder)
|
||||
index = updateList.Count;
|
||||
while (index > 0 && updateList[index-1].UpdateOrder > item.UpdateOrder)
|
||||
{
|
||||
index--;
|
||||
if (index == 0) { break; }
|
||||
}
|
||||
}
|
||||
if (!updateListSet.Contains(item))
|
||||
@@ -1057,12 +1057,15 @@ namespace Barotrauma
|
||||
if (listBox.DraggedElement != null) { return CursorState.Dragging; }
|
||||
if (listBox.CanDragElements) { return CursorState.Move; }
|
||||
|
||||
var hoverParent = c;
|
||||
while (true)
|
||||
if (listBox.HoverCursor != CursorState.Default)
|
||||
{
|
||||
if (hoverParent == parent || hoverParent == null) { break; }
|
||||
if (hoverParent.State == GUIComponent.ComponentState.Hover) { return CursorState.Hand; }
|
||||
hoverParent = hoverParent.Parent;
|
||||
var hoverParent = c;
|
||||
while (true)
|
||||
{
|
||||
if (hoverParent == parent || hoverParent == null) { break; }
|
||||
if (hoverParent.State == GUIComponent.ComponentState.Hover) { return CursorState.Hand; }
|
||||
hoverParent = hoverParent.Parent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,8 @@ namespace Barotrauma
|
||||
private bool selectMultiple;
|
||||
|
||||
public bool Dropped { get; set; }
|
||||
|
||||
public bool AllowNonText { get; set; }
|
||||
|
||||
public object SelectedItemData
|
||||
{
|
||||
@@ -318,9 +320,9 @@ namespace Barotrauma
|
||||
if (textBlock == null)
|
||||
{
|
||||
textBlock = component.GetChild<GUITextBlock>();
|
||||
if (textBlock == null) return false;
|
||||
if (textBlock is null && !AllowNonText) { return false; }
|
||||
}
|
||||
button.Text = textBlock.Text;
|
||||
button.Text = textBlock?.Text ?? "";
|
||||
}
|
||||
Dropped = false;
|
||||
// TODO: OnSelected can be called multiple times and when it shouldn't be called -> turn into an event so that nobody else can call it.
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace Barotrauma
|
||||
{
|
||||
private Dictionary<string, GUIComponentStyle> componentStyles;
|
||||
|
||||
private XElement configElement;
|
||||
private readonly XElement configElement;
|
||||
|
||||
private GraphicsDevice graphicsDevice;
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace Barotrauma
|
||||
private static UISprite spectateIcon, disconnectedIcon;
|
||||
private static Sprite ownerIcon, moderatorIcon;
|
||||
|
||||
public enum InfoFrameTab { Crew, Mission, Reputation, MyCharacter, Traitor, Submarine, Talents };
|
||||
public enum InfoFrameTab { Crew, Mission, Reputation, Traitor, Submarine, Talents };
|
||||
public static InfoFrameTab selectedTab;
|
||||
private GUIFrame infoFrame, contentFrame;
|
||||
|
||||
@@ -34,6 +34,8 @@ namespace Barotrauma
|
||||
private List<CharacterTeamType> teamIDs;
|
||||
private const string inLobbyString = "\u2022 \u2022 \u2022";
|
||||
|
||||
private GUIFrame pendingChangesFrame = null;
|
||||
|
||||
public static Color OwnCharacterBGColor = Color.Gold * 0.7f;
|
||||
|
||||
private class LinkedGUI
|
||||
@@ -134,6 +136,13 @@ namespace Barotrauma
|
||||
|
||||
public void Update()
|
||||
{
|
||||
GameSession.UpdateTalentNotificationIndicator(talentPointNotification);
|
||||
if (Character.Controlled is { } controlled && talentResetButton != null && talentApplyButton != null)
|
||||
{
|
||||
int talentCount = selectedTalents.Count - controlled.Info.UnlockedTalents.Count;
|
||||
talentResetButton.Enabled = talentApplyButton.Enabled = talentCount > 0;
|
||||
}
|
||||
|
||||
if (selectedTab != InfoFrameTab.Crew) return;
|
||||
if (linkedGUIList == null) return;
|
||||
|
||||
@@ -183,16 +192,8 @@ namespace Barotrauma
|
||||
new GUIFrame(new RectTransform(GUI.Canvas.RelativeSize, infoFrame.RectTransform, Anchor.Center), style: "GUIBackgroundBlocker");
|
||||
|
||||
//this used to be a switch expression but i changed it because it killed enc :(
|
||||
Vector2 contentFrameSize;
|
||||
switch (selectedTab)
|
||||
{
|
||||
case InfoFrameTab.MyCharacter:
|
||||
contentFrameSize = new Vector2(0.45f, 0.5f);
|
||||
break;
|
||||
default:
|
||||
contentFrameSize = new Vector2(0.45f, 0.667f);
|
||||
break;
|
||||
}
|
||||
//now it's not even a switch statement anymore :(
|
||||
Vector2 contentFrameSize = new Vector2(0.45f, 0.667f);
|
||||
contentFrame = new GUIFrame(new RectTransform(contentFrameSize, infoFrame.RectTransform, Anchor.TopCenter, Pivot.TopCenter) { RelativeOffset = new Vector2(0.0f, 0.12f) });
|
||||
|
||||
var horizontalLayoutGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.958f, 0.943f), contentFrame.RectTransform, Anchor.TopCenter, Pivot.TopCenter) { AbsoluteOffset = new Point(0, GUI.IntScale(25f)) }, isHorizontal: true)
|
||||
@@ -243,6 +244,17 @@ namespace Barotrauma
|
||||
{
|
||||
TextGetter = () => TextManager.GetWithVariable("campaignmoney", "[money]", string.Format(CultureInfo.InvariantCulture, "{0:N0}", campaignMode.Money))
|
||||
};
|
||||
GUIFrame bottomDisclaimerFrame = new GUIFrame(new RectTransform(new Vector2(contentFrameSize.X, 0.1f), infoFrame.RectTransform)
|
||||
{
|
||||
AbsoluteOffset = new Point(contentFrame.Rect.X, contentFrame.Rect.Bottom + GUI.IntScale(8))
|
||||
}, style: null);
|
||||
|
||||
pendingChangesFrame = new GUIFrame(new RectTransform(Vector2.One, bottomDisclaimerFrame.RectTransform, Anchor.Center), style: null);
|
||||
|
||||
if (GameMain.NetLobbyScreen?.CampaignCharacterDiscarded ?? false)
|
||||
{
|
||||
NetLobbyScreen.CreateChangesPendingFrame(pendingChangesFrame);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -255,20 +267,17 @@ namespace Barotrauma
|
||||
|
||||
var submarineButton = createTabButton(InfoFrameTab.Submarine, "submarine");
|
||||
|
||||
if (GameMain.NetworkMember != null)
|
||||
var talentsButton = createTabButton(InfoFrameTab.Talents, "tabmenu.character");
|
||||
talentsButton.OnAddedToGUIUpdateList += (component) =>
|
||||
{
|
||||
var myCharacterButton = createTabButton(InfoFrameTab.MyCharacter, "tabmenu.character");
|
||||
}
|
||||
|
||||
var talentsButton = createTabButton(InfoFrameTab.Talents, "tabmenu.talents");
|
||||
talentsButton.OnAddedToGUIUpdateList += (GUIComponent component) =>
|
||||
{
|
||||
talentsButton.Enabled = Character.Controlled?.Info != null && (GameMain.GameSession?.Campaign != null || Screen.Selected == GameMain.TestScreen || GameMain.GameSession.GameMode is TestGameMode);
|
||||
talentsButton.Enabled = Character.Controlled?.Info != null;
|
||||
if (!talentsButton.Enabled && selectedTab == InfoFrameTab.Talents)
|
||||
{
|
||||
SelectInfoFrameTab(null, InfoFrameTab.Crew);
|
||||
}
|
||||
};
|
||||
|
||||
talentPointNotification = GameSession.CreateTalentIconNotification(talentsButton);
|
||||
}
|
||||
|
||||
private bool SelectInfoFrameTab(GUIButton button, object userData)
|
||||
@@ -300,10 +309,6 @@ namespace Barotrauma
|
||||
if (traitor == null || traitorMission == null) return false;
|
||||
CreateTraitorInfo(infoFrameHolder, traitorMission, traitor);
|
||||
break;
|
||||
case InfoFrameTab.MyCharacter:
|
||||
if (GameMain.NetworkMember == null) { return false; }
|
||||
GameMain.NetLobbyScreen.CreatePlayerFrame(infoFrameHolder);
|
||||
break;
|
||||
case InfoFrameTab.Submarine:
|
||||
CreateSubmarineInfo(infoFrameHolder, Submarine.MainSub);
|
||||
break;
|
||||
@@ -1188,6 +1193,11 @@ namespace Barotrauma
|
||||
private GUITextBlock talentPointText;
|
||||
private GUIListBox skillListBox;
|
||||
|
||||
private GUIButton talentApplyButton,
|
||||
talentResetButton;
|
||||
|
||||
private GUIImage talentPointNotification;
|
||||
|
||||
private readonly ImmutableDictionary<TalentTree.TalentTreeStageState, GUIComponentStyle> talentStageStyles = new Dictionary<TalentTree.TalentTreeStageState, GUIComponentStyle>
|
||||
{
|
||||
{ TalentTree.TalentTreeStageState.Invalid, GUI.Style.GetComponentStyle("TalentTreeLocked") },
|
||||
@@ -1219,9 +1229,22 @@ namespace Barotrauma
|
||||
int padding = GUI.IntScale(15);
|
||||
GUIFrame talentFrameContent = new GUIFrame(new RectTransform(new Point(talentFrameBackground.Rect.Width - padding, talentFrameBackground.Rect.Height - padding), infoFrame.RectTransform, Anchor.Center), style: null);
|
||||
|
||||
GUIFrame paddedTalentFrame = new GUIFrame(new RectTransform(new Vector2(0.9f), talentFrameContent.RectTransform, Anchor.Center), style: null);
|
||||
GUIFrame paddedTalentFrame = new GUIFrame(new RectTransform(new Vector2(1f, 0.9f), talentFrameContent.RectTransform, Anchor.Center), style: null);
|
||||
|
||||
if (controlledCharacter.Info == null)
|
||||
GUIFrame talentFrameMain = new GUIFrame(new RectTransform(Vector2.One, paddedTalentFrame.RectTransform), style: null);
|
||||
|
||||
GUIFrame characterSettingsFrame = null;
|
||||
GUILayoutGroup characterLayout = null;
|
||||
if (!(GameMain.NetworkMember is null))
|
||||
{
|
||||
characterSettingsFrame = new GUIFrame(new RectTransform(Vector2.One, talentFrameContent.RectTransform), style: null) { Visible = false };
|
||||
characterLayout = new GUILayoutGroup(new RectTransform(Vector2.One, characterSettingsFrame.RectTransform));
|
||||
GUIFrame containerFrame = new GUIFrame(new RectTransform(new Vector2(1f, 0.9f), characterLayout.RectTransform), style: null);
|
||||
GUIFrame playerFrame = new GUIFrame(new RectTransform(new Vector2(0.9f, 0.7f), containerFrame.RectTransform, Anchor.Center), style: null);
|
||||
GameMain.NetLobbyScreen.CreatePlayerFrame(playerFrame, alwaysAllowEditing: true, createPendingText: false);
|
||||
}
|
||||
|
||||
if (controlledCharacter.Info is null)
|
||||
{
|
||||
DebugConsole.ThrowError("No character info found for talent UI");
|
||||
return;
|
||||
@@ -1229,7 +1252,7 @@ namespace Barotrauma
|
||||
|
||||
selectedTalents = controlledCharacter.Info.UnlockedTalents.ToList();
|
||||
|
||||
GUILayoutGroup talentFrameLayoutGroup = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 1.0f), paddedTalentFrame.RectTransform, anchor: Anchor.Center), childAnchor: Anchor.TopCenter)
|
||||
GUILayoutGroup talentFrameLayoutGroup = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 1.0f), talentFrameMain.RectTransform, anchor: Anchor.Center), childAnchor: Anchor.TopCenter)
|
||||
{
|
||||
AbsoluteSpacing = GUI.IntScale(5)
|
||||
};
|
||||
@@ -1241,11 +1264,11 @@ namespace Barotrauma
|
||||
|
||||
new GUICustomComponent(new RectTransform(new Vector2(0.25f, 1f), talentInfoLayoutGroup.RectTransform), onDraw: (batch, component) =>
|
||||
{
|
||||
float posY = component.Rect.Bottom - component.Rect.Width;
|
||||
float posY = component.Rect.Center.Y - component.Rect.Width / 2;
|
||||
info.DrawPortrait(batch, new Vector2(component.Rect.X, posY), Vector2.Zero, component.Rect.Width, false, false);
|
||||
});
|
||||
|
||||
GUILayoutGroup nameLayout = new GUILayoutGroup(new RectTransform(new Vector2(0.375f, 1f), talentInfoLayoutGroup.RectTransform));
|
||||
GUILayoutGroup nameLayout = new GUILayoutGroup(new RectTransform(new Vector2(0.3f, 1f), talentInfoLayoutGroup.RectTransform)) { RelativeSpacing = 0.05f };
|
||||
|
||||
Vector2 nameSize = GUI.SubHeadingFont.MeasureString(info.Name);
|
||||
GUITextBlock nameBlock = new GUITextBlock(new RectTransform(Vector2.One, nameLayout.RectTransform), info.Name, font: GUI.SubHeadingFont) { TextColor = job.Prefab.UIColor };
|
||||
@@ -1260,7 +1283,56 @@ namespace Barotrauma
|
||||
GUITextBlock traitBlock = new GUITextBlock(new RectTransform(Vector2.One, nameLayout.RectTransform), traitString, font: GUI.SmallFont);
|
||||
traitBlock.RectTransform.NonScaledSize = traitSize.Pad(traitBlock.Padding).ToPoint();
|
||||
|
||||
GUILayoutGroup skillLayout = new GUILayoutGroup(new RectTransform(new Vector2(0.375f, 1f), talentInfoLayoutGroup.RectTransform)) { Stretch = true };
|
||||
if (!(GameMain.NetworkMember is null))
|
||||
{
|
||||
GUIButton newCharacterBox = new GUIButton(new RectTransform(Vector2.One, nameLayout.RectTransform, Anchor.BottomCenter), text: GameMain.NetLobbyScreen.CampaignCharacterDiscarded ? TextManager.Get("settings") : TextManager.Get("createnew"))
|
||||
{
|
||||
IgnoreLayoutGroups = true
|
||||
};
|
||||
|
||||
newCharacterBox.OnClicked = (button, o) =>
|
||||
{
|
||||
if (!GameMain.NetLobbyScreen.CampaignCharacterDiscarded)
|
||||
{
|
||||
GameMain.NetLobbyScreen.TryDiscardCampaignCharacter(() =>
|
||||
{
|
||||
newCharacterBox.Text = TextManager.Get("settings");
|
||||
|
||||
if (pendingChangesFrame != null)
|
||||
{
|
||||
NetLobbyScreen.CreateChangesPendingFrame(pendingChangesFrame);
|
||||
}
|
||||
OpenMenu();
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
OpenMenu();
|
||||
return true;
|
||||
|
||||
void OpenMenu()
|
||||
{
|
||||
characterSettingsFrame!.Visible = true;
|
||||
talentFrameMain.Visible = false;
|
||||
}
|
||||
};
|
||||
|
||||
if (!(characterLayout is null))
|
||||
{
|
||||
GUILayoutGroup characterCloseButtonLayout = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.1f), characterLayout.RectTransform), childAnchor: Anchor.BottomRight);
|
||||
new GUIButton(new RectTransform(new Vector2(0.4f, 1f), characterCloseButtonLayout.RectTransform), TextManager.Get("close"))
|
||||
{
|
||||
OnClicked = (button, o) =>
|
||||
{
|
||||
characterSettingsFrame!.Visible = false;
|
||||
talentFrameMain.Visible = true;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
GUILayoutGroup skillLayout = new GUILayoutGroup(new RectTransform(new Vector2(0.45f, 1f), talentInfoLayoutGroup.RectTransform)) { Stretch = true };
|
||||
|
||||
string skillString = TextManager.Get("skills");
|
||||
Vector2 skillSize = GUI.SubHeadingFont.MeasureString(skillString);
|
||||
@@ -1276,6 +1348,7 @@ namespace Barotrauma
|
||||
|
||||
GUIListBox talentTreeListBox = new GUIListBox(new RectTransform(new Vector2(1f, 0.7f), talentFrameLayoutGroup.RectTransform, Anchor.TopCenter), isHorizontal: true, style: null);
|
||||
|
||||
List<GUITextBlock> subTreeNames = new List<GUITextBlock>();
|
||||
foreach (var subTree in talentTree.TalentSubTrees)
|
||||
{
|
||||
GUIFrame subTreeFrame = new GUIFrame(new RectTransform(new Vector2(0.333f, 1f), talentTreeListBox.Content.RectTransform, anchor: Anchor.TopLeft), style: null);
|
||||
@@ -1285,7 +1358,7 @@ namespace Barotrauma
|
||||
int elementPadding = GUI.IntScale(8);
|
||||
Point headerSize = subtreeTitleFrame.RectTransform.NonScaledSize;
|
||||
GUIFrame subTreeTitleBackground = new GUIFrame(new RectTransform(new Point(headerSize.X - elementPadding, headerSize.Y), subtreeTitleFrame.RectTransform, anchor: Anchor.Center), style: "SubtreeHeader");
|
||||
new GUITextBlock(new RectTransform(Vector2.One, subTreeTitleBackground.RectTransform, anchor: Anchor.TopCenter), subTree.DisplayName, font: GUI.LargeFont, textAlignment: Alignment.Center);
|
||||
subTreeNames.Add(new GUITextBlock(new RectTransform(Vector2.One, subTreeTitleBackground.RectTransform, anchor: Anchor.TopCenter), subTree.DisplayName, font: GUI.SubHeadingFont, textAlignment: Alignment.Center));
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
@@ -1296,7 +1369,7 @@ namespace Barotrauma
|
||||
GUIFrame talentBackground = new GUIFrame(new RectTransform(new Point(talentFrameSize.X - elementPadding, talentFrameSize.Y - elementPadding), talentOptionFrame.RectTransform, anchor: Anchor.Center), style: "TalentBackground");
|
||||
GUIFrame talentBackgroundHighlight = new GUIFrame(new RectTransform(Vector2.One, talentBackground.RectTransform, anchor: Anchor.Center), style: "TalentBackgroundGlow") { Visible = false };
|
||||
|
||||
GUIImage cornerIcon = new GUIImage(new RectTransform(new Vector2(0.25f), talentOptionFrame.RectTransform, anchor: Anchor.BottomRight, scaleBasis: ScaleBasis.BothHeight), style: null)
|
||||
GUIImage cornerIcon = new GUIImage(new RectTransform(new Vector2(0.2f), talentOptionFrame.RectTransform, anchor: Anchor.BottomRight, scaleBasis: ScaleBasis.BothHeight) { MaxSize = new Point(16) }, style: null)
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
@@ -1316,10 +1389,12 @@ namespace Barotrauma
|
||||
{
|
||||
GUIFrame talentFrame = new GUIFrame(new RectTransform(Vector2.One, talentOptionLayoutGroup.RectTransform), style: null)
|
||||
{
|
||||
CanBeFocused = false,
|
||||
CanBeFocused = false
|
||||
};
|
||||
|
||||
GUIButton talentButton = new GUIButton(new RectTransform(Vector2.One, talentFrame.RectTransform, anchor: Anchor.Center), style: null)
|
||||
GUIFrame croppedTalentFrame = new GUIFrame(new RectTransform(Vector2.One, talentFrame.RectTransform, anchor: Anchor.Center, scaleBasis: ScaleBasis.BothHeight), style: null);
|
||||
|
||||
GUIButton talentButton = new GUIButton(new RectTransform(Vector2.One, croppedTalentFrame.RectTransform, anchor: Anchor.Center), style: null)
|
||||
{
|
||||
ToolTip = $"{talent.DisplayName}\n\n{talent.Description}",
|
||||
UserData = talent.Identifier,
|
||||
@@ -1361,7 +1436,7 @@ namespace Barotrauma
|
||||
GUIComponent iconImage;
|
||||
if (talent.Icon is null)
|
||||
{
|
||||
iconImage = new GUITextBlock(new RectTransform(Vector2.One, talentButton.RectTransform, anchor: Anchor.Center, scaleBasis: ScaleBasis.BothHeight), text: "???", font: GUI.LargeFont, textAlignment: Alignment.Center, style: null)
|
||||
iconImage = new GUITextBlock(new RectTransform(Vector2.One, talentButton.RectTransform, anchor: Anchor.Center), text: "???", font: GUI.LargeFont, textAlignment: Alignment.Center, style: null)
|
||||
{
|
||||
OutlineColor = GUI.Style.Red,
|
||||
TextColor = GUI.Style.Red,
|
||||
@@ -1387,10 +1462,11 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
}
|
||||
GUITextBlock.AutoScaleAndNormalize(subTreeNames);
|
||||
|
||||
GUILayoutGroup talentBottomFrame = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.07f), talentFrameLayoutGroup.RectTransform, Anchor.TopCenter), isHorizontal: true) { RelativeSpacing = 0.01f };
|
||||
|
||||
GUILayoutGroup experienceLayout = new GUILayoutGroup(new RectTransform(new Vector2(0.775f, 1f), talentBottomFrame.RectTransform));
|
||||
GUILayoutGroup experienceLayout = new GUILayoutGroup(new RectTransform(new Vector2(0.59f, 1f), talentBottomFrame.RectTransform));
|
||||
GUIFrame experienceBarFrame = new GUIFrame(new RectTransform(new Vector2(1f, 0.5f), experienceLayout.RectTransform), style: null);
|
||||
|
||||
experienceBar = new GUIProgressBar(new RectTransform(new Vector2(1f, 1f), experienceBarFrame.RectTransform, Anchor.CenterLeft),
|
||||
@@ -1399,19 +1475,22 @@ namespace Barotrauma
|
||||
IsHorizontal = true
|
||||
};
|
||||
|
||||
experienceText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 1.0f), experienceBarFrame.RectTransform, anchor: Anchor.Center), "", font: GUI.Font, textAlignment: Alignment.CenterRight);
|
||||
|
||||
talentPointText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), experienceLayout.RectTransform, anchor: Anchor.Center), "", font: GUI.SubHeadingFont, parseRichText: true, textAlignment: Alignment.CenterRight);
|
||||
|
||||
new GUIButton(new RectTransform(new Vector2(0.1f, 1f), talentBottomFrame.RectTransform), text: TextManager.Get("reset"), style: "GUICharacterInfoButton")
|
||||
experienceText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 1.0f), experienceBarFrame.RectTransform, anchor: Anchor.Center), "", font: GUI.Font, textAlignment: Alignment.CenterRight)
|
||||
{
|
||||
OnClicked = ResetTalentSelection,
|
||||
Shadow = true
|
||||
};
|
||||
|
||||
new GUIButton(new RectTransform(new Vector2(0.1f, 1f), talentBottomFrame.RectTransform), text: TextManager.Get("applysettingsbutton"), style: "GUICharacterInfoButton")
|
||||
talentPointText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), experienceLayout.RectTransform, anchor: Anchor.Center), "", font: GUI.SubHeadingFont, parseRichText: true, textAlignment: Alignment.CenterRight) { AutoScaleVertical = true };
|
||||
|
||||
talentResetButton = new GUIButton(new RectTransform(new Vector2(0.19f, 1f), talentBottomFrame.RectTransform), text: TextManager.Get("reset"), style: "GUIButtonFreeScale")
|
||||
{
|
||||
OnClicked = ResetTalentSelection
|
||||
};
|
||||
talentApplyButton = new GUIButton(new RectTransform(new Vector2(0.19f, 1f), talentBottomFrame.RectTransform), text: TextManager.Get("applysettingsbutton"), style: "GUIButtonFreeScale")
|
||||
{
|
||||
OnClicked = ApplyTalentSelection,
|
||||
};
|
||||
GUITextBlock.AutoScaleAndNormalize(talentResetButton.TextBlock, talentApplyButton.TextBlock);
|
||||
|
||||
UpdateTalentButtons();
|
||||
}
|
||||
@@ -1419,11 +1498,12 @@ namespace Barotrauma
|
||||
private void CreateTalentSkillList(Character character, GUIListBox parent)
|
||||
{
|
||||
parent.Content.ClearChildren();
|
||||
List<GUITextBlock> skillNames = new List<GUITextBlock>();
|
||||
foreach (Skill skill in character.Info.Job.Skills)
|
||||
{
|
||||
GUILayoutGroup skillContainer = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.2f), parent.Content.RectTransform), isHorizontal: true) { CanBeFocused = false };
|
||||
|
||||
new GUITextBlock(new RectTransform(new Vector2(0.7f, 1f), skillContainer.RectTransform), TextManager.Get($"skillname.{skill.Identifier}", returnNull: true) ?? skill.Identifier);
|
||||
skillNames.Add(new GUITextBlock(new RectTransform(new Vector2(0.7f, 1f), skillContainer.RectTransform), TextManager.Get($"skillname.{skill.Identifier}", returnNull: true) ?? skill.Identifier));
|
||||
new GUITextBlock(new RectTransform(new Vector2(0.15f, 1.0f), skillContainer.RectTransform), Math.Floor(skill.Level).ToString("F0"), textAlignment: Alignment.CenterRight) { Padding = new Vector4(0, 0, 4, 0) };
|
||||
|
||||
float modifiedSkillLevel = character.GetSkillLevel(skill.Identifier);
|
||||
@@ -1444,6 +1524,7 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
parent.RecalculateChildren();
|
||||
GUITextBlock.AutoScaleAndNormalize(skillNames);
|
||||
}
|
||||
|
||||
private void UpdateTalentButtons()
|
||||
|
||||
@@ -1068,7 +1068,6 @@ namespace Barotrauma
|
||||
spriteBatch.End();
|
||||
}
|
||||
|
||||
|
||||
sw.Stop();
|
||||
PerformanceCounter.AddElapsedTicks("Draw total", sw.ElapsedTicks);
|
||||
PerformanceCounter.DrawTimeGraph.Update(sw.ElapsedTicks * 1000.0f / (float)Stopwatch.Frequency);
|
||||
|
||||
+1
-1
@@ -60,7 +60,7 @@ namespace Barotrauma
|
||||
var newCampaignContainer = new GUIFrame(new RectTransform(new Vector2(0.95f, 0.95f), campaignContainer.RectTransform, Anchor.Center), style: null);
|
||||
var loadCampaignContainer = new GUIFrame(new RectTransform(new Vector2(0.95f, 0.95f), campaignContainer.RectTransform, Anchor.Center), style: null);
|
||||
|
||||
GameMain.NetLobbyScreen.CampaignSetupUI = new CampaignSetupUI(true, newCampaignContainer, loadCampaignContainer, null, saveFiles);
|
||||
GameMain.NetLobbyScreen.CampaignSetupUI = new MultiPlayerCampaignSetupUI(newCampaignContainer, loadCampaignContainer, null, saveFiles);
|
||||
|
||||
var newCampaignButton = new GUIButton(new RectTransform(new Vector2(0.5f, 1.0f), buttonContainer.RectTransform),
|
||||
TextManager.Get("NewCampaign"), style: "GUITabButton")
|
||||
|
||||
@@ -21,7 +21,8 @@ namespace Barotrauma
|
||||
{
|
||||
if (GameMain.NetworkMember != null && GameMain.NetLobbyScreen != null)
|
||||
{
|
||||
if (GameMain.NetLobbyScreen.HeadSelectionList != null) { GameMain.NetLobbyScreen.HeadSelectionList.Visible = false; }
|
||||
GameMain.NetLobbyScreen.CharacterAppearanceCustomizationMenu?.Dispose();
|
||||
GameMain.NetLobbyScreen.CharacterAppearanceCustomizationMenu = null;
|
||||
if (GameMain.NetLobbyScreen.JobSelectionFrame != null) { GameMain.NetLobbyScreen.JobSelectionFrame.Visible = false; }
|
||||
}
|
||||
if (tabMenu == null && !(GameMode is TutorialMode) && !ConversationAction.IsDialogOpen)
|
||||
@@ -39,6 +40,7 @@ namespace Barotrauma
|
||||
|
||||
private GUILayoutGroup topLeftButtonGroup;
|
||||
private GUIButton crewListButton, commandButton, tabMenuButton;
|
||||
private GUIImage talentPointNotification;
|
||||
|
||||
private GUIComponent respawnInfoFrame, respawnButtonContainer;
|
||||
private GUITextBlock respawnInfoText;
|
||||
@@ -88,11 +90,11 @@ namespace Barotrauma
|
||||
tabMenuButton = new GUIButton(new RectTransform(buttonSize, parent: topLeftButtonGroup.RectTransform), style: "TabMenuButton")
|
||||
{
|
||||
ToolTip = TextManager.GetWithVariable("hudbutton.tabmenu", "[key]", GameMain.Config.KeyBindText(InputType.InfoTab)),
|
||||
OnClicked = (button, userData) =>
|
||||
{
|
||||
return ToggleTabMenu();
|
||||
}
|
||||
OnClicked = (button, userData) => ToggleTabMenu()
|
||||
};
|
||||
|
||||
talentPointNotification = CreateTalentIconNotification(tabMenuButton);
|
||||
|
||||
GameMain.Instance.ResolutionChanged += CreateTopLeftButtons;
|
||||
|
||||
respawnInfoFrame = new GUIFrame(new RectTransform(new Vector2(0.5f, 1.0f), parent: topLeftButtonGroup.RectTransform)
|
||||
@@ -139,11 +141,41 @@ namespace Barotrauma
|
||||
|
||||
if (GameMain.NetworkMember != null)
|
||||
{
|
||||
GameMain.NetLobbyScreen?.HeadSelectionList?.AddToGUIUpdateList();
|
||||
GameMain.NetLobbyScreen.CharacterAppearanceCustomizationMenu?.AddToGUIUpdateList();
|
||||
GameMain.NetLobbyScreen?.JobSelectionFrame?.AddToGUIUpdateList();
|
||||
}
|
||||
}
|
||||
|
||||
public static GUIImage CreateTalentIconNotification(GUIComponent parent, bool offset = true)
|
||||
{
|
||||
GUIImage indicator = new GUIImage(new RectTransform(new Vector2(0.45f), parent.RectTransform, anchor: Anchor.TopRight, scaleBasis: ScaleBasis.BothWidth), style: "TalentPointNotification")
|
||||
{
|
||||
Visible = false,
|
||||
CanBeFocused = false
|
||||
};
|
||||
Point notificationSize = indicator.RectTransform.NonScaledSize;
|
||||
if (offset)
|
||||
{
|
||||
indicator.RectTransform.AbsoluteOffset = new Point(-(notificationSize.X / 2), -(notificationSize.Y / 2));
|
||||
}
|
||||
return indicator;
|
||||
}
|
||||
|
||||
public static void UpdateTalentNotificationIndicator(GUIImage indicator)
|
||||
{
|
||||
if (indicator != null)
|
||||
{
|
||||
if (Character.Controlled?.Info == null)
|
||||
{
|
||||
indicator.Visible = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
indicator.Visible = Character.Controlled.Info.GetAvailableTalentPoints() > 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
partial void UpdateProjSpecific(float deltaTime)
|
||||
{
|
||||
if (GUI.DisableHUD) { return; }
|
||||
@@ -158,28 +190,24 @@ namespace Barotrauma
|
||||
else
|
||||
{
|
||||
tabMenu.Update();
|
||||
if ((PlayerInput.KeyHit(InputType.InfoTab) || PlayerInput.KeyHit(Microsoft.Xna.Framework.Input.Keys.Escape)) &&
|
||||
if ((PlayerInput.KeyHit(InputType.InfoTab) || PlayerInput.KeyHit(Microsoft.Xna.Framework.Input.Keys.Escape)) &&
|
||||
!(GUI.KeyboardDispatcher.Subscriber is GUITextBox))
|
||||
{
|
||||
ToggleTabMenu();
|
||||
}
|
||||
}
|
||||
|
||||
UpdateTalentNotificationIndicator(talentPointNotification);
|
||||
|
||||
if (GameMain.NetworkMember != null)
|
||||
{
|
||||
if (GameMain.NetLobbyScreen?.HeadSelectionList != null)
|
||||
{
|
||||
if (PlayerInput.PrimaryMouseButtonDown() && !GUI.IsMouseOn(GameMain.NetLobbyScreen.HeadSelectionList))
|
||||
{
|
||||
if (GameMain.NetLobbyScreen.HeadSelectionList != null) { GameMain.NetLobbyScreen.HeadSelectionList.Visible = false; }
|
||||
}
|
||||
}
|
||||
GameMain.NetLobbyScreen?.CharacterAppearanceCustomizationMenu?.Update();
|
||||
if (GameMain.NetLobbyScreen?.JobSelectionFrame != null)
|
||||
{
|
||||
if (PlayerInput.PrimaryMouseButtonDown() && !GUI.IsMouseOn(GameMain.NetLobbyScreen.JobSelectionFrame))
|
||||
if (GameMain.NetLobbyScreen.JobSelectionFrame != null && PlayerInput.PrimaryMouseButtonDown() && !GUI.IsMouseOn(GameMain.NetLobbyScreen.JobSelectionFrame))
|
||||
{
|
||||
GameMain.NetLobbyScreen.JobList.Deselect();
|
||||
if (GameMain.NetLobbyScreen.JobSelectionFrame != null) { GameMain.NetLobbyScreen.JobSelectionFrame.Visible = false; }
|
||||
GameMain.NetLobbyScreen.JobSelectionFrame.Visible = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -323,7 +323,7 @@ namespace Barotrauma
|
||||
case Layout.Default:
|
||||
{
|
||||
int personalSlotCount = SlotTypes.Count(s => PersonalSlots.HasFlag(s));
|
||||
int normalSlotCount = SlotTypes.Count(s => !PersonalSlots.HasFlag(s));
|
||||
int normalSlotCount = SlotTypes.Count(s => !PersonalSlots.HasFlag(s) && s != InvSlotType.HealthInterface);
|
||||
|
||||
int x = GameMain.GraphicsWidth / 2 - normalSlotCount * (SlotSize.X + Spacing) / 2;
|
||||
int upperX = HUDLayoutSettings.BottomRightInfoArea.X - SlotSize.X - Spacing * 4 - HideButtonWidth;
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public override void AddTooltipInfo(ref string name, ref string description)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(materialName))
|
||||
if (!string.IsNullOrEmpty(materialName) && item.ContainedItems.Count() > 0)
|
||||
{
|
||||
string mergedMaterialName = materialName;
|
||||
foreach (Item containedItem in item.ContainedItems)
|
||||
@@ -23,7 +23,7 @@ namespace Barotrauma.Items.Components
|
||||
if (containedMaterial == null) { continue; }
|
||||
mergedMaterialName += ", " + containedMaterial.materialName;
|
||||
}
|
||||
name = TextManager.GetWithVariable("entityname.geneticmaterial", "[type]", mergedMaterialName);
|
||||
name = name.Replace(materialName, mergedMaterialName);
|
||||
}
|
||||
|
||||
if (Tainted)
|
||||
|
||||
@@ -164,7 +164,7 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
}
|
||||
activateButton.Enabled = inputContainer.Inventory.AllItems.Any();
|
||||
activateButton.Enabled = outputsFound;
|
||||
activateButton.Text = TextManager.Get(ActivateButtonText);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -516,11 +516,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
string name = GetRecipeNameAndAmount(selectedItem);
|
||||
|
||||
float quality = 0;
|
||||
foreach (string tag in selectedItem.TargetItem.Tags)
|
||||
{
|
||||
quality += user?.Info?.GetSavedStatValue(StatTypes.IncreaseFabricationQuality, tag) ?? 0;
|
||||
}
|
||||
float quality = GetFabricatedItemQuality(selectedItem, user);
|
||||
if (quality > 0)
|
||||
{
|
||||
name = TextManager.GetWithVariable("itemname.quality" + (int)quality, "[itemname]", name+'\n', fallBackTag: "itemname.quality3");
|
||||
|
||||
@@ -246,25 +246,26 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
protected override void CreateGUI()
|
||||
{
|
||||
GuiFrame.ClearChildren();
|
||||
|
||||
GuiFrame.RectTransform.RelativeOffset = new Vector2(0.05f, 0.0f);
|
||||
GuiFrame.CanBeFocused = true;
|
||||
new GUICustomComponent(new RectTransform(GuiFrame.Rect.Size - GUIStyle.ItemFrameMargin, GuiFrame.RectTransform, Anchor.Center) { AbsoluteOffset = GUIStyle.ItemFrameOffset }, DrawHUDBack, null);
|
||||
GUIFrame paddedContainer = new GUIFrame(new RectTransform(new Vector2(0.95f, 0.9f), GuiFrame.RectTransform, Anchor.Center), style: null);
|
||||
var submarineBack = new GUICustomComponent(new RectTransform(GuiFrame.Rect.Size - GUIStyle.ItemFrameMargin, GuiFrame.RectTransform, Anchor.Center) { AbsoluteOffset = GUIStyle.ItemFrameOffset }, DrawHUDBack, null);
|
||||
GUIFrame paddedContainer = new GUIFrame(new RectTransform(GuiFrame.Rect.Size - GUIStyle.ItemFrameMargin, GuiFrame.RectTransform, Anchor.Center), style: null);
|
||||
submarineContainer = new GUIFrame(new RectTransform(Vector2.One, paddedContainer.RectTransform, Anchor.Center), style: null);
|
||||
|
||||
new GUICustomComponent(new RectTransform(GuiFrame.Rect.Size - GUIStyle.ItemFrameMargin, GuiFrame.RectTransform, Anchor.Center) { AbsoluteOffset = GUIStyle.ItemFrameOffset }, DrawHUDFront, null)
|
||||
var submarineFront = new GUICustomComponent(new RectTransform(GuiFrame.Rect.Size - GUIStyle.ItemFrameMargin, GuiFrame.RectTransform, Anchor.Center) { AbsoluteOffset = GUIStyle.ItemFrameOffset }, DrawHUDFront, null)
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
|
||||
GUILayoutGroup buttonLayout = new GUILayoutGroup(new RectTransform(new Vector2(0.5f, 0.2f), paddedContainer.RectTransform), isHorizontal: true);
|
||||
GUILayoutGroup buttonLayout = new GUILayoutGroup(new RectTransform(new Vector2(0.5f, 0.15f), paddedContainer.RectTransform) { MaxSize = new Point(int.MaxValue, GUI.IntScale(40)) }, isHorizontal: true) { CanBeFocused = true };
|
||||
|
||||
modeSwitchButtons = ImmutableArray.Create
|
||||
(
|
||||
new GUIButton(new RectTransform(new Vector2(0.25f, 0.5f), buttonLayout.RectTransform), string.Empty, style: "StatusMonitorButton.HullStatus") { UserData = MiniMapMode.HullStatus, Enabled = EnableHullStatus, ToolTip = TextManager.Get("StatusMonitorButton.HullStatus.Tooltip") },
|
||||
new GUIButton(new RectTransform(new Vector2(0.25f, 0.5f), buttonLayout.RectTransform), string.Empty, style: "StatusMonitorButton.ElectricalView") { UserData = MiniMapMode.ElectricalView, Enabled = EnableHullCondition, ToolTip = TextManager.Get("StatusMonitorButton.ElectricalView.Tooltip") },
|
||||
new GUIButton(new RectTransform(new Vector2(0.25f, 0.5f), buttonLayout.RectTransform), string.Empty, style: "StatusMonitorButton.HullCondition") { UserData = MiniMapMode.HullCondition, Enabled = EnableHullCondition, ToolTip = TextManager.Get("StatusMonitorButton.HullCondition.Tooltip") },
|
||||
new GUIButton(new RectTransform(new Vector2(0.25f, 0.5f), buttonLayout.RectTransform), string.Empty, style: "StatusMonitorButton.ItemFinder") { UserData = MiniMapMode.ItemFinder, Enabled = EnableItemFinder, ToolTip = TextManager.Get("StatusMonitorButton.ItemFinder.Tooltip") }
|
||||
new GUIButton(new RectTransform(new Vector2(0.25f, 1.0f), buttonLayout.RectTransform), string.Empty, style: "StatusMonitorButton.HullStatus") { UserData = MiniMapMode.HullStatus, Enabled = EnableHullStatus, ToolTip = TextManager.Get("StatusMonitorButton.HullStatus.Tooltip") },
|
||||
new GUIButton(new RectTransform(new Vector2(0.25f, 1.0f), buttonLayout.RectTransform), string.Empty, style: "StatusMonitorButton.ElectricalView") { UserData = MiniMapMode.ElectricalView, Enabled = EnableHullCondition, ToolTip = TextManager.Get("StatusMonitorButton.ElectricalView.Tooltip") },
|
||||
new GUIButton(new RectTransform(new Vector2(0.25f, 1.0f), buttonLayout.RectTransform), string.Empty, style: "StatusMonitorButton.HullCondition") { UserData = MiniMapMode.HullCondition, Enabled = EnableHullCondition, ToolTip = TextManager.Get("StatusMonitorButton.HullCondition.Tooltip") },
|
||||
new GUIButton(new RectTransform(new Vector2(0.25f, 1.0f), buttonLayout.RectTransform), string.Empty, style: "StatusMonitorButton.ItemFinder") { UserData = MiniMapMode.ItemFinder, Enabled = EnableItemFinder, ToolTip = TextManager.Get("StatusMonitorButton.ItemFinder.Tooltip") }
|
||||
);
|
||||
|
||||
foreach (GUIButton button in modeSwitchButtons)
|
||||
@@ -295,14 +296,15 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
List<Order> reports = Order.PrefabList.FindAll(o => o.IsReport && o.SymbolSprite != null && !o.Hidden);
|
||||
|
||||
GUIFrame bottomFrame = new GUIFrame(new RectTransform(new Vector2(0.5f, 0.15f), paddedContainer.RectTransform, Anchor.BottomCenter), style: null)
|
||||
GUIFrame bottomFrame = new GUIFrame(new RectTransform(new Vector2(0.5f, 0.15f), paddedContainer.RectTransform, Anchor.BottomCenter) { MaxSize = new Point(int.MaxValue, GUI.IntScale(40)) }, style: null)
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
|
||||
reportFrame = new GUILayoutGroup(new RectTransform(new Vector2(1), bottomFrame.RectTransform), isHorizontal: true)
|
||||
{
|
||||
AbsoluteSpacing = (int)(5 * GUI.Scale)
|
||||
Stretch = true,
|
||||
AbsoluteSpacing = GUI.IntScale(5)
|
||||
};
|
||||
|
||||
if (reports.Any())
|
||||
@@ -359,10 +361,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
searchBar.OnSelected += (sender, key) =>
|
||||
{
|
||||
itemsFoundOnSub = Item.ItemList.Where(it =>
|
||||
it.Submarine == item.Submarine &&
|
||||
!it.NonInteractable && !it.HiddenInGame &&
|
||||
(it.GetComponent<Holdable>() != null || it.GetComponent<Wearable>() != null)).Select(it => it.Prefab).ToImmutableHashSet();
|
||||
itemsFoundOnSub = Item.ItemList.Where(it => VisibleOnItemFinder(it)).Select(it => it.Prefab).ToImmutableHashSet();
|
||||
};
|
||||
|
||||
searchBar.OnKeyHit += ControlSearchTooltip;
|
||||
@@ -390,6 +389,28 @@ namespace Barotrauma.Items.Components
|
||||
c.CanBeFocused = false;
|
||||
c.Children.ForEach(c2 => c2.CanBeFocused = false);
|
||||
});
|
||||
|
||||
submarineBack.RectTransform.MaxSize =
|
||||
submarineFront.RectTransform.MaxSize =
|
||||
submarineContainer.RectTransform.MaxSize =
|
||||
new Point(int.MaxValue, paddedContainer.Rect.Height - bottomFrame.Rect.Height - buttonLayout.Rect.Height);
|
||||
}
|
||||
|
||||
private bool VisibleOnItemFinder(Item it)
|
||||
{
|
||||
if (it.Submarine != item.Submarine) { return false; }
|
||||
if (it.NonInteractable || it.HiddenInGame) { return false; }
|
||||
if (it.GetComponent<Pickable>() == null) { return false; }
|
||||
|
||||
var holdable = it.GetComponent<Holdable>();
|
||||
if (holdable != null && holdable.Attached) { return false; }
|
||||
|
||||
var wire = it.GetComponent<Wire>();
|
||||
if (wire != null && wire.Connections.Any(c => c != null)) { return false; }
|
||||
|
||||
if (it.HasTag("traitormissionitem")) { return false; }
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override void AddToGUIUpdateList()
|
||||
@@ -546,10 +567,7 @@ namespace Barotrauma.Items.Components
|
||||
// is there a better way to do this?
|
||||
if (GuiFrame.Rect.Size != elementSize)
|
||||
{
|
||||
if (item.Submarine is { } sub)
|
||||
{
|
||||
BakeSubmarine(sub, miniMapFrame.Rect);
|
||||
}
|
||||
CreateGUI();
|
||||
elementSize = GuiFrame.Rect.Size;
|
||||
}
|
||||
|
||||
@@ -782,10 +800,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
foreach (Item it in Item.ItemList)
|
||||
{
|
||||
if (it.Submarine != item.Submarine) { continue; }
|
||||
if (it.HiddenInGame || it.NonInteractable) { continue; }
|
||||
if (it.GetComponent<Wire>() is { Connections: { } conn} && conn.Any()) { continue; }
|
||||
if (it.HasTag("traitormissionitem")) { continue; }
|
||||
if (!VisibleOnItemFinder(it)) { continue; }
|
||||
|
||||
if (it.Prefab == searchedPrefab)
|
||||
{
|
||||
@@ -794,7 +809,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
if (it.FindParentInventory(inventory => inventory is ItemInventory { Owner: Item { ParentInventory: null } }) is ItemInventory parent)
|
||||
{
|
||||
foundItems.Add((Item) parent.Owner);
|
||||
foundItems.Add((Item)parent.Owner);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1165,7 +1180,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
if (entity is Item it)
|
||||
{
|
||||
if (it.GetComponent<Holdable>() != null || it.ParentInventory != null) { continue; }
|
||||
if (it.GetComponent<Pickable>() != null || it.ParentInventory != null) { continue; }
|
||||
DrawItem(spriteBatch, it, parentRect, worldBorders, inflate);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
{
|
||||
partial class Quality : ItemComponent
|
||||
{
|
||||
public override void AddTooltipInfo(ref string name, ref string description)
|
||||
{
|
||||
foreach (var statValue in statValues)
|
||||
{
|
||||
int roundedValue = (int)Math.Round(statValue.Value * qualityLevel * 100);
|
||||
if (roundedValue == 0) { return; }
|
||||
string colorStr = XMLExtensions.ColorToString(GUI.Style.Green);
|
||||
description += $"\n ‖color:{colorStr}‖{roundedValue.ToString("+0;-#")}%‖color:end‖ {TextManager.Get("qualitystattypenames." + statValue.Key.ToString(), true) ?? statValue.Key.ToString()}";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -51,7 +51,7 @@ namespace Barotrauma.Items.Components
|
||||
public override bool ShouldDrawHUD(Character character)
|
||||
{
|
||||
if (!HasRequiredItems(character, false) || character.SelectedConstruction != item) return false;
|
||||
return item.ConditionPercentage < RepairThreshold || character.IsTraitor && item.ConditionPercentage > MinSabotageCondition || (CurrentFixer == character && (!item.IsFullCondition || (character.IsTraitor && item.ConditionPercentage > MinSabotageCondition))) || CanTinker(character);
|
||||
return item.ConditionPercentage < RepairThreshold || character.IsTraitor && item.ConditionPercentage > MinSabotageCondition || (CurrentFixer == character && (!item.IsFullCondition || (character.IsTraitor && item.ConditionPercentage > MinSabotageCondition))) || IsTinkerable(character);
|
||||
}
|
||||
|
||||
partial void InitProjSpecific(XElement element)
|
||||
@@ -162,7 +162,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
tinkerButtonText = "Tinker";
|
||||
tinkeringText = "Tinkering";
|
||||
TinkerButton = new GUIButton(new RectTransform(new Vector2(0.8f, 0.15f), paddedFrame.RectTransform, Anchor.BottomCenter), tinkerButtonText, style: "GUIButtonSmall")
|
||||
TinkerButton = new GUIButton(new RectTransform(new Vector2(0.8f, 0.15f), paddedFrame.RectTransform, Anchor.BottomCenter), tinkerButtonText)
|
||||
{
|
||||
IgnoreLayoutGroups = true,
|
||||
Visible = false,
|
||||
@@ -254,7 +254,7 @@ namespace Barotrauma.Items.Components
|
||||
progressBarOverlayText.Visible = false;
|
||||
}
|
||||
|
||||
RepairButton.Enabled = (currentFixerAction == FixActions.None || (CurrentFixer == character && currentFixerAction != FixActions.Repair)) && !item.IsFullCondition;
|
||||
RepairButton.Enabled = (currentFixerAction == FixActions.None || (CurrentFixer == character && currentFixerAction != FixActions.Repair)) && !item.IsFullCondition && item.ConditionPercentage < RepairThreshold;
|
||||
RepairButton.Text = (currentFixerAction == FixActions.None || CurrentFixer != character || currentFixerAction != FixActions.Repair) ?
|
||||
repairButtonText :
|
||||
repairingText + new string('.', ((int)(Timing.TotalTime * 2.0f) % 3) + 1);
|
||||
@@ -269,7 +269,7 @@ namespace Barotrauma.Items.Components
|
||||
TinkerButton.Visible = IsTinkerable(character);
|
||||
TinkerButton.IgnoreLayoutGroups = !TinkerButton.Visible;
|
||||
TinkerButton.Enabled = (currentFixerAction == FixActions.None || (CurrentFixer == character && currentFixerAction != FixActions.Tinker)) && CanTinker(character);
|
||||
TinkerButton.Text = (currentFixerAction == FixActions.None || CurrentFixer != character || currentFixerAction != FixActions.Tinker && CanTinker(character)) ?
|
||||
TinkerButton.Text = (currentFixerAction == FixActions.None || CurrentFixer != character || currentFixerAction != FixActions.Tinker) ?
|
||||
tinkerButtonText :
|
||||
tinkeringText + new string('.', ((int)(Timing.TotalTime * 2.0f) % 3) + 1);
|
||||
|
||||
@@ -326,6 +326,7 @@ namespace Barotrauma.Items.Components
|
||||
deteriorateAlwaysResetTimer = msg.ReadSingle();
|
||||
DeteriorateAlways = msg.ReadBoolean();
|
||||
tinkeringDuration = msg.ReadSingle();
|
||||
tinkeringStrength = msg.ReadSingle();
|
||||
ushort currentFixerID = msg.ReadUInt16();
|
||||
currentFixerAction = (FixActions)msg.ReadRangedInteger(0, 2);
|
||||
CurrentFixer = currentFixerID != 0 ? Entity.FindEntityByID(currentFixerID) as Character : null;
|
||||
|
||||
@@ -316,11 +316,12 @@ namespace Barotrauma
|
||||
|
||||
string colorStr = XMLExtensions.ColorToString(!item.AllowStealing ? GUI.Style.Red : Color.White);
|
||||
|
||||
toolTip = $"‖color:{colorStr}‖{name}‖color:end‖";
|
||||
if (item.Quality > 0)
|
||||
{
|
||||
name = TextManager.GetWithVariable("itemname.quality" + item.Quality, "[itemname]", name, fallBackTag: "itemname.quality3");
|
||||
// substring by to get rid of the empty space at start, text file should be adjusted
|
||||
toolTip += $"\n{TextManager.GetWithVariable("itemname.quality" + item.Quality, "[itemname]", "", fallBackTag: "itemname.quality3")?.Substring(1)}";
|
||||
}
|
||||
toolTip = $"‖color:{colorStr}‖{name}‖color:end‖";
|
||||
|
||||
if (itemsInSlot.All(it => it.NonInteractable || it.NonPlayerTeamInteractable))
|
||||
{
|
||||
@@ -1653,9 +1654,9 @@ namespace Barotrauma
|
||||
scale: iconSize.X / stealIcon.size.X);
|
||||
}
|
||||
int maxStackSize = item.Prefab.MaxStackSize;
|
||||
if (item.Container != null)
|
||||
if (inventory is ItemInventory itemInventory)
|
||||
{
|
||||
maxStackSize = Math.Min(maxStackSize, item.Container.GetComponent<ItemContainer>()?.GetMaxStackSize(slotIndex) ?? maxStackSize);
|
||||
maxStackSize = Math.Min(maxStackSize, itemInventory.Container.GetMaxStackSize(slotIndex));
|
||||
}
|
||||
if (maxStackSize > 1 && inventory != null)
|
||||
{
|
||||
|
||||
@@ -265,7 +265,7 @@ namespace Barotrauma
|
||||
if (!currentDisplayLocation.Discovered)
|
||||
{
|
||||
RemoveFogOfWar(currentDisplayLocation);
|
||||
currentDisplayLocation.Discovered = true;
|
||||
currentDisplayLocation.Discover();
|
||||
if (currentDisplayLocation.MapPosition.X > furthestDiscoveredLocation.MapPosition.X)
|
||||
{
|
||||
furthestDiscoveredLocation = currentDisplayLocation;
|
||||
@@ -426,7 +426,7 @@ namespace Barotrauma
|
||||
Level.Loaded.DebugSetStartLocation(CurrentLocation);
|
||||
Level.Loaded.DebugSetEndLocation(null);
|
||||
|
||||
CurrentLocation.Discovered = true;
|
||||
CurrentLocation.Discover();
|
||||
OnLocationChanged?.Invoke(prevLocation, CurrentLocation);
|
||||
SelectLocation(-1);
|
||||
if (GameMain.Client == null)
|
||||
|
||||
@@ -2755,6 +2755,9 @@ namespace Barotrauma.Networking
|
||||
msg.Write((byte)characterInfo.BeardIndex);
|
||||
msg.Write((byte)characterInfo.MoustacheIndex);
|
||||
msg.Write((byte)characterInfo.FaceAttachmentIndex);
|
||||
msg.WriteColorR8G8B8(characterInfo.SkinColor);
|
||||
msg.WriteColorR8G8B8(characterInfo.HairColor);
|
||||
msg.WriteColorR8G8B8(characterInfo.FacialHairColor);
|
||||
|
||||
var jobPreferences = GameMain.NetLobbyScreen.JobPreferences;
|
||||
int count = Math.Min(jobPreferences.Count, 3);
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
abstract class CampaignSetupUI
|
||||
{
|
||||
protected readonly GUIComponent newGameContainer, loadGameContainer;
|
||||
|
||||
protected GUIListBox subList;
|
||||
protected GUIListBox saveList;
|
||||
protected List<GUITickBox> subTickBoxes;
|
||||
|
||||
protected GUITextBox saveNameBox, seedBox;
|
||||
|
||||
protected GUILayoutGroup subPreviewContainer;
|
||||
|
||||
protected GUIButton loadGameButton;
|
||||
|
||||
public Action<SubmarineInfo, string, string, CampaignSettings> StartNewGame;
|
||||
public Action<string> LoadGame;
|
||||
|
||||
protected enum CategoryFilter { All = 0, Vanilla = 1, Custom = 2 };
|
||||
protected CategoryFilter subFilter = CategoryFilter.All;
|
||||
|
||||
public GUIButton StartButton
|
||||
{
|
||||
get;
|
||||
protected set;
|
||||
}
|
||||
|
||||
public GUITextBlock InitialMoneyText
|
||||
{
|
||||
get;
|
||||
protected set;
|
||||
}
|
||||
|
||||
public GUITickBox EnableRadiationToggle { get; set; }
|
||||
public GUILayoutGroup CampaignSettingsContent { get; set; }
|
||||
|
||||
public GUIButton CampaignCustomizeButton { get; set; }
|
||||
public GUIMessageBox CampaignCustomizeSettings { get; set; }
|
||||
|
||||
public GUITextBlock MaxMissionCountText;
|
||||
|
||||
public CampaignSetupUI(GUIComponent newGameContainer, GUIComponent loadGameContainer)
|
||||
{
|
||||
this.newGameContainer = newGameContainer;
|
||||
this.loadGameContainer = loadGameContainer;
|
||||
}
|
||||
}
|
||||
}
|
||||
+521
@@ -0,0 +1,521 @@
|
||||
using Barotrauma.Tutorials;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Barotrauma.IO;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
using System.Globalization;
|
||||
using Barotrauma.Extensions;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
class MultiPlayerCampaignSetupUI : CampaignSetupUI
|
||||
{
|
||||
private GUIButton deleteMpSaveButton;
|
||||
|
||||
public MultiPlayerCampaignSetupUI(GUIComponent newGameContainer, GUIComponent loadGameContainer, IEnumerable<SubmarineInfo> submarines, IEnumerable<string> saveFiles = null)
|
||||
: base(newGameContainer, loadGameContainer)
|
||||
{
|
||||
var columnContainer = new GUILayoutGroup(new RectTransform(Vector2.One, newGameContainer.RectTransform), isHorizontal: true)
|
||||
{
|
||||
Stretch = true,
|
||||
RelativeSpacing = 0.0f
|
||||
};
|
||||
|
||||
var leftColumn = new GUILayoutGroup(new RectTransform(Vector2.One, columnContainer.RectTransform))
|
||||
{
|
||||
Stretch = true,
|
||||
RelativeSpacing = 0.015f
|
||||
};
|
||||
|
||||
var rightColumn = new GUILayoutGroup(new RectTransform(Vector2.Zero, columnContainer.RectTransform))
|
||||
{
|
||||
Stretch = true,
|
||||
RelativeSpacing = 0.015f
|
||||
};
|
||||
|
||||
columnContainer.Recalculate();
|
||||
|
||||
// New game left side
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.02f), leftColumn.RectTransform) { MinSize = new Point(0, 20) }, TextManager.Get("SaveName"), font: GUI.SubHeadingFont);
|
||||
saveNameBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 0.05f), leftColumn.RectTransform) { MinSize = new Point(0, 20) }, string.Empty)
|
||||
{
|
||||
textFilterFunction = (string str) => { return ToolBox.RemoveInvalidFileNameChars(str); }
|
||||
};
|
||||
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.02f), leftColumn.RectTransform) { MinSize = new Point(0, 20) }, TextManager.Get("MapSeed"), font: GUI.SubHeadingFont);
|
||||
seedBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 0.05f), leftColumn.RectTransform) { MinSize = new Point(0, 20) }, ToolBox.RandomSeed(8));
|
||||
|
||||
// Spacing to fix the multiplayer campaign setup layout
|
||||
CreateMultiplayerCampaignSubList(leftColumn.RectTransform);
|
||||
|
||||
//spacing
|
||||
//new GUIFrame(new RectTransform(new Vector2(1.0f, 0.25f), leftColumn.RectTransform), style: null);
|
||||
|
||||
// New game right side
|
||||
subPreviewContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 1.0f), rightColumn.RectTransform))
|
||||
{
|
||||
Stretch = true
|
||||
};
|
||||
|
||||
var buttonContainer = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.12f),
|
||||
leftColumn.RectTransform) { MaxSize = new Point(int.MaxValue, 60) }, childAnchor: Anchor.BottomRight, isHorizontal: true);
|
||||
|
||||
StartButton = new GUIButton(new RectTransform(new Vector2(0.4f, 1f), buttonContainer.RectTransform, Anchor.BottomRight) { MaxSize = new Point(350, 60) }, TextManager.Get("StartCampaignButton"))
|
||||
{
|
||||
OnClicked = (GUIButton btn, object userData) =>
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(saveNameBox.Text))
|
||||
{
|
||||
saveNameBox.Flash(GUI.Style.Red);
|
||||
return false;
|
||||
}
|
||||
|
||||
SubmarineInfo selectedSub = null;
|
||||
|
||||
if (GameMain.NetLobbyScreen.SelectedSub == null) { return false; }
|
||||
selectedSub = GameMain.NetLobbyScreen.SelectedSub;
|
||||
|
||||
if (selectedSub.SubmarineClass == SubmarineClass.Undefined)
|
||||
{
|
||||
new GUIMessageBox(TextManager.Get("error"), TextManager.Get("undefinedsubmarineselected"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(selectedSub.MD5Hash.Hash))
|
||||
{
|
||||
((GUITextBlock)subList.SelectedComponent).TextColor = Color.DarkRed * 0.8f;
|
||||
subList.SelectedComponent.CanBeFocused = false;
|
||||
subList.Deselect();
|
||||
return false;
|
||||
}
|
||||
|
||||
string savePath = SaveUtil.CreateSavePath(SaveUtil.SaveType.Multiplayer, saveNameBox.Text);
|
||||
bool hasRequiredContentPackages = selectedSub.RequiredContentPackagesInstalled;
|
||||
|
||||
CampaignSettings settings = new CampaignSettings();
|
||||
|
||||
settings.RadiationEnabled = GameMain.NetLobbyScreen.IsRadiationEnabled();
|
||||
settings.MaxMissionCount = GameMain.NetLobbyScreen.GetMaxMissionCount();
|
||||
|
||||
if (selectedSub.HasTag(SubmarineTag.Shuttle) || !hasRequiredContentPackages)
|
||||
{
|
||||
if (!hasRequiredContentPackages)
|
||||
{
|
||||
var msgBox = new GUIMessageBox(TextManager.Get("ContentPackageMismatch"),
|
||||
TextManager.GetWithVariable("ContentPackageMismatchWarning", "[requiredcontentpackages]", string.Join(", ", selectedSub.RequiredContentPackages)),
|
||||
new string[] { TextManager.Get("Yes"), TextManager.Get("No") });
|
||||
|
||||
msgBox.Buttons[0].OnClicked = msgBox.Close;
|
||||
msgBox.Buttons[0].OnClicked += (button, obj) =>
|
||||
{
|
||||
if (GUIMessageBox.MessageBoxes.Count == 0)
|
||||
{
|
||||
StartNewGame?.Invoke(selectedSub, savePath, seedBox.Text, settings);
|
||||
CoroutineManager.StartCoroutine(WaitForCampaignSetup(), "WaitForCampaignSetup");
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
msgBox.Buttons[1].OnClicked = msgBox.Close;
|
||||
}
|
||||
|
||||
if (selectedSub.HasTag(SubmarineTag.Shuttle))
|
||||
{
|
||||
var msgBox = new GUIMessageBox(TextManager.Get("ShuttleSelected"),
|
||||
TextManager.Get("ShuttleWarning"),
|
||||
new string[] { TextManager.Get("Yes"), TextManager.Get("No") });
|
||||
|
||||
msgBox.Buttons[0].OnClicked = (button, obj) =>
|
||||
{
|
||||
StartNewGame?.Invoke(selectedSub, savePath, seedBox.Text, settings);
|
||||
CoroutineManager.StartCoroutine(WaitForCampaignSetup(), "WaitForCampaignSetup");
|
||||
return true;
|
||||
};
|
||||
msgBox.Buttons[0].OnClicked += msgBox.Close;
|
||||
|
||||
msgBox.Buttons[1].OnClicked = msgBox.Close;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
StartNewGame?.Invoke(selectedSub, savePath, seedBox.Text, settings);
|
||||
CoroutineManager.StartCoroutine(WaitForCampaignSetup(), "WaitForCampaignSetup");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
InitialMoneyText = new GUITextBlock(new RectTransform(new Vector2(0.6f, 1f), buttonContainer.RectTransform), "", font: GUI.Style.SmallFont, textColor: GUI.Style.Green)
|
||||
{
|
||||
TextGetter = () =>
|
||||
{
|
||||
int initialMoney = CampaignMode.InitialMoney;
|
||||
if (GameMain.NetLobbyScreen.SelectedSub != null)
|
||||
{
|
||||
initialMoney -= GameMain.NetLobbyScreen.SelectedSub.Price;
|
||||
}
|
||||
initialMoney = Math.Max(initialMoney, MultiPlayerCampaign.MinimumInitialMoney);
|
||||
return TextManager.GetWithVariable("campaignstartingmoney", "[money]", string.Format(CultureInfo.InvariantCulture, "{0:N0}", initialMoney));
|
||||
}
|
||||
};
|
||||
|
||||
columnContainer.Recalculate();
|
||||
leftColumn.Recalculate();
|
||||
rightColumn.Recalculate();
|
||||
|
||||
if (submarines != null) { UpdateSubList(submarines); }
|
||||
UpdateLoadMenu(saveFiles);
|
||||
}
|
||||
|
||||
private void CreateMultiplayerCampaignSubList(RectTransform parent)
|
||||
{
|
||||
GUILayoutGroup subHolder = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.725f), parent))
|
||||
{
|
||||
RelativeSpacing = 0.005f,
|
||||
Stretch = true
|
||||
};
|
||||
|
||||
var subLabel = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.055f), subHolder.RectTransform) { MinSize = new Point(0, 25) }, TextManager.Get("purchasablesubmarines", fallBackTag: "workshoplabelsubmarines"), font: GUI.SubHeadingFont);
|
||||
|
||||
var filterContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.05f), subHolder.RectTransform), isHorizontal: true)
|
||||
{
|
||||
Stretch = true
|
||||
};
|
||||
var searchTitle = new GUITextBlock(new RectTransform(new Vector2(0.001f, 1.0f), filterContainer.RectTransform), TextManager.Get("serverlog.filter"), textAlignment: Alignment.CenterLeft, font: GUI.Font);
|
||||
var searchBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 1.0f), filterContainer.RectTransform, Anchor.CenterRight), font: GUI.Font, createClearButton: true);
|
||||
filterContainer.RectTransform.MinSize = searchBox.RectTransform.MinSize;
|
||||
searchBox.OnSelected += (sender, userdata) => { searchTitle.Visible = false; };
|
||||
searchBox.OnDeselected += (sender, userdata) => { searchTitle.Visible = true; };
|
||||
searchBox.OnTextChanged += (textBox, text) =>
|
||||
{
|
||||
foreach (GUIComponent child in subList.Content.Children)
|
||||
{
|
||||
if (!(child.UserData is SubmarineInfo sub)) { continue; }
|
||||
child.Visible = string.IsNullOrEmpty(text) ? true : sub.DisplayName.ToLower().Contains(text.ToLower());
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
subList = new GUIListBox(new RectTransform(Vector2.One, subHolder.RectTransform));
|
||||
subTickBoxes = new List<GUITickBox>();
|
||||
|
||||
for (int i = 0; i < GameMain.Client.ServerSubmarines.Count; i++)
|
||||
{
|
||||
SubmarineInfo sub = GameMain.Client.ServerSubmarines[i];
|
||||
|
||||
if (!sub.IsCampaignCompatible) continue;
|
||||
|
||||
var frame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.2f), subList.Content.RectTransform) { MinSize = new Point(0, 20) },
|
||||
style: "ListBoxElement")
|
||||
{
|
||||
ToolTip = sub.Description,
|
||||
UserData = sub
|
||||
};
|
||||
|
||||
int buttonSize = (int)(frame.Rect.Height * 0.8f);
|
||||
|
||||
GUITickBox tickBox = new GUITickBox(new RectTransform(new Vector2(0.8f, 1.0f), frame.RectTransform, Anchor.CenterLeft), ToolBox.LimitString(sub.DisplayName, GUI.Font, subList.Content.Rect.Width - 65))
|
||||
{
|
||||
UserData = sub,
|
||||
OnSelected = (GUITickBox box) =>
|
||||
{
|
||||
GameMain.Client.RequestCampaignSub(box.UserData as SubmarineInfo, box.Selected);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
subTickBoxes.Add(tickBox);
|
||||
tickBox.Selected = GameMain.NetLobbyScreen.CampaignSubmarines.Contains(sub);
|
||||
|
||||
frame.RectTransform.MinSize = new Point(0, tickBox.RectTransform.MinSize.Y);
|
||||
|
||||
var subTextBlock = tickBox.TextBlock;
|
||||
|
||||
var matchingSub = SubmarineInfo.SavedSubmarines.FirstOrDefault(s => s.Name == sub.Name && s.MD5Hash?.Hash == sub.MD5Hash?.Hash);
|
||||
if (matchingSub == null) matchingSub = SubmarineInfo.SavedSubmarines.FirstOrDefault(s => s.Name == sub.Name);
|
||||
|
||||
if (matchingSub == null)
|
||||
{
|
||||
subTextBlock.TextColor = new Color(subTextBlock.TextColor, 0.5f);
|
||||
frame.ToolTip = TextManager.Get("SubNotFound");
|
||||
}
|
||||
else if (matchingSub?.MD5Hash == null || matchingSub.MD5Hash?.Hash != sub.MD5Hash?.Hash)
|
||||
{
|
||||
subTextBlock.TextColor = new Color(subTextBlock.TextColor, 0.5f);
|
||||
frame.ToolTip = TextManager.Get("SubDoesntMatch");
|
||||
}
|
||||
|
||||
if (!sub.RequiredContentPackagesInstalled)
|
||||
{
|
||||
subTextBlock.TextColor = Color.Lerp(subTextBlock.TextColor, Color.DarkRed, 0.5f);
|
||||
frame.ToolTip = TextManager.Get("ContentPackageMismatch") + "\n\n" + frame.RawToolTip;
|
||||
}
|
||||
|
||||
var classText = new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), frame.RectTransform, Anchor.CenterRight),
|
||||
TextManager.Get($"submarineclass.{sub.SubmarineClass}"), textAlignment: Alignment.CenterRight, font: GUI.SmallFont)
|
||||
{
|
||||
TextColor = subTextBlock.TextColor * 0.8f,
|
||||
ToolTip = subTextBlock.RawToolTip
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public void RefreshMultiplayerCampaignSubUI(List<SubmarineInfo> campaignSubs)
|
||||
{
|
||||
for (int i = 0; i < subTickBoxes.Count; i++)
|
||||
{
|
||||
subTickBoxes[i].Selected = campaignSubs.Contains(subTickBoxes[i].UserData as SubmarineInfo);
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerable<object> WaitForCampaignSetup()
|
||||
{
|
||||
GUI.SetCursorWaiting();
|
||||
string headerText = TextManager.Get("CampaignStartingPleaseWait");
|
||||
var msgBox = new GUIMessageBox(headerText, TextManager.Get("CampaignStarting"), new string[] { TextManager.Get("Cancel") });
|
||||
|
||||
msgBox.Buttons[0].OnClicked = (btn, userdata) =>
|
||||
{
|
||||
GameMain.NetLobbyScreen.HighlightMode(GameMain.NetLobbyScreen.SelectedModeIndex);
|
||||
GameMain.NetLobbyScreen.SelectMode(GameMain.NetLobbyScreen.SelectedModeIndex);
|
||||
GUI.ClearCursorWait();
|
||||
CoroutineManager.StopCoroutines("WaitForCampaignSetup");
|
||||
return true;
|
||||
};
|
||||
msgBox.Buttons[0].OnClicked += msgBox.Close;
|
||||
|
||||
DateTime timeOut = DateTime.Now + new TimeSpan(0, 0, 20);
|
||||
while (Screen.Selected != GameMain.GameScreen && DateTime.Now < timeOut)
|
||||
{
|
||||
msgBox.Header.Text = headerText + new string('.', (int)Timing.TotalTime % 3 + 1);
|
||||
yield return CoroutineStatus.Running;
|
||||
}
|
||||
msgBox.Close();
|
||||
GUI.ClearCursorWait();
|
||||
yield return CoroutineStatus.Success;
|
||||
}
|
||||
|
||||
public void UpdateSubList(IEnumerable<SubmarineInfo> submarines)
|
||||
{
|
||||
List<SubmarineInfo> subsToShow;
|
||||
string downloadFolder = Path.GetFullPath(SaveUtil.SubmarineDownloadFolder);
|
||||
subsToShow = submarines.Where(s => s.IsCampaignCompatibleIgnoreClass && Path.GetDirectoryName(Path.GetFullPath(s.FilePath)) != downloadFolder).ToList();
|
||||
|
||||
subsToShow.Sort((s1, s2) =>
|
||||
{
|
||||
int p1 = s1.Price > CampaignMode.InitialMoney ? 10 : 0;
|
||||
int p2 = s2.Price > CampaignMode.InitialMoney ? 10 : 0;
|
||||
return p1.CompareTo(p2) * 100 + s1.Name.CompareTo(s2.Name);
|
||||
});
|
||||
|
||||
subList.ClearChildren();
|
||||
|
||||
foreach (SubmarineInfo sub in subsToShow)
|
||||
{
|
||||
var textBlock = new GUITextBlock(
|
||||
new RectTransform(new Vector2(1, 0.1f), subList.Content.RectTransform) { MinSize = new Point(0, 30) },
|
||||
ToolBox.LimitString(sub.DisplayName, GUI.Font, subList.Rect.Width - 65), style: "ListBoxElement")
|
||||
{
|
||||
ToolTip = sub.Description,
|
||||
UserData = sub
|
||||
};
|
||||
|
||||
if (!sub.RequiredContentPackagesInstalled)
|
||||
{
|
||||
textBlock.TextColor = Color.Lerp(textBlock.TextColor, Color.DarkRed, .5f);
|
||||
textBlock.ToolTip = TextManager.Get("ContentPackageMismatch") + "\n\n" + textBlock.RawToolTip;
|
||||
}
|
||||
|
||||
var priceText = new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), textBlock.RectTransform, Anchor.CenterRight),
|
||||
TextManager.GetWithVariable("currencyformat", "[credits]", string.Format(CultureInfo.InvariantCulture, "{0:N0}", sub.Price)), textAlignment: Alignment.CenterRight, font: GUI.SmallFont)
|
||||
{
|
||||
TextColor = sub.Price > CampaignMode.InitialMoney ? GUI.Style.Red : textBlock.TextColor * 0.8f,
|
||||
ToolTip = textBlock.ToolTip
|
||||
};
|
||||
#if !DEBUG
|
||||
if (!GameMain.DebugDraw)
|
||||
{
|
||||
if (sub.Price > CampaignMode.InitialMoney || !sub.IsCampaignCompatible)
|
||||
{
|
||||
textBlock.CanBeFocused = false;
|
||||
textBlock.TextColor *= 0.5f;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if (SubmarineInfo.SavedSubmarines.Any())
|
||||
{
|
||||
var validSubs = subsToShow.Where(s => s.IsCampaignCompatible && s.Price <= CampaignMode.InitialMoney).ToList();
|
||||
if (validSubs.Count > 0)
|
||||
{
|
||||
subList.Select(validSubs[Rand.Int(validSubs.Count)]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private List<string> prevSaveFiles;
|
||||
public void UpdateLoadMenu(IEnumerable<string> saveFiles = null)
|
||||
{
|
||||
prevSaveFiles?.Clear();
|
||||
prevSaveFiles = null;
|
||||
loadGameContainer.ClearChildren();
|
||||
|
||||
if (saveFiles == null)
|
||||
{
|
||||
saveFiles = SaveUtil.GetSaveFiles(SaveUtil.SaveType.Multiplayer);
|
||||
}
|
||||
|
||||
var leftColumn = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.85f), loadGameContainer.RectTransform), childAnchor: Anchor.TopCenter)
|
||||
{
|
||||
Stretch = true,
|
||||
RelativeSpacing = 0.03f
|
||||
};
|
||||
|
||||
saveList = new GUIListBox(new RectTransform(Vector2.One, leftColumn.RectTransform))
|
||||
{
|
||||
OnSelected = SelectSaveFile
|
||||
};
|
||||
|
||||
foreach (string saveFile in saveFiles)
|
||||
{
|
||||
string fileName = saveFile;
|
||||
string subName = "";
|
||||
string saveTime = "";
|
||||
string contentPackageStr = "";
|
||||
var saveFrame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.1f), saveList.Content.RectTransform) { MinSize = new Point(0, 45) }, style: "ListBoxElement")
|
||||
{
|
||||
UserData = saveFile
|
||||
};
|
||||
|
||||
var nameText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), saveFrame.RectTransform), "")
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
|
||||
bool isCompatible = true;
|
||||
prevSaveFiles ??= new List<string>();
|
||||
|
||||
prevSaveFiles?.Add(saveFile);
|
||||
string[] splitSaveFile = saveFile.Split(';');
|
||||
saveFrame.UserData = splitSaveFile[0];
|
||||
fileName = nameText.Text = Path.GetFileNameWithoutExtension(splitSaveFile[0]);
|
||||
if (splitSaveFile.Length > 1) { subName = splitSaveFile[1]; }
|
||||
if (splitSaveFile.Length > 2) { saveTime = splitSaveFile[2]; }
|
||||
if (splitSaveFile.Length > 3) { contentPackageStr = splitSaveFile[3]; }
|
||||
|
||||
if (!string.IsNullOrEmpty(saveTime) && long.TryParse(saveTime, out long unixTime))
|
||||
{
|
||||
DateTime time = ToolBox.Epoch.ToDateTime(unixTime);
|
||||
saveTime = time.ToString();
|
||||
}
|
||||
if (!string.IsNullOrEmpty(contentPackageStr))
|
||||
{
|
||||
List<string> contentPackagePaths = contentPackageStr.Split('|').ToList();
|
||||
if (!GameSession.IsCompatibleWithEnabledContentPackages(contentPackagePaths, out string errorMsg))
|
||||
{
|
||||
nameText.TextColor = GUI.Style.Red;
|
||||
saveFrame.ToolTip = string.Join("\n", errorMsg, TextManager.Get("campaignmode.contentpackagemismatchwarning"));
|
||||
}
|
||||
}
|
||||
if (!isCompatible)
|
||||
{
|
||||
nameText.TextColor = GUI.Style.Red;
|
||||
saveFrame.ToolTip = TextManager.Get("campaignmode.incompatiblesave");
|
||||
}
|
||||
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), saveFrame.RectTransform, Anchor.BottomLeft),
|
||||
text: subName, font: GUI.SmallFont)
|
||||
{
|
||||
CanBeFocused = false,
|
||||
UserData = fileName
|
||||
};
|
||||
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 1.0f), saveFrame.RectTransform),
|
||||
text: saveTime, textAlignment: Alignment.Right, font: GUI.SmallFont)
|
||||
{
|
||||
CanBeFocused = false,
|
||||
UserData = fileName
|
||||
};
|
||||
}
|
||||
|
||||
saveList.Content.RectTransform.SortChildren((c1, c2) =>
|
||||
{
|
||||
string file1 = c1.GUIComponent.UserData as string;
|
||||
string file2 = c2.GUIComponent.UserData as string;
|
||||
DateTime file1WriteTime = DateTime.MinValue;
|
||||
DateTime file2WriteTime = DateTime.MinValue;
|
||||
try
|
||||
{
|
||||
file1WriteTime = File.GetLastWriteTime(file1);
|
||||
}
|
||||
catch
|
||||
{
|
||||
//do nothing - DateTime.MinValue will be used and the element will get sorted at the bottom of the list
|
||||
};
|
||||
try
|
||||
{
|
||||
file2WriteTime = File.GetLastWriteTime(file2);
|
||||
}
|
||||
catch
|
||||
{
|
||||
//do nothing - DateTime.MinValue will be used and the element will get sorted at the bottom of the list
|
||||
};
|
||||
return file2WriteTime.CompareTo(file1WriteTime);
|
||||
});
|
||||
|
||||
loadGameButton = new GUIButton(new RectTransform(new Vector2(0.45f, 0.12f), loadGameContainer.RectTransform, Anchor.BottomRight), TextManager.Get("LoadButton"))
|
||||
{
|
||||
OnClicked = (btn, obj) =>
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(saveList.SelectedData as string)) { return false; }
|
||||
LoadGame?.Invoke(saveList.SelectedData as string);
|
||||
CoroutineManager.StartCoroutine(WaitForCampaignSetup(), "WaitForCampaignSetup");
|
||||
return true;
|
||||
},
|
||||
Enabled = false
|
||||
};
|
||||
deleteMpSaveButton = new GUIButton(new RectTransform(new Vector2(0.45f, 0.12f), loadGameContainer.RectTransform, Anchor.BottomLeft),
|
||||
TextManager.Get("Delete"), style: "GUIButtonSmall")
|
||||
{
|
||||
OnClicked = DeleteSave,
|
||||
Visible = false
|
||||
};
|
||||
}
|
||||
|
||||
private bool SelectSaveFile(GUIComponent component, object obj)
|
||||
{
|
||||
string fileName = (string)obj;
|
||||
|
||||
loadGameButton.Enabled = true;
|
||||
deleteMpSaveButton.Visible = deleteMpSaveButton.Enabled = GameMain.Client.IsServerOwner;
|
||||
deleteMpSaveButton.Enabled = GameMain.GameSession?.SavePath != fileName;
|
||||
if (deleteMpSaveButton.Visible)
|
||||
{
|
||||
deleteMpSaveButton.UserData = obj as string;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool DeleteSave(GUIButton button, object obj)
|
||||
{
|
||||
string saveFile = obj as string;
|
||||
if (obj == null) { return false; }
|
||||
|
||||
string header = TextManager.Get("deletedialoglabel");
|
||||
string body = TextManager.GetWithVariable("deletedialogquestion", "[file]", Path.GetFileNameWithoutExtension(saveFile));
|
||||
|
||||
EventEditorScreen.AskForConfirmation(header, body, () =>
|
||||
{
|
||||
SaveUtil.DeleteSave(saveFile);
|
||||
prevSaveFiles?.RemoveAll(s => s.StartsWith(saveFile));
|
||||
UpdateLoadMenu(prevSaveFiles.ToList());
|
||||
return true;
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
+353
-404
@@ -10,58 +10,108 @@ using Barotrauma.Extensions;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
class CampaignSetupUI
|
||||
class SinglePlayerCampaignSetupUI : CampaignSetupUI
|
||||
{
|
||||
private readonly GUIComponent newGameContainer, loadGameContainer;
|
||||
public CharacterInfo.AppearanceCustomizationMenu[] CharacterMenus { get; private set; }
|
||||
|
||||
private GUIListBox subList;
|
||||
private GUIListBox saveList;
|
||||
private List<GUITickBox> subTickBoxes;
|
||||
|
||||
private readonly GUITextBox saveNameBox, seedBox;
|
||||
|
||||
private readonly GUILayoutGroup subPreviewContainer;
|
||||
|
||||
private GUIButton loadGameButton, deleteMpSaveButton;
|
||||
|
||||
public Action<SubmarineInfo, string, string, CampaignSettings> StartNewGame;
|
||||
public Action<string> LoadGame;
|
||||
|
||||
private enum CategoryFilter { All = 0, Vanilla = 1, Custom = 2 };
|
||||
private CategoryFilter subFilter = CategoryFilter.All;
|
||||
|
||||
public GUIButton StartButton
|
||||
private GUIButton nextButton;
|
||||
private GUILayoutGroup characterInfoColumns;
|
||||
|
||||
public SinglePlayerCampaignSetupUI(GUIComponent newGameContainer, GUIComponent loadGameContainer, IEnumerable<SubmarineInfo> submarines, IEnumerable<string> saveFiles = null)
|
||||
: base(newGameContainer, loadGameContainer)
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
UpdateNewGameMenu(submarines);
|
||||
UpdateLoadMenu(saveFiles);
|
||||
}
|
||||
|
||||
public GUITextBlock InitialMoneyText
|
||||
private int currentPage = 0;
|
||||
private GUIListBox pageContainer;
|
||||
|
||||
public void Update()
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
float targetScroll =
|
||||
(float)currentPage / ((float)pageContainer.Content.CountChildren - 1);
|
||||
|
||||
pageContainer.BarScroll = MathHelper.Lerp(pageContainer.BarScroll, targetScroll, 0.2f);
|
||||
if (MathUtils.NearlyEqual(pageContainer.BarScroll, targetScroll, 0.001f))
|
||||
{
|
||||
pageContainer.BarScroll = targetScroll;
|
||||
}
|
||||
|
||||
for (int i=0; i<CharacterMenus.Length; i++)
|
||||
{
|
||||
CharacterMenus[i]?.Update();
|
||||
}
|
||||
|
||||
pageContainer.HoverCursor = CursorState.Default;
|
||||
pageContainer.Content.HoverCursor = CursorState.Default;
|
||||
}
|
||||
|
||||
public void SetPage(int pageIndex)
|
||||
{
|
||||
currentPage = pageIndex;
|
||||
for (int i = 0; i < pageContainer.Content.CountChildren; i++)
|
||||
{
|
||||
var child = pageContainer.Content.GetChild(i);
|
||||
child.CanBeFocused = (i == currentPage);
|
||||
child.GetAllChildren().ForEach(c =>
|
||||
{
|
||||
if (c is GUIDropDown dd)
|
||||
{
|
||||
dd.Dropped = false;
|
||||
}
|
||||
c.CanBeFocused = (i == currentPage);
|
||||
});
|
||||
}
|
||||
var previewListBox = subPreviewContainer.GetAllChildren<GUIListBox>().FirstOrDefault();
|
||||
previewListBox?.GetAllChildren()?.ForEach(c =>
|
||||
{
|
||||
c.CanBeFocused = false;
|
||||
});
|
||||
}
|
||||
|
||||
public GUITickBox EnableRadiationToggle { get; set; }
|
||||
public GUILayoutGroup CampaignSettingsContent { get; set; }
|
||||
|
||||
public GUIButton CampaignCustomizeButton { get; set; }
|
||||
public GUIMessageBox CampaignCustomizeSettings { get; set; }
|
||||
|
||||
public GUITextBlock MaxMissionCountText;
|
||||
|
||||
private readonly bool isMultiplayer;
|
||||
|
||||
public CampaignSetupUI(bool isMultiplayer, GUIComponent newGameContainer, GUIComponent loadGameContainer, IEnumerable<SubmarineInfo> submarines, IEnumerable<string> saveFiles = null)
|
||||
private void UpdateNewGameMenu(IEnumerable<SubmarineInfo> submarines)
|
||||
{
|
||||
this.isMultiplayer = isMultiplayer;
|
||||
this.newGameContainer = newGameContainer;
|
||||
this.loadGameContainer = loadGameContainer;
|
||||
pageContainer =
|
||||
new GUIListBox(new RectTransform(Vector2.One, newGameContainer.RectTransform), style: null, isHorizontal: true)
|
||||
{
|
||||
ScrollBarEnabled = false,
|
||||
ScrollBarVisible = false,
|
||||
HoverCursor = CursorState.Default
|
||||
};
|
||||
|
||||
var columnContainer = new GUILayoutGroup(new RectTransform(Vector2.One, newGameContainer.RectTransform), isHorizontal: true)
|
||||
GUILayoutGroup createPageLayout()
|
||||
{
|
||||
var containerItem =
|
||||
new GUIFrame(new RectTransform(Vector2.One, pageContainer.Content.RectTransform), style: null);
|
||||
return new GUILayoutGroup(new RectTransform(Vector2.One * 0.95f, containerItem.RectTransform,
|
||||
Anchor.Center));
|
||||
}
|
||||
|
||||
CreateFirstPage(createPageLayout(), submarines);
|
||||
CreateSecondPage(createPageLayout());
|
||||
|
||||
pageContainer.RecalculateChildren();
|
||||
pageContainer.GetAllChildren().ForEach(c =>
|
||||
{
|
||||
c.ClampMouseRectToParent = true;
|
||||
});
|
||||
pageContainer.GetAllChildren<GUIDropDown>().ForEach(dd =>
|
||||
{
|
||||
dd.ListBox.ClampMouseRectToParent = false;
|
||||
dd.ListBox.Content.ClampMouseRectToParent = false;
|
||||
});
|
||||
SetPage(0);
|
||||
}
|
||||
|
||||
private void CreateFirstPage(GUILayoutGroup firstPageLayout, IEnumerable<SubmarineInfo> submarines)
|
||||
{
|
||||
firstPageLayout.RelativeSpacing = 0.02f;
|
||||
|
||||
var columnContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.9f), firstPageLayout.RectTransform), isHorizontal: true)
|
||||
{
|
||||
Stretch = true,
|
||||
RelativeSpacing = isMultiplayer ? 0.0f : 0.02f
|
||||
RelativeSpacing = 0.02f
|
||||
};
|
||||
|
||||
var leftColumn = new GUILayoutGroup(new RectTransform(Vector2.One, columnContainer.RectTransform))
|
||||
@@ -70,7 +120,7 @@ namespace Barotrauma
|
||||
RelativeSpacing = 0.015f
|
||||
};
|
||||
|
||||
var rightColumn = new GUILayoutGroup(new RectTransform(isMultiplayer ? Vector2.Zero : new Vector2(1.5f, 1.0f), columnContainer.RectTransform))
|
||||
var rightColumn = new GUILayoutGroup(new RectTransform(new Vector2(1.5f, 1.0f), columnContainer.RectTransform))
|
||||
{
|
||||
Stretch = true,
|
||||
RelativeSpacing = 0.015f
|
||||
@@ -88,47 +138,37 @@ namespace Barotrauma
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.02f), leftColumn.RectTransform) { MinSize = new Point(0, 20) }, TextManager.Get("MapSeed"), font: GUI.SubHeadingFont);
|
||||
seedBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 0.05f), leftColumn.RectTransform) { MinSize = new Point(0, 20) }, ToolBox.RandomSeed(8));
|
||||
|
||||
if (!isMultiplayer)
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.02f), leftColumn.RectTransform) { MinSize = new Point(0, 20) }, TextManager.Get("SelectedSub"), font: GUI.SubHeadingFont);
|
||||
|
||||
var moddedDropdown = new GUIDropDown(new RectTransform(new Vector2(1f, 0.02f), leftColumn.RectTransform), "", 3);
|
||||
moddedDropdown.AddItem(TextManager.Get("clientpermission.all"), CategoryFilter.All);
|
||||
moddedDropdown.AddItem(TextManager.Get("servertag.modded.false"), CategoryFilter.Vanilla);
|
||||
moddedDropdown.AddItem(TextManager.Get("customrank"), CategoryFilter.Custom);
|
||||
moddedDropdown.Select(0);
|
||||
|
||||
var filterContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.05f), leftColumn.RectTransform), isHorizontal: true)
|
||||
{
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.02f), leftColumn.RectTransform) { MinSize = new Point(0, 20) }, TextManager.Get("SelectedSub"), font: GUI.SubHeadingFont);
|
||||
Stretch = true
|
||||
};
|
||||
|
||||
var moddedDropdown = new GUIDropDown(new RectTransform(new Vector2(1f, 0.02f), leftColumn.RectTransform), "", 3);
|
||||
moddedDropdown.AddItem(TextManager.Get("clientpermission.all"), CategoryFilter.All);
|
||||
moddedDropdown.AddItem(TextManager.Get("servertag.modded.false"), CategoryFilter.Vanilla);
|
||||
moddedDropdown.AddItem(TextManager.Get("customrank"), CategoryFilter.Custom);
|
||||
moddedDropdown.Select(0);
|
||||
subList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.65f), leftColumn.RectTransform)) { ScrollBarVisible = true };
|
||||
|
||||
var filterContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.05f), leftColumn.RectTransform), isHorizontal: true)
|
||||
{
|
||||
Stretch = true
|
||||
};
|
||||
var searchTitle = new GUITextBlock(new RectTransform(new Vector2(0.001f, 1.0f), filterContainer.RectTransform), TextManager.Get("serverlog.filter"), textAlignment: Alignment.CenterLeft, font: GUI.Font);
|
||||
var searchBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 1.0f), filterContainer.RectTransform, Anchor.CenterRight), font: GUI.Font, createClearButton: true);
|
||||
filterContainer.RectTransform.MinSize = searchBox.RectTransform.MinSize;
|
||||
searchBox.OnSelected += (sender, userdata) => { searchTitle.Visible = false; };
|
||||
searchBox.OnDeselected += (sender, userdata) => { searchTitle.Visible = true; };
|
||||
searchBox.OnTextChanged += (textBox, text) => { FilterSubs(subList, text); return true; };
|
||||
|
||||
subList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.65f), leftColumn.RectTransform)) { ScrollBarVisible = true };
|
||||
|
||||
var searchTitle = new GUITextBlock(new RectTransform(new Vector2(0.001f, 1.0f), filterContainer.RectTransform), TextManager.Get("serverlog.filter"), textAlignment: Alignment.CenterLeft, font: GUI.Font);
|
||||
var searchBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 1.0f), filterContainer.RectTransform, Anchor.CenterRight), font: GUI.Font, createClearButton: true);
|
||||
filterContainer.RectTransform.MinSize = searchBox.RectTransform.MinSize;
|
||||
searchBox.OnSelected += (sender, userdata) => { searchTitle.Visible = false; };
|
||||
searchBox.OnDeselected += (sender, userdata) => { searchTitle.Visible = true; };
|
||||
searchBox.OnTextChanged += (textBox, text) => { FilterSubs(subList, text); return true; };
|
||||
|
||||
moddedDropdown.OnSelected = (component, data) =>
|
||||
{
|
||||
searchBox.Text = string.Empty;
|
||||
subFilter = (CategoryFilter)data;
|
||||
UpdateSubList(SubmarineInfo.SavedSubmarines);
|
||||
return true;
|
||||
};
|
||||
|
||||
subList.OnSelected = OnSubSelected;
|
||||
}
|
||||
else // Spacing to fix the multiplayer campaign setup layout
|
||||
moddedDropdown.OnSelected = (component, data) =>
|
||||
{
|
||||
CreateMultiplayerCampaignSubList(leftColumn.RectTransform);
|
||||
searchBox.Text = string.Empty;
|
||||
subFilter = (CategoryFilter)data;
|
||||
UpdateSubList(SubmarineInfo.SavedSubmarines);
|
||||
return true;
|
||||
};
|
||||
|
||||
//spacing
|
||||
//new GUIFrame(new RectTransform(new Vector2(1.0f, 0.25f), leftColumn.RectTransform), style: null);
|
||||
}
|
||||
subList.OnSelected = OnSubSelected;
|
||||
|
||||
// New game right side
|
||||
subPreviewContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 1.0f), rightColumn.RectTransform))
|
||||
@@ -136,176 +176,162 @@ namespace Barotrauma
|
||||
Stretch = true
|
||||
};
|
||||
|
||||
var buttonContainer = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.12f),
|
||||
(isMultiplayer ? leftColumn : rightColumn).RectTransform) { MaxSize = new Point(int.MaxValue, 60) }, childAnchor: Anchor.BottomRight, isHorizontal: true);
|
||||
if (!isMultiplayer) { buttonContainer.IgnoreLayoutGroups = true; }
|
||||
|
||||
StartButton = new GUIButton(new RectTransform(new Vector2(0.4f, 1f), buttonContainer.RectTransform, Anchor.BottomRight) { MaxSize = new Point(350, 60) }, TextManager.Get("StartCampaignButton"))
|
||||
var firstPageButtonContainer = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.08f),
|
||||
firstPageLayout.RectTransform), childAnchor: Anchor.BottomLeft, isHorizontal: true)
|
||||
{
|
||||
OnClicked = (GUIButton btn, object userData) =>
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(saveNameBox.Text))
|
||||
{
|
||||
saveNameBox.Flash(GUI.Style.Red);
|
||||
return false;
|
||||
}
|
||||
|
||||
SubmarineInfo selectedSub = null;
|
||||
|
||||
if (!isMultiplayer)
|
||||
{
|
||||
if (!(subList.SelectedData is SubmarineInfo)) { return false; }
|
||||
selectedSub = subList.SelectedData as SubmarineInfo;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (GameMain.NetLobbyScreen.SelectedSub == null) { return false; }
|
||||
selectedSub = GameMain.NetLobbyScreen.SelectedSub;
|
||||
}
|
||||
|
||||
if (selectedSub.SubmarineClass == SubmarineClass.Undefined)
|
||||
{
|
||||
new GUIMessageBox(TextManager.Get("error"), TextManager.Get("undefinedsubmarineselected"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(selectedSub.MD5Hash.Hash))
|
||||
{
|
||||
((GUITextBlock)subList.SelectedComponent).TextColor = Color.DarkRed * 0.8f;
|
||||
subList.SelectedComponent.CanBeFocused = false;
|
||||
subList.Deselect();
|
||||
return false;
|
||||
}
|
||||
|
||||
string savePath = SaveUtil.CreateSavePath(isMultiplayer ? SaveUtil.SaveType.Multiplayer : SaveUtil.SaveType.Singleplayer, saveNameBox.Text);
|
||||
bool hasRequiredContentPackages = selectedSub.RequiredContentPackagesInstalled;
|
||||
|
||||
CampaignSettings settings = new CampaignSettings();
|
||||
if (isMultiplayer)
|
||||
{
|
||||
settings.RadiationEnabled = GameMain.NetLobbyScreen.IsRadiationEnabled();
|
||||
settings.MaxMissionCount = GameMain.NetLobbyScreen.GetMaxMissionCount();
|
||||
}
|
||||
else
|
||||
{
|
||||
settings.RadiationEnabled = EnableRadiationToggle?.Selected ?? false;
|
||||
if (MaxMissionCountText != null && Int32.TryParse(MaxMissionCountText.Text, out int missionCount))
|
||||
{
|
||||
settings.MaxMissionCount = missionCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
settings.MaxMissionCount = CampaignSettings.DefaultMaxMissionCount;
|
||||
}
|
||||
}
|
||||
|
||||
if (selectedSub.HasTag(SubmarineTag.Shuttle) || !hasRequiredContentPackages)
|
||||
{
|
||||
if (!hasRequiredContentPackages)
|
||||
{
|
||||
var msgBox = new GUIMessageBox(TextManager.Get("ContentPackageMismatch"),
|
||||
TextManager.GetWithVariable("ContentPackageMismatchWarning", "[requiredcontentpackages]", string.Join(", ", selectedSub.RequiredContentPackages)),
|
||||
new string[] { TextManager.Get("Yes"), TextManager.Get("No") });
|
||||
|
||||
msgBox.Buttons[0].OnClicked = msgBox.Close;
|
||||
msgBox.Buttons[0].OnClicked += (button, obj) =>
|
||||
{
|
||||
if (GUIMessageBox.MessageBoxes.Count == 0)
|
||||
{
|
||||
StartNewGame?.Invoke(selectedSub, savePath, seedBox.Text, settings);
|
||||
if (isMultiplayer)
|
||||
{
|
||||
CoroutineManager.StartCoroutine(WaitForCampaignSetup(), "WaitForCampaignSetup");
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
msgBox.Buttons[1].OnClicked = msgBox.Close;
|
||||
}
|
||||
|
||||
if (selectedSub.HasTag(SubmarineTag.Shuttle))
|
||||
{
|
||||
var msgBox = new GUIMessageBox(TextManager.Get("ShuttleSelected"),
|
||||
TextManager.Get("ShuttleWarning"),
|
||||
new string[] { TextManager.Get("Yes"), TextManager.Get("No") });
|
||||
|
||||
msgBox.Buttons[0].OnClicked = (button, obj) =>
|
||||
{
|
||||
StartNewGame?.Invoke(selectedSub, savePath, seedBox.Text, settings);
|
||||
if (isMultiplayer)
|
||||
{
|
||||
CoroutineManager.StartCoroutine(WaitForCampaignSetup(), "WaitForCampaignSetup");
|
||||
}
|
||||
return true;
|
||||
};
|
||||
msgBox.Buttons[0].OnClicked += msgBox.Close;
|
||||
|
||||
msgBox.Buttons[1].OnClicked = msgBox.Close;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
StartNewGame?.Invoke(selectedSub, savePath, seedBox.Text, settings);
|
||||
if (isMultiplayer)
|
||||
{
|
||||
CoroutineManager.StartCoroutine(WaitForCampaignSetup(), "WaitForCampaignSetup");
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
RelativeSpacing = 0.025f
|
||||
};
|
||||
|
||||
InitialMoneyText = new GUITextBlock(new RectTransform(new Vector2(isMultiplayer ? 0.6f : 0.3f, 1f), buttonContainer.RectTransform), "", font: isMultiplayer ? GUI.Style.SmallFont : GUI.Style.Font, textColor: GUI.Style.Green)
|
||||
InitialMoneyText = new GUITextBlock(new RectTransform(new Vector2(0.3f, 1f), firstPageButtonContainer.RectTransform), "", font: GUI.Style.Font, textColor: GUI.Style.Green, textAlignment: Alignment.CenterLeft)
|
||||
{
|
||||
TextGetter = () =>
|
||||
{
|
||||
int initialMoney = CampaignMode.InitialMoney;
|
||||
if (isMultiplayer)
|
||||
{
|
||||
if (GameMain.NetLobbyScreen.SelectedSub != null)
|
||||
{
|
||||
initialMoney -= GameMain.NetLobbyScreen.SelectedSub.Price;
|
||||
}
|
||||
}
|
||||
else if (subList.SelectedData is SubmarineInfo subInfo)
|
||||
if (subList.SelectedData is SubmarineInfo subInfo)
|
||||
{
|
||||
initialMoney -= subInfo.Price;
|
||||
}
|
||||
initialMoney = Math.Max(initialMoney, isMultiplayer ? MultiPlayerCampaign.MinimumInitialMoney : 0);
|
||||
initialMoney = Math.Max(initialMoney, 0);
|
||||
return TextManager.GetWithVariable("campaignstartingmoney", "[money]", string.Format(CultureInfo.InvariantCulture, "{0:N0}", initialMoney));
|
||||
}
|
||||
};
|
||||
|
||||
if (!isMultiplayer)
|
||||
CampaignCustomizeButton = new GUIButton(new RectTransform(new Vector2(0.25f, 1f), firstPageButtonContainer.RectTransform, Anchor.CenterLeft), TextManager.Get("SettingsButton"))
|
||||
{
|
||||
CampaignCustomizeButton = new GUIButton(new RectTransform(new Vector2(0.25f, 1f), buttonContainer.RectTransform, Anchor.CenterLeft), TextManager.Get("SettingsButton"))
|
||||
OnClicked = (tb, userdata) =>
|
||||
{
|
||||
OnClicked = (tb, userdata) =>
|
||||
{
|
||||
CreateCustomizeWindow();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
CreateCustomizeWindow();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
var disclaimerBtn = new GUIButton(new RectTransform(new Vector2(1.0f, 0.8f), rightColumn.RectTransform, Anchor.TopRight) { AbsoluteOffset = new Point(5) }, style: "GUINotificationButton")
|
||||
nextButton = new GUIButton(new RectTransform(new Vector2(0.4f, 1f), firstPageButtonContainer.RectTransform, Anchor.BottomRight), TextManager.Get("Next"))
|
||||
{
|
||||
OnClicked = (GUIButton btn, object userData) =>
|
||||
{
|
||||
IgnoreLayoutGroups = true,
|
||||
OnClicked = (btn, userdata) => { GameMain.Instance.ShowCampaignDisclaimer(); return true; }
|
||||
};
|
||||
disclaimerBtn.RectTransform.MaxSize = new Point((int)(30 * GUI.Scale));
|
||||
}
|
||||
SetPage(1);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
var disclaimerBtn = new GUIButton(new RectTransform(new Vector2(1.0f, 0.8f), rightColumn.RectTransform, Anchor.TopRight) { AbsoluteOffset = new Point(5) }, style: "GUINotificationButton")
|
||||
{
|
||||
IgnoreLayoutGroups = true,
|
||||
OnClicked = (btn, userdata) => { GameMain.Instance.ShowCampaignDisclaimer(); return true; }
|
||||
};
|
||||
disclaimerBtn.RectTransform.MaxSize = new Point((int)(30 * GUI.Scale));
|
||||
|
||||
columnContainer.Recalculate();
|
||||
leftColumn.Recalculate();
|
||||
rightColumn.Recalculate();
|
||||
|
||||
if (submarines != null) { UpdateSubList(submarines); }
|
||||
UpdateLoadMenu(saveFiles);
|
||||
}
|
||||
|
||||
private void CreateSecondPage(GUILayoutGroup secondPageLayout)
|
||||
{
|
||||
secondPageLayout.RelativeSpacing = 0.01f;
|
||||
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.04f), secondPageLayout.RectTransform),
|
||||
TextManager.Get("Crew"), font: GUI.Style.SubHeadingFont, textAlignment: Alignment.TopLeft);
|
||||
|
||||
characterInfoColumns = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.86f), secondPageLayout.RectTransform), isHorizontal: true)
|
||||
{
|
||||
Stretch = true,
|
||||
RelativeSpacing = 0.01f
|
||||
};
|
||||
|
||||
var secondPageButtonContainer = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.08f),
|
||||
secondPageLayout.RectTransform), childAnchor: Anchor.BottomLeft, isHorizontal: true)
|
||||
{
|
||||
RelativeSpacing = 0.2f
|
||||
};
|
||||
|
||||
var backButton = new GUIButton(new RectTransform(new Vector2(0.4f, 1f), secondPageButtonContainer.RectTransform, Anchor.BottomRight), TextManager.Get("Back"))
|
||||
{
|
||||
OnClicked = (GUIButton btn, object userData) =>
|
||||
{
|
||||
SetPage(0);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
StartButton = new GUIButton(new RectTransform(new Vector2(0.4f, 1f), secondPageButtonContainer.RectTransform, Anchor.BottomRight), TextManager.Get("StartCampaignButton"))
|
||||
{
|
||||
OnClicked = FinishSetup
|
||||
};
|
||||
}
|
||||
|
||||
public void RandomizeCrew()
|
||||
{
|
||||
var characterInfos = new List<(CharacterInfo Info, JobPrefab Job)>();
|
||||
foreach (JobPrefab jobPrefab in JobPrefab.Prefabs)
|
||||
{
|
||||
for (int i = 0; i < jobPrefab.InitialCount; i++)
|
||||
{
|
||||
var variant = Rand.Range(0, jobPrefab.Variants);
|
||||
characterInfos.Add((new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobPrefab: jobPrefab, variant: variant), jobPrefab));
|
||||
}
|
||||
}
|
||||
|
||||
characterInfoColumns.ClearChildren();
|
||||
CharacterMenus?.ForEach(m => m.Dispose());
|
||||
CharacterMenus = new CharacterInfo.AppearanceCustomizationMenu[characterInfos.Count];
|
||||
|
||||
for (int i = 0; i < characterInfos.Count; i++)
|
||||
{
|
||||
var subLayout = new GUILayoutGroup(new RectTransform(new Vector2(1.0f / characterInfos.Count, 1.0f),
|
||||
characterInfoColumns.RectTransform));
|
||||
|
||||
var (characterInfo, job) = characterInfos[i];
|
||||
|
||||
characterInfo.CreateIcon(new RectTransform(new Vector2(1.0f, 0.275f), subLayout.RectTransform));
|
||||
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), subLayout.RectTransform), job.Name, job.UIColor);
|
||||
|
||||
var characterName = new GUITextBox(new RectTransform(new Vector2(1.0f, 0.1f), subLayout.RectTransform))
|
||||
{
|
||||
Text = characterInfo.Name,
|
||||
UserData = "random"
|
||||
};
|
||||
characterName.OnDeselected += (sender, key) =>
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(sender.Text))
|
||||
{
|
||||
characterInfo.Name = characterInfo.GetRandomName(Rand.RandSync.Unsynced);
|
||||
sender.Text = characterInfo.Name;
|
||||
sender.UserData = "random";
|
||||
}
|
||||
else
|
||||
{
|
||||
characterInfo.Name = sender.Text;
|
||||
sender.UserData = "user";
|
||||
}
|
||||
};
|
||||
characterName.OnEnterPressed += (sender, text) =>
|
||||
{
|
||||
sender.Deselect();
|
||||
return false;
|
||||
};
|
||||
|
||||
var customizationFrame =
|
||||
new GUIFrame(new RectTransform(new Vector2(1.0f, 0.6f), subLayout.RectTransform), style: null);
|
||||
CharacterMenus[i] =
|
||||
new CharacterInfo.AppearanceCustomizationMenu(characterInfo, customizationFrame, hasIcon: false)
|
||||
{
|
||||
OnHeadSwitch = menu =>
|
||||
{
|
||||
if (characterName.UserData is string ud && ud == "random")
|
||||
{
|
||||
characterInfo.Name = characterInfo.GetRandomName(Rand.RandSync.Unsynced);
|
||||
characterName.Text = characterInfo.Name;
|
||||
characterName.UserData = "random";
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private void CreateCustomizeWindow()
|
||||
{
|
||||
CampaignCustomizeSettings = new GUIMessageBox("", "", new string[] { TextManager.Get("OK") }, new Vector2(0.2f, 0.2f));
|
||||
@@ -355,106 +381,93 @@ namespace Barotrauma
|
||||
maxMissionCountContainer.Children.ForEach(c => c.ToolTip = maxMissionCountSettingHolder.ToolTip);
|
||||
}
|
||||
|
||||
private void CreateMultiplayerCampaignSubList(RectTransform parent)
|
||||
private bool FinishSetup(GUIButton btn, object userdata)
|
||||
{
|
||||
GUILayoutGroup subHolder = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.725f), parent))
|
||||
if (string.IsNullOrWhiteSpace(saveNameBox.Text))
|
||||
{
|
||||
RelativeSpacing = 0.005f,
|
||||
Stretch = true
|
||||
};
|
||||
saveNameBox.Flash(GUI.Style.Red);
|
||||
return false;
|
||||
}
|
||||
|
||||
var subLabel = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.055f), subHolder.RectTransform) { MinSize = new Point(0, 25) }, TextManager.Get("purchasablesubmarines", fallBackTag: "workshoplabelsubmarines"), font: GUI.SubHeadingFont);
|
||||
SubmarineInfo selectedSub = null;
|
||||
|
||||
var filterContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.05f), subHolder.RectTransform), isHorizontal: true)
|
||||
if (!(subList.SelectedData is SubmarineInfo)) { return false; }
|
||||
selectedSub = subList.SelectedData as SubmarineInfo;
|
||||
|
||||
if (selectedSub.SubmarineClass == SubmarineClass.Undefined)
|
||||
{
|
||||
Stretch = true
|
||||
};
|
||||
var searchTitle = new GUITextBlock(new RectTransform(new Vector2(0.001f, 1.0f), filterContainer.RectTransform), TextManager.Get("serverlog.filter"), textAlignment: Alignment.CenterLeft, font: GUI.Font);
|
||||
var searchBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 1.0f), filterContainer.RectTransform, Anchor.CenterRight), font: GUI.Font, createClearButton: true);
|
||||
filterContainer.RectTransform.MinSize = searchBox.RectTransform.MinSize;
|
||||
searchBox.OnSelected += (sender, userdata) => { searchTitle.Visible = false; };
|
||||
searchBox.OnDeselected += (sender, userdata) => { searchTitle.Visible = true; };
|
||||
searchBox.OnTextChanged += (textBox, text) =>
|
||||
new GUIMessageBox(TextManager.Get("error"), TextManager.Get("undefinedsubmarineselected"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(selectedSub.MD5Hash.Hash))
|
||||
{
|
||||
foreach (GUIComponent child in subList.Content.Children)
|
||||
((GUITextBlock)subList.SelectedComponent).TextColor = Color.DarkRed * 0.8f;
|
||||
subList.SelectedComponent.CanBeFocused = false;
|
||||
subList.Deselect();
|
||||
return false;
|
||||
}
|
||||
|
||||
string savePath = SaveUtil.CreateSavePath(SaveUtil.SaveType.Singleplayer, saveNameBox.Text);
|
||||
bool hasRequiredContentPackages = selectedSub.RequiredContentPackagesInstalled;
|
||||
|
||||
CampaignSettings settings = new CampaignSettings();
|
||||
settings.RadiationEnabled = EnableRadiationToggle?.Selected ?? false;
|
||||
if (MaxMissionCountText != null && Int32.TryParse(MaxMissionCountText.Text, out int missionCount))
|
||||
{
|
||||
settings.MaxMissionCount = missionCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
settings.MaxMissionCount = CampaignSettings.DefaultMaxMissionCount;
|
||||
}
|
||||
|
||||
if (selectedSub.HasTag(SubmarineTag.Shuttle) || !hasRequiredContentPackages)
|
||||
{
|
||||
if (!hasRequiredContentPackages)
|
||||
{
|
||||
if (!(child.UserData is SubmarineInfo sub)) { continue; }
|
||||
child.Visible = string.IsNullOrEmpty(text) ? true : sub.DisplayName.ToLower().Contains(text.ToLower());
|
||||
}
|
||||
return true;
|
||||
};
|
||||
var msgBox = new GUIMessageBox(TextManager.Get("ContentPackageMismatch"),
|
||||
TextManager.GetWithVariable("ContentPackageMismatchWarning", "[requiredcontentpackages]", string.Join(", ", selectedSub.RequiredContentPackages)),
|
||||
new string[] { TextManager.Get("Yes"), TextManager.Get("No") });
|
||||
|
||||
subList = new GUIListBox(new RectTransform(Vector2.One, subHolder.RectTransform));
|
||||
subTickBoxes = new List<GUITickBox>();
|
||||
|
||||
for (int i = 0; i < GameMain.Client.ServerSubmarines.Count; i++)
|
||||
{
|
||||
SubmarineInfo sub = GameMain.Client.ServerSubmarines[i];
|
||||
|
||||
if (!sub.IsCampaignCompatible) continue;
|
||||
|
||||
var frame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.2f), subList.Content.RectTransform) { MinSize = new Point(0, 20) },
|
||||
style: "ListBoxElement")
|
||||
{
|
||||
ToolTip = sub.Description,
|
||||
UserData = sub
|
||||
};
|
||||
|
||||
int buttonSize = (int)(frame.Rect.Height * 0.8f);
|
||||
|
||||
GUITickBox tickBox = new GUITickBox(new RectTransform(new Vector2(0.8f, 1.0f), frame.RectTransform, Anchor.CenterLeft), ToolBox.LimitString(sub.DisplayName, GUI.Font, subList.Content.Rect.Width - 65))
|
||||
{
|
||||
UserData = sub,
|
||||
OnSelected = (GUITickBox box) =>
|
||||
msgBox.Buttons[0].OnClicked = msgBox.Close;
|
||||
msgBox.Buttons[0].OnClicked += (button, obj) =>
|
||||
{
|
||||
GameMain.Client.RequestCampaignSub(box.UserData as SubmarineInfo, box.Selected);
|
||||
if (GUIMessageBox.MessageBoxes.Count == 0)
|
||||
{
|
||||
StartNewGame?.Invoke(selectedSub, savePath, seedBox.Text, settings);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
subTickBoxes.Add(tickBox);
|
||||
tickBox.Selected = GameMain.NetLobbyScreen.CampaignSubmarines.Contains(sub);
|
||||
};
|
||||
|
||||
frame.RectTransform.MinSize = new Point(0, tickBox.RectTransform.MinSize.Y);
|
||||
|
||||
var subTextBlock = tickBox.TextBlock;
|
||||
|
||||
var matchingSub = SubmarineInfo.SavedSubmarines.FirstOrDefault(s => s.Name == sub.Name && s.MD5Hash?.Hash == sub.MD5Hash?.Hash);
|
||||
if (matchingSub == null) matchingSub = SubmarineInfo.SavedSubmarines.FirstOrDefault(s => s.Name == sub.Name);
|
||||
|
||||
if (matchingSub == null)
|
||||
{
|
||||
subTextBlock.TextColor = new Color(subTextBlock.TextColor, 0.5f);
|
||||
frame.ToolTip = TextManager.Get("SubNotFound");
|
||||
}
|
||||
else if (matchingSub?.MD5Hash == null || matchingSub.MD5Hash?.Hash != sub.MD5Hash?.Hash)
|
||||
{
|
||||
subTextBlock.TextColor = new Color(subTextBlock.TextColor, 0.5f);
|
||||
frame.ToolTip = TextManager.Get("SubDoesntMatch");
|
||||
msgBox.Buttons[1].OnClicked = msgBox.Close;
|
||||
}
|
||||
|
||||
if (!sub.RequiredContentPackagesInstalled)
|
||||
if (selectedSub.HasTag(SubmarineTag.Shuttle))
|
||||
{
|
||||
subTextBlock.TextColor = Color.Lerp(subTextBlock.TextColor, Color.DarkRed, 0.5f);
|
||||
frame.ToolTip = TextManager.Get("ContentPackageMismatch") + "\n\n" + frame.RawToolTip;
|
||||
}
|
||||
var msgBox = new GUIMessageBox(TextManager.Get("ShuttleSelected"),
|
||||
TextManager.Get("ShuttleWarning"),
|
||||
new string[] { TextManager.Get("Yes"), TextManager.Get("No") });
|
||||
|
||||
var classText = new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), frame.RectTransform, Anchor.CenterRight),
|
||||
TextManager.Get($"submarineclass.{sub.SubmarineClass}"), textAlignment: Alignment.CenterRight, font: GUI.SmallFont)
|
||||
{
|
||||
TextColor = subTextBlock.TextColor * 0.8f,
|
||||
ToolTip = subTextBlock.RawToolTip
|
||||
};
|
||||
msgBox.Buttons[0].OnClicked = (button, obj) =>
|
||||
{
|
||||
StartNewGame?.Invoke(selectedSub, savePath, seedBox.Text, settings);
|
||||
return true;
|
||||
};
|
||||
msgBox.Buttons[0].OnClicked += msgBox.Close;
|
||||
|
||||
msgBox.Buttons[1].OnClicked = msgBox.Close;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void RefreshMultiplayerCampaignSubUI(List<SubmarineInfo> campaignSubs)
|
||||
{
|
||||
for (int i = 0; i < subTickBoxes.Count; i++)
|
||||
else
|
||||
{
|
||||
subTickBoxes[i].Selected = campaignSubs.Contains(subTickBoxes[i].UserData as SubmarineInfo);
|
||||
StartNewGame?.Invoke(selectedSub, savePath, seedBox.Text, settings);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void RandomizeSeed()
|
||||
{
|
||||
seedBox.Text = ToolBox.RandomSeed(8);
|
||||
@@ -478,54 +491,28 @@ namespace Barotrauma
|
||||
|
||||
if (!(obj is SubmarineInfo sub)) { return true; }
|
||||
#if !DEBUG
|
||||
if (!isMultiplayer && sub.Price > CampaignMode.InitialMoney && !GameMain.DebugDraw)
|
||||
if (sub.Price > CampaignMode.InitialMoney && !GameMain.DebugDraw)
|
||||
{
|
||||
StartButton.Enabled = false;
|
||||
SetPage(0);
|
||||
nextButton.Enabled = false;
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
StartButton.Enabled = true;
|
||||
nextButton.Enabled = true;
|
||||
sub.CreatePreviewWindow(subPreviewContainer);
|
||||
return true;
|
||||
}
|
||||
|
||||
private IEnumerable<object> WaitForCampaignSetup()
|
||||
{
|
||||
GUI.SetCursorWaiting();
|
||||
string headerText = TextManager.Get("CampaignStartingPleaseWait");
|
||||
var msgBox = new GUIMessageBox(headerText, TextManager.Get("CampaignStarting"), new string[] { TextManager.Get("Cancel") });
|
||||
|
||||
msgBox.Buttons[0].OnClicked = (btn, userdata) =>
|
||||
{
|
||||
GameMain.NetLobbyScreen.HighlightMode(GameMain.NetLobbyScreen.SelectedModeIndex);
|
||||
GameMain.NetLobbyScreen.SelectMode(GameMain.NetLobbyScreen.SelectedModeIndex);
|
||||
GUI.ClearCursorWait();
|
||||
CoroutineManager.StopCoroutines("WaitForCampaignSetup");
|
||||
return true;
|
||||
};
|
||||
msgBox.Buttons[0].OnClicked += msgBox.Close;
|
||||
|
||||
DateTime timeOut = DateTime.Now + new TimeSpan(0, 0, 20);
|
||||
while (Screen.Selected != GameMain.GameScreen && DateTime.Now < timeOut)
|
||||
{
|
||||
msgBox.Header.Text = headerText + new string('.', (int)Timing.TotalTime % 3 + 1);
|
||||
yield return CoroutineStatus.Running;
|
||||
}
|
||||
msgBox.Close();
|
||||
GUI.ClearCursorWait();
|
||||
yield return CoroutineStatus.Success;
|
||||
}
|
||||
|
||||
public void CreateDefaultSaveName()
|
||||
{
|
||||
string savePath = SaveUtil.CreateSavePath(isMultiplayer ? SaveUtil.SaveType.Multiplayer : SaveUtil.SaveType.Singleplayer);
|
||||
string savePath = SaveUtil.CreateSavePath(SaveUtil.SaveType.Singleplayer);
|
||||
saveNameBox.Text = Path.GetFileNameWithoutExtension(savePath);
|
||||
}
|
||||
|
||||
public void UpdateSubList(IEnumerable<SubmarineInfo> submarines)
|
||||
{
|
||||
List<SubmarineInfo> subsToShow;
|
||||
if (!isMultiplayer && subFilter != CategoryFilter.All)
|
||||
if (subFilter != CategoryFilter.All)
|
||||
{
|
||||
subsToShow = submarines.Where(s => s.IsCampaignCompatibleIgnoreClass && s.IsVanillaSubmarine() == (subFilter == CategoryFilter.Vanilla)).ToList();
|
||||
}
|
||||
@@ -596,10 +583,10 @@ namespace Barotrauma
|
||||
|
||||
if (saveFiles == null)
|
||||
{
|
||||
saveFiles = SaveUtil.GetSaveFiles(isMultiplayer ? SaveUtil.SaveType.Multiplayer : SaveUtil.SaveType.Singleplayer);
|
||||
saveFiles = SaveUtil.GetSaveFiles(SaveUtil.SaveType.Singleplayer);
|
||||
}
|
||||
|
||||
var leftColumn = new GUILayoutGroup(new RectTransform(isMultiplayer ? new Vector2(1.0f, 0.85f) : new Vector2(0.5f, 1.0f), loadGameContainer.RectTransform), childAnchor: Anchor.TopCenter)
|
||||
var leftColumn = new GUILayoutGroup(new RectTransform(new Vector2(0.5f, 1.0f), loadGameContainer.RectTransform), childAnchor: Anchor.TopCenter)
|
||||
{
|
||||
Stretch = true,
|
||||
RelativeSpacing = 0.03f
|
||||
@@ -610,26 +597,23 @@ namespace Barotrauma
|
||||
OnSelected = SelectSaveFile
|
||||
};
|
||||
|
||||
if (!isMultiplayer)
|
||||
new GUIButton(new RectTransform(new Vector2(0.6f, 0.08f), leftColumn.RectTransform), TextManager.Get("showinfolder"))
|
||||
{
|
||||
new GUIButton(new RectTransform(new Vector2(0.6f, 0.08f), leftColumn.RectTransform), TextManager.Get("showinfolder"))
|
||||
OnClicked = (btn, userdata) =>
|
||||
{
|
||||
OnClicked = (btn, userdata) =>
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
ToolBox.OpenFileWithShell(SaveUtil.SaveFolder);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
new GUIMessageBox(
|
||||
TextManager.Get("error"),
|
||||
TextManager.GetWithVariables("showinfoldererror", new string[] { "[folder]", "[errormessage]" }, new string[] { SaveUtil.SaveFolder, e.Message }));
|
||||
}
|
||||
return true;
|
||||
ToolBox.OpenFileWithShell(SaveUtil.SaveFolder);
|
||||
}
|
||||
};
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
new GUIMessageBox(
|
||||
TextManager.Get("error"),
|
||||
TextManager.GetWithVariables("showinfoldererror", new string[] { "[folder]", "[errormessage]" }, new string[] { SaveUtil.SaveFolder, e.Message }));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
foreach (string saveFile in saveFiles)
|
||||
{
|
||||
@@ -649,39 +633,27 @@ namespace Barotrauma
|
||||
|
||||
bool isCompatible = true;
|
||||
prevSaveFiles ??= new List<string>();
|
||||
if (!isMultiplayer)
|
||||
{
|
||||
nameText.Text = Path.GetFileNameWithoutExtension(saveFile);
|
||||
XDocument doc = SaveUtil.LoadGameSessionDoc(saveFile);
|
||||
|
||||
if (doc?.Root == null)
|
||||
{
|
||||
DebugConsole.ThrowError("Error loading save file \"" + saveFile + "\". The file may be corrupted.");
|
||||
nameText.TextColor = GUI.Style.Red;
|
||||
continue;
|
||||
}
|
||||
if (doc.Root.GetChildElement("multiplayercampaign") != null)
|
||||
{
|
||||
//multiplayer campaign save in the wrong folder -> don't show the save
|
||||
saveList.Content.RemoveChild(saveFrame);
|
||||
continue;
|
||||
}
|
||||
subName = doc.Root.GetAttributeString("submarine", "");
|
||||
saveTime = doc.Root.GetAttributeString("savetime", "");
|
||||
isCompatible = SaveUtil.IsSaveFileCompatible(doc);
|
||||
contentPackageStr = doc.Root.GetAttributeString("selectedcontentpackages", "");
|
||||
prevSaveFiles?.Add(saveFile);
|
||||
}
|
||||
else
|
||||
nameText.Text = Path.GetFileNameWithoutExtension(saveFile);
|
||||
XDocument doc = SaveUtil.LoadGameSessionDoc(saveFile);
|
||||
|
||||
if (doc?.Root == null)
|
||||
{
|
||||
prevSaveFiles?.Add(saveFile);
|
||||
string[] splitSaveFile = saveFile.Split(';');
|
||||
saveFrame.UserData = splitSaveFile[0];
|
||||
fileName = nameText.Text = Path.GetFileNameWithoutExtension(splitSaveFile[0]);
|
||||
if (splitSaveFile.Length > 1) { subName = splitSaveFile[1]; }
|
||||
if (splitSaveFile.Length > 2) { saveTime = splitSaveFile[2]; }
|
||||
if (splitSaveFile.Length > 3) { contentPackageStr = splitSaveFile[3]; }
|
||||
DebugConsole.ThrowError("Error loading save file \"" + saveFile + "\". The file may be corrupted.");
|
||||
nameText.TextColor = GUI.Style.Red;
|
||||
continue;
|
||||
}
|
||||
if (doc.Root.GetChildElement("multiplayercampaign") != null)
|
||||
{
|
||||
//multiplayer campaign save in the wrong folder -> don't show the save
|
||||
saveList.Content.RemoveChild(saveFrame);
|
||||
continue;
|
||||
}
|
||||
subName = doc.Root.GetAttributeString("submarine", "");
|
||||
saveTime = doc.Root.GetAttributeString("savetime", "");
|
||||
isCompatible = SaveUtil.IsSaveFileCompatible(doc);
|
||||
contentPackageStr = doc.Root.GetAttributeString("selectedcontentpackages", "");
|
||||
prevSaveFiles?.Add(saveFile);
|
||||
if (!string.IsNullOrEmpty(saveTime) && long.TryParse(saveTime, out long unixTime))
|
||||
{
|
||||
DateTime time = ToolBox.Epoch.ToDateTime(unixTime);
|
||||
@@ -748,38 +720,16 @@ namespace Barotrauma
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(saveList.SelectedData as string)) { return false; }
|
||||
LoadGame?.Invoke(saveList.SelectedData as string);
|
||||
if (isMultiplayer)
|
||||
{
|
||||
CoroutineManager.StartCoroutine(WaitForCampaignSetup(), "WaitForCampaignSetup");
|
||||
}
|
||||
return true;
|
||||
},
|
||||
Enabled = false
|
||||
};
|
||||
deleteMpSaveButton = new GUIButton(new RectTransform(new Vector2(0.45f, 0.12f), loadGameContainer.RectTransform, Anchor.BottomLeft),
|
||||
TextManager.Get("Delete"), style: "GUIButtonSmall")
|
||||
{
|
||||
OnClicked = DeleteSave,
|
||||
Visible = false
|
||||
};
|
||||
}
|
||||
|
||||
private bool SelectSaveFile(GUIComponent component, object obj)
|
||||
{
|
||||
string fileName = (string)obj;
|
||||
|
||||
if (isMultiplayer)
|
||||
{
|
||||
loadGameButton.Enabled = true;
|
||||
deleteMpSaveButton.Visible = deleteMpSaveButton.Enabled = GameMain.Client.IsServerOwner;
|
||||
deleteMpSaveButton.Enabled = GameMain.GameSession?.SavePath != fileName;
|
||||
if (deleteMpSaveButton.Visible)
|
||||
{
|
||||
deleteMpSaveButton.UserData = obj as string;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
XDocument doc = SaveUtil.LoadGameSessionDoc(fileName);
|
||||
if (doc?.Root == null)
|
||||
{
|
||||
@@ -868,6 +818,5 @@ namespace Barotrauma
|
||||
}
|
||||
loadGameContainer.RemoveChild(prevFrame);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
+22
-25
@@ -182,7 +182,7 @@ namespace Barotrauma.CharacterEditor
|
||||
showSpritesheet = false;
|
||||
isFrozen = false;
|
||||
autoFreeze = false;
|
||||
limbPairEditing = true;
|
||||
limbPairEditing = false;
|
||||
uniformScaling = true;
|
||||
lockSpriteOrigin = true;
|
||||
lockSpritePosition = false;
|
||||
@@ -1581,7 +1581,6 @@ namespace Barotrauma.CharacterEditor
|
||||
Character.Controlled = character;
|
||||
SetWallCollisions(character.AnimController.forceStanding);
|
||||
CreateTextures();
|
||||
limbPairEditing = character.IsHumanoid;
|
||||
CreateGUI();
|
||||
ClearWidgets();
|
||||
ClearSelection();
|
||||
@@ -1803,6 +1802,7 @@ namespace Barotrauma.CharacterEditor
|
||||
{
|
||||
case AnimationType.Walk:
|
||||
case AnimationType.Run:
|
||||
case AnimationType.Crouch:
|
||||
if (!ragdollParams.CanWalk) { continue; }
|
||||
break;
|
||||
case AnimationType.SwimSlow:
|
||||
@@ -1819,8 +1819,8 @@ namespace Barotrauma.CharacterEditor
|
||||
{
|
||||
AllFiles.Add(configFilePath);
|
||||
}
|
||||
limbPairEditing = false;
|
||||
SpawnCharacter(configFilePath, ragdollParams);
|
||||
limbPairEditing = false;
|
||||
limbsToggle.Selected = true;
|
||||
recalculateColliderToggle.Selected = true;
|
||||
lockSpriteOriginToggle.Selected = false;
|
||||
@@ -2599,11 +2599,15 @@ namespace Barotrauma.CharacterEditor
|
||||
var layoutGroupAnimation = new GUILayoutGroup(new RectTransform(Vector2.One, animationControls.RectTransform), childAnchor: Anchor.TopLeft) { CanBeFocused = false };
|
||||
var animationSelectionElement = new GUIFrame(new RectTransform(new Point(elementSize.X * 2 - (int)(5 * GUI.xScale), elementSize.Y), layoutGroupAnimation.RectTransform), style: null);
|
||||
var animationSelectionText = new GUITextBlock(new RectTransform(new Point(elementSize.X, elementSize.Y), animationSelectionElement.RectTransform), GetCharacterEditorTranslation("SelectedAnimation") + ": ", Color.WhiteSmoke, textAlignment: Alignment.Center);
|
||||
animSelection = new GUIDropDown(new RectTransform(new Point((int)(100 * GUI.xScale), elementSize.Y), animationSelectionElement.RectTransform, Anchor.TopRight), elementCount: 4);
|
||||
animSelection = new GUIDropDown(new RectTransform(new Point((int)(100 * GUI.xScale), elementSize.Y), animationSelectionElement.RectTransform, Anchor.TopRight), elementCount: 5);
|
||||
if (character.AnimController.CanWalk)
|
||||
{
|
||||
animSelection.AddItem(AnimationType.Walk.ToString(), AnimationType.Walk);
|
||||
animSelection.AddItem(AnimationType.Run.ToString(), AnimationType.Run);
|
||||
if (character.IsHumanoid)
|
||||
{
|
||||
animSelection.AddItem(AnimationType.Crouch.ToString(), AnimationType.Crouch);
|
||||
}
|
||||
}
|
||||
animSelection.AddItem(AnimationType.SwimSlow.ToString(), AnimationType.SwimSlow);
|
||||
animSelection.AddItem(AnimationType.SwimFast.ToString(), AnimationType.SwimFast);
|
||||
@@ -2622,25 +2626,15 @@ namespace Barotrauma.CharacterEditor
|
||||
switch (character.AnimController.ForceSelectAnimationType)
|
||||
{
|
||||
case AnimationType.Walk:
|
||||
character.AnimController.forceStanding = true;
|
||||
character.ForceRun = false;
|
||||
if (!wallCollisionsEnabled)
|
||||
{
|
||||
SetWallCollisions(true);
|
||||
}
|
||||
if (previousAnim != AnimationType.Walk && previousAnim != AnimationType.Run)
|
||||
{
|
||||
TeleportTo(spawnPosition);
|
||||
}
|
||||
break;
|
||||
case AnimationType.Run:
|
||||
case AnimationType.Crouch:
|
||||
character.AnimController.forceStanding = true;
|
||||
character.ForceRun = true;
|
||||
character.ForceRun = character.AnimController.ForceSelectAnimationType == AnimationType.Run;
|
||||
if (!wallCollisionsEnabled)
|
||||
{
|
||||
SetWallCollisions(true);
|
||||
}
|
||||
if (previousAnim != AnimationType.Walk && previousAnim != AnimationType.Run)
|
||||
if (previousAnim != AnimationType.Walk && previousAnim != AnimationType.Run && previousAnim != AnimationType.Crouch)
|
||||
{
|
||||
TeleportTo(spawnPosition);
|
||||
}
|
||||
@@ -3046,21 +3040,24 @@ namespace Barotrauma.CharacterEditor
|
||||
loadBox.Buttons[1].OnClicked += (btn, data) =>
|
||||
{
|
||||
string fileName = Path.GetFileNameWithoutExtension(selectedFile);
|
||||
if (character.IsHumanoid)
|
||||
if (character.IsHumanoid && character.AnimController is HumanoidAnimController humanAnimController)
|
||||
{
|
||||
switch (selectedType)
|
||||
{
|
||||
case AnimationType.Walk:
|
||||
character.AnimController.WalkParams = HumanWalkParams.GetAnimParams(character, fileName);
|
||||
humanAnimController.WalkParams = HumanWalkParams.GetAnimParams(character, fileName);
|
||||
break;
|
||||
case AnimationType.Run:
|
||||
character.AnimController.RunParams = HumanRunParams.GetAnimParams(character, fileName);
|
||||
humanAnimController.RunParams = HumanRunParams.GetAnimParams(character, fileName);
|
||||
break;
|
||||
case AnimationType.Crouch:
|
||||
humanAnimController.HumanCrouchParams = HumanCrouchParams.GetAnimParams(character, fileName);
|
||||
break;
|
||||
case AnimationType.SwimSlow:
|
||||
character.AnimController.SwimSlowParams = HumanSwimSlowParams.GetAnimParams(character, fileName);
|
||||
humanAnimController.SwimSlowParams = HumanSwimSlowParams.GetAnimParams(character, fileName);
|
||||
break;
|
||||
case AnimationType.SwimFast:
|
||||
character.AnimController.SwimFastParams = HumanSwimFastParams.GetAnimParams(character, fileName);
|
||||
humanAnimController.SwimFastParams = HumanSwimFastParams.GetAnimParams(character, fileName);
|
||||
break;
|
||||
default:
|
||||
DebugConsole.ThrowError(GetCharacterEditorTranslation("AnimationTypeNotImplemented").Replace("[type]", selectedType.ToString()));
|
||||
@@ -4152,7 +4149,7 @@ namespace Barotrauma.CharacterEditor
|
||||
float offset = 0.1f;
|
||||
w.refresh = () =>
|
||||
{
|
||||
var refPoint = SimToScreen(collider.SimPosition + GetSimSpaceForward() * offset);
|
||||
var refPoint = SimToScreen(character.AnimController.Collider.SimPosition + GetSimSpaceForward() * offset);
|
||||
var handMovement = ConvertUnits.ToDisplayUnits(humanGroundedParams.HandMoveAmount);
|
||||
w.DrawPos = refPoint + new Vector2(handMovement.X * character.AnimController.Dir, handMovement.Y) * Cam.Zoom;
|
||||
};
|
||||
@@ -4167,7 +4164,7 @@ namespace Barotrauma.CharacterEditor
|
||||
{
|
||||
if (w.IsSelected)
|
||||
{
|
||||
GUI.DrawLine(sp, w.DrawPos, SimToScreen(collider.SimPosition + GetSimSpaceForward() * offset), GUI.Style.Green);
|
||||
GUI.DrawLine(sp, w.DrawPos, SimToScreen(character.AnimController.Collider.SimPosition + GetSimSpaceForward() * offset), GUI.Style.Green);
|
||||
}
|
||||
};
|
||||
}).Draw(spriteBatch, deltaTime);
|
||||
@@ -4731,7 +4728,7 @@ namespace Barotrauma.CharacterEditor
|
||||
rotation: 0,
|
||||
origin: orig,
|
||||
sourceRectangle: wearable.InheritSourceRect ? limb.ActiveSprite.SourceRect : wearable.Sprite.SourceRect,
|
||||
scale: (wearable.InheritTextureScale ? 1 : wearable.Scale / RagdollParams.TextureScale) * spriteSheetZoom,
|
||||
scale: (wearable.InheritScale ? 1 : wearable.Scale / RagdollParams.TextureScale) * spriteSheetZoom,
|
||||
effects: SpriteEffects.None,
|
||||
color: Color.White,
|
||||
layerDepth: 0);
|
||||
|
||||
@@ -284,7 +284,7 @@ namespace Barotrauma.CharacterEditor
|
||||
}
|
||||
|
||||
isTextureSelected = true;
|
||||
texturePathElement.Text = destinationPath;
|
||||
texturePathElement.Text = destinationPath.CleanUpPath();
|
||||
};
|
||||
FileSelection.ClearFileTypeFilters();
|
||||
FileSelection.AddFileTypeFilter("PNG", "*.png");
|
||||
@@ -431,7 +431,7 @@ namespace Barotrauma.CharacterEditor
|
||||
box.Header.Font = GUI.LargeFont;
|
||||
box.Content.ChildAnchor = Anchor.TopCenter;
|
||||
box.Content.AbsoluteSpacing = (int)(20 * GUI.Scale);
|
||||
int elementSize = (int)(30 * GUI.Scale);
|
||||
int elementSize = (int)(40 * GUI.Scale);
|
||||
var frame = new GUIFrame(new RectTransform(new Point(box.Content.Rect.Width - (int)(80 * GUI.xScale), box.Content.Rect.Height - (int)(200 * GUI.yScale)),
|
||||
box.Content.RectTransform, Anchor.Center), style: null, color: ParamsEditor.Color)
|
||||
{
|
||||
@@ -625,8 +625,12 @@ namespace Barotrauma.CharacterEditor
|
||||
var jointsElement = new GUIFrame(new RectTransform(new Vector2(1, 0.05f), content.RectTransform), style: null) { CanBeFocused = false };
|
||||
new GUITextBlock(new RectTransform(new Vector2(0.2f, 1f), jointsElement.RectTransform), GetCharacterEditorTranslation("Joints"), font: GUI.SubHeadingFont);
|
||||
var jointButtonElement = new GUIFrame(new RectTransform(new Vector2(0.5f, 1f), jointsElement.RectTransform)
|
||||
{ RelativeOffset = new Vector2(0.15f, 0) }, style: null)
|
||||
{ CanBeFocused = false };
|
||||
{
|
||||
RelativeOffset = new Vector2(0.15f, 0)
|
||||
}, style: null)
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
var jointsList = new GUIListBox(new RectTransform(new Vector2(1, 0.45f), content.RectTransform));
|
||||
var removeJointButton = new GUIButton(new RectTransform(new Point(jointButtonElement.Rect.Height, jointButtonElement.Rect.Height), jointButtonElement.RectTransform), style: "GUIMinusButton")
|
||||
{
|
||||
@@ -824,7 +828,7 @@ namespace Barotrauma.CharacterEditor
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
var group = new GUILayoutGroup(new RectTransform(Vector2.One, limbElement.RectTransform)) { AbsoluteSpacing = 2 };
|
||||
var group = new GUILayoutGroup(new RectTransform(Vector2.One, limbElement.RectTransform)) { AbsoluteSpacing = 16 };
|
||||
var label = new GUITextBlock(new RectTransform(new Point(group.Rect.Width, elementSize), group.RectTransform), name, font: GUI.SubHeadingFont);
|
||||
var idField = new GUIFrame(new RectTransform(new Point(group.Rect.Width, elementSize), group.RectTransform), style: null);
|
||||
var nameField = new GUIFrame(new RectTransform(new Point(group.Rect.Width, elementSize), group.RectTransform), style: null);
|
||||
|
||||
@@ -25,6 +25,7 @@ namespace Barotrauma
|
||||
public Effect PostProcessEffect { get; private set; }
|
||||
public Effect GradientEffect { get; private set; }
|
||||
public Effect GrainEffect { get; private set; }
|
||||
public Effect ThresholdTintEffect { get; private set; }
|
||||
public Effect BlueprintEffect { get; set; }
|
||||
|
||||
public GameScreen(GraphicsDevice graphics, ContentManager content)
|
||||
@@ -38,21 +39,20 @@ namespace Barotrauma
|
||||
CreateRenderTargets(graphics);
|
||||
};
|
||||
|
||||
Effect LoadEffect(string path)
|
||||
=> content.Load<Effect>(path
|
||||
#if LINUX || OSX
|
||||
//var blurEffect = content.Load<Effect>("Effects/blurshader_opengl");
|
||||
damageEffect = content.Load<Effect>("Effects/damageshader_opengl");
|
||||
PostProcessEffect = content.Load<Effect>("Effects/postprocess_opengl");
|
||||
GradientEffect = content.Load<Effect>("Effects/gradientshader_opengl");
|
||||
GrainEffect = content.Load<Effect>("Effects/grainshader_opengl");
|
||||
BlueprintEffect = content.Load<Effect>("Effects/blueprintshader_opengl");
|
||||
#else
|
||||
//var blurEffect = content.Load<Effect>("Effects/blurshader");
|
||||
damageEffect = content.Load<Effect>("Effects/damageshader");
|
||||
PostProcessEffect = content.Load<Effect>("Effects/postprocess");
|
||||
GradientEffect = content.Load<Effect>("Effects/gradientshader");
|
||||
GrainEffect = content.Load<Effect>("Effects/grainshader");
|
||||
BlueprintEffect = content.Load<Effect>("Effects/blueprintshader");
|
||||
+"_opengl"
|
||||
#endif
|
||||
);
|
||||
|
||||
//var blurEffect = LoadEffect("Effects/blurshader");
|
||||
damageEffect = LoadEffect("Effects/damageshader");
|
||||
PostProcessEffect = LoadEffect("Effects/postprocess");
|
||||
GradientEffect = LoadEffect("Effects/gradientshader");
|
||||
GrainEffect = LoadEffect("Effects/grainshader");
|
||||
ThresholdTintEffect = LoadEffect("Effects/thresholdtint");
|
||||
BlueprintEffect = LoadEffect("Effects/blueprintshader");
|
||||
|
||||
damageStencil = TextureLoader.FromFile("Content/Map/walldamage.png");
|
||||
damageEffect.Parameters["xStencil"].SetValue(damageStencil);
|
||||
|
||||
@@ -40,7 +40,7 @@ namespace Barotrauma
|
||||
|
||||
private readonly GUIFrame[] menuTabs;
|
||||
|
||||
private CampaignSetupUI campaignSetupUI;
|
||||
private SinglePlayerCampaignSetupUI campaignSetupUI;
|
||||
|
||||
private GUITextBox serverNameBox, /*portBox, queryPortBox,*/ passwordBox, maxPlayersBox;
|
||||
private GUITickBox isPublicBox, wrongPasswordBanBox, karmaBox;
|
||||
@@ -594,6 +594,8 @@ namespace Barotrauma
|
||||
GameMain.Instance.ShowCampaignDisclaimer(() => { SelectTab(null, Tab.NewGame); });
|
||||
return true;
|
||||
}
|
||||
campaignSetupUI.RandomizeCrew();
|
||||
campaignSetupUI.SetPage(0);
|
||||
campaignSetupUI.CreateDefaultSaveName();
|
||||
campaignSetupUI.RandomizeSeed();
|
||||
campaignSetupUI.UpdateSubList(SubmarineInfo.SavedSubmarines);
|
||||
@@ -985,24 +987,32 @@ namespace Barotrauma
|
||||
if (selectedTab < Tab.Empty && menuTabs[(int)selectedTab] != null)
|
||||
{
|
||||
menuTabs[(int)selectedTab].AddToGUIUpdateList();
|
||||
switch (selectedTab)
|
||||
{
|
||||
case Tab.NewGame:
|
||||
campaignSetupUI.CharacterMenus?.ForEach(m => m.AddToGUIUpdateList());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Update(double deltaTime)
|
||||
{
|
||||
#if !DEBUG
|
||||
#if USE_STEAM
|
||||
#if !DEBUG && USE_STEAM
|
||||
if (GameMain.Config.UseSteamMatchmaking)
|
||||
{
|
||||
hostServerButton.Enabled = Steam.SteamManager.IsInitialized;
|
||||
}
|
||||
steamWorkshopButton.Enabled = Steam.SteamManager.IsInitialized;
|
||||
#endif
|
||||
#else
|
||||
#if USE_STEAM
|
||||
#elif USE_STEAM
|
||||
steamWorkshopButton.Enabled = true;
|
||||
#endif
|
||||
#endif
|
||||
switch (selectedTab)
|
||||
{
|
||||
case Tab.NewGame:
|
||||
campaignSetupUI.Update();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void DrawBackground(GraphicsDevice graphics, SpriteBatch spriteBatch)
|
||||
@@ -1119,6 +1129,11 @@ namespace Barotrauma
|
||||
selectedSub = new SubmarineInfo(Path.Combine(SaveUtil.TempPath, selectedSub.Name + ".sub"));
|
||||
|
||||
GameMain.GameSession = new GameSession(selectedSub, saveName, GameModePreset.SinglePlayerCampaign, settings, mapSeed);
|
||||
GameMain.GameSession.CrewManager.CharacterInfos.Clear();
|
||||
foreach (var characterInfo in campaignSetupUI.CharacterMenus.Select(m => m.CharacterInfo))
|
||||
{
|
||||
GameMain.GameSession.CrewManager.AddCharacterInfo(characterInfo);
|
||||
}
|
||||
((SinglePlayerCampaign)GameMain.GameSession.GameMode).LoadNewLevel();
|
||||
}
|
||||
|
||||
@@ -1146,7 +1161,7 @@ namespace Barotrauma
|
||||
menuTabs[(int)Tab.NewGame].ClearChildren();
|
||||
menuTabs[(int)Tab.LoadGame].ClearChildren();
|
||||
|
||||
var innerNewGame = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.9f), menuTabs[(int)Tab.NewGame].RectTransform, Anchor.Center) { RelativeOffset = new Vector2(0.0f, 0.025f) })
|
||||
var innerNewGame = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.9f), menuTabs[(int)Tab.NewGame].RectTransform, Anchor.Center))
|
||||
{
|
||||
Stretch = true,
|
||||
RelativeSpacing = 0.02f
|
||||
@@ -1154,30 +1169,14 @@ namespace Barotrauma
|
||||
var newGameContent = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.95f), innerNewGame.RectTransform, Anchor.Center),
|
||||
style: "InnerFrame");
|
||||
|
||||
var paddedNewGame = new GUIFrame(new RectTransform(new Vector2(0.95f), newGameContent.RectTransform, Anchor.Center), style: null);
|
||||
var paddedLoadGame = new GUIFrame(new RectTransform(new Vector2(0.9f, 0.9f), menuTabs[(int)Tab.LoadGame].RectTransform, Anchor.Center) { AbsoluteOffset = new Point(0, 10) },
|
||||
style: null);
|
||||
|
||||
campaignSetupUI = new CampaignSetupUI(false, paddedNewGame, paddedLoadGame, SubmarineInfo.SavedSubmarines)
|
||||
campaignSetupUI = new SinglePlayerCampaignSetupUI(newGameContent, paddedLoadGame, SubmarineInfo.SavedSubmarines)
|
||||
{
|
||||
LoadGame = LoadGame,
|
||||
StartNewGame = StartGame
|
||||
};
|
||||
|
||||
var startButtonContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.05f), innerNewGame.RectTransform, Anchor.Center), isHorizontal: true, childAnchor: Anchor.BottomRight)
|
||||
{
|
||||
RelativeSpacing = 0.05f
|
||||
};
|
||||
campaignSetupUI.StartButton.RectTransform.Parent = startButtonContainer.RectTransform;
|
||||
campaignSetupUI.StartButton.RectTransform.MinSize = new Point(
|
||||
(int)(campaignSetupUI.StartButton.TextBlock.TextSize.X * 1.5f),
|
||||
campaignSetupUI.StartButton.RectTransform.MinSize.Y);
|
||||
startButtonContainer.RectTransform.MinSize = new Point(0, campaignSetupUI.StartButton.RectTransform.MinSize.Y);
|
||||
if (campaignSetupUI.CampaignCustomizeButton != null)
|
||||
{
|
||||
campaignSetupUI.CampaignCustomizeButton.RectTransform.Parent = startButtonContainer.RectTransform;
|
||||
}
|
||||
campaignSetupUI.InitialMoneyText.RectTransform.Parent = startButtonContainer.RectTransform;
|
||||
}
|
||||
|
||||
private void CreateHostServerFields()
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -41,21 +41,13 @@ namespace Barotrauma
|
||||
public Sprite(Texture2D texture, Rectangle? sourceRectangle, Vector2? newOffset, float newRotation = 0.0f, string path = null)
|
||||
{
|
||||
this.texture = texture;
|
||||
|
||||
sourceRect = sourceRectangle ?? new Rectangle(0, 0, texture.Width, texture.Height);
|
||||
|
||||
offset = newOffset ?? Vector2.Zero;
|
||||
|
||||
size = new Vector2(sourceRect.Width, sourceRect.Height);
|
||||
|
||||
origin = Vector2.Zero;
|
||||
|
||||
effects = SpriteEffects.None;
|
||||
|
||||
rotation = newRotation;
|
||||
|
||||
FilePath = path;
|
||||
|
||||
AddToList(this);
|
||||
}
|
||||
|
||||
@@ -85,7 +77,7 @@ namespace Barotrauma
|
||||
EnsureLazyLoaded(isAsync: true);
|
||||
}
|
||||
|
||||
public void EnsureLazyLoaded(bool isAsync=false)
|
||||
public void EnsureLazyLoaded(bool isAsync = false)
|
||||
{
|
||||
if (!LazyLoad || texture != null || cannotBeLoaded || loadingAsync) { return; }
|
||||
loadingAsync = isAsync;
|
||||
@@ -382,7 +374,7 @@ namespace Barotrauma
|
||||
{
|
||||
foreach (Sprite s in LoadedSprites)
|
||||
{
|
||||
if (s.FullPath == FullPath) return;
|
||||
if (s.FullPath == FullPath) { return; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user