Unstable 0.1500.5.0 (almost forgor edition 💀)

This commit is contained in:
Markus Isberg
2021-10-01 23:56:14 +09:00
parent 3043a9a7bc
commit 08bdfc6cea
150 changed files with 5669 additions and 4403 deletions
@@ -81,10 +81,10 @@ namespace Barotrauma
ConvertUnits.ToDisplayUnits(new Vector2(attachJoint.WorldAnchorB.X, -attachJoint.WorldAnchorB.Y)), GUI.Style.Green, 0, 4);
}
if (LatchOntoAI.WallAttachPos.HasValue)
if (LatchOntoAI.AttachPos.HasValue)
{
//GUI.DrawLine(spriteBatch, pos,
// ConvertUnits.ToDisplayUnits(new Vector2(LatchOntoAI.WallAttachPos.Value.X, -LatchOntoAI.WallAttachPos.Value.Y)), GUI.Style.Green, 0, 3);
GUI.DrawLine(spriteBatch, pos,
ConvertUnits.ToDisplayUnits(new Vector2(LatchOntoAI.AttachPos.Value.X, -LatchOntoAI.AttachPos.Value.Y)), GUI.Style.Green, 0, 3);
}
}
@@ -562,8 +562,10 @@ namespace Barotrauma
if (this is HumanoidAnimController humanoid)
{
Vector2 pos = ConvertUnits.ToDisplayUnits(humanoid.RightHandIKPos);
if (humanoid.character.Submarine != null) { pos += humanoid.character.Submarine.Position; }
GUI.DrawRectangle(spriteBatch, new Rectangle((int)pos.X, (int)-pos.Y, 4, 4), GUI.Style.Green, true);
pos = ConvertUnits.ToDisplayUnits(humanoid.LeftHandIKPos);
if (humanoid.character.Submarine != null) { pos += humanoid.character.Submarine.Position; }
GUI.DrawRectangle(spriteBatch, new Rectangle((int)pos.X, (int)-pos.Y, 4, 4), GUI.Style.Green, true);
}
@@ -100,7 +100,7 @@ namespace Barotrauma
}
}
private static bool shouldRecreateHudTexts = true;
public static bool ShouldRecreateHudTexts { get; set; } = true;
private static bool heldDownShiftWhenGotHudTexts;
public static bool IsCampaignInterfaceOpen =>
@@ -150,7 +150,7 @@ namespace Barotrauma
}
}
if (character.IsHumanoid && character.SelectedCharacter != null)
if (character.Params.CanInteract && character.SelectedCharacter != null)
{
character.SelectedCharacter.CharacterHealth.AddToGUIUpdateList();
}
@@ -195,7 +195,7 @@ namespace Barotrauma
}
}
if (character.IsHumanoid && character.SelectedCharacter != null && character.SelectedCharacter.Inventory != null)
if (character.Params.CanInteract && character.SelectedCharacter != null && character.SelectedCharacter.Inventory != null)
{
if (character.SelectedCharacter.CanInventoryBeAccessed)
{
@@ -219,7 +219,7 @@ namespace Barotrauma
if (focusedItemOverlayTimer <= 0.0f)
{
focusedItem = null;
shouldRecreateHudTexts = true;
ShouldRecreateHudTexts = true;
}
}
}
@@ -285,6 +285,21 @@ namespace Barotrauma
i.GetRootInventoryOwner() == i);
}
if (GameMain.GameSession != null)
{
foreach (var mission in GameMain.GameSession.Missions)
{
if (!mission.DisplayTargetHudIcons) { continue; }
foreach (var target in mission.HudIconTargets)
{
if (target.Submarine != character.Submarine) { continue; }
float alpha = GetDistanceBasedIconAlpha(target, maxDistance: mission.Prefab.HudIconMaxDistance);
if (alpha <= 0.0f) { continue; }
GUI.DrawIndicator(spriteBatch, target.DrawPosition, cam, 100.0f, mission.Prefab.HudIcon, mission.Prefab.HudIconColor * alpha);
}
}
}
foreach (Character.ObjectiveEntity objectiveEntity in character.ActiveObjectiveEntities)
{
DrawObjectiveIndicator(spriteBatch, cam, character, objectiveEntity, 1.0f);
@@ -317,7 +332,7 @@ namespace Barotrauma
if (focusedItem != character.FocusedItem)
{
focusedItemOverlayTimer = Math.Min(1.0f, focusedItemOverlayTimer);
shouldRecreateHudTexts = true;
ShouldRecreateHudTexts = true;
}
focusedItem = character.FocusedItem;
}
@@ -342,13 +357,13 @@ namespace Barotrauma
if (!GUI.DisableItemHighlights && !Inventory.DraggingItemToWorld)
{
bool shiftDown = PlayerInput.IsShiftDown();
if (shouldRecreateHudTexts || heldDownShiftWhenGotHudTexts != shiftDown)
if (ShouldRecreateHudTexts || heldDownShiftWhenGotHudTexts != shiftDown)
{
shouldRecreateHudTexts = true;
ShouldRecreateHudTexts = true;
heldDownShiftWhenGotHudTexts = shiftDown;
}
var hudTexts = focusedItem.GetHUDTexts(character, shouldRecreateHudTexts);
shouldRecreateHudTexts = false;
var hudTexts = focusedItem.GetHUDTexts(character, ShouldRecreateHudTexts);
ShouldRecreateHudTexts = false;
int dir = Math.Sign(focusedItem.WorldPosition.X - character.WorldPosition.X);
@@ -490,7 +505,7 @@ namespace Barotrauma
if (!character.IsIncapacitated && character.Stun <= 0.0f)
{
if (character.IsHumanoid && character.SelectedCharacter != null && character.SelectedCharacter.Inventory != null)
if (character.Params.CanInteract && character.SelectedCharacter != null && character.SelectedCharacter.Inventory != null)
{
if (character.SelectedCharacter.CanInventoryBeAccessed)
{
@@ -17,11 +17,15 @@ namespace Barotrauma
public bool LastControlled;
#warning TODO: Refactor
private Sprite disguisedPortrait;
private List<WearableSprite> disguisedAttachmentSprites;
private Vector2? disguisedSheetIndex;
private Sprite disguisedJobIcon;
private Color disguisedJobColor;
private Color disguisedHairColor;
private Color disguisedFacialHairColor;
private Color disguisedSkinColor;
private Sprite tintMask;
private float tintHighlightThreshold;
@@ -161,10 +165,10 @@ namespace Barotrauma
private void DrawInfoFrameCharacterIcon(SpriteBatch sb, Rectangle componentRect)
{
if (headSprite == null) { return; }
if (_headSprite == null) { return; }
Vector2 targetAreaSize = componentRect.Size.ToVector2();
float scale = Math.Min(targetAreaSize.X / headSprite.size.X, targetAreaSize.Y / headSprite.size.Y);
DrawIcon(sb, componentRect.Location.ToVector2() + headSprite.size / 2 * scale, targetAreaSize);
float scale = Math.Min(targetAreaSize.X / _headSprite.size.X, targetAreaSize.Y / _headSprite.size.Y);
DrawIcon(sb, componentRect.Location.ToVector2() + _headSprite.size / 2 * scale, targetAreaSize);
}
public GUIFrame CreateCharacterFrame(GUIComponent parent, string text, object userData)
@@ -227,193 +231,36 @@ namespace Barotrauma
{
if (idCard.Item.Tags == string.Empty) return;
if (idCard.StoredJobPrefab == null || idCard.StoredPortrait == null)
if (idCard.StoredOwnerAppearance.JobPrefab == null || idCard.StoredOwnerAppearance.Portrait == null)
{
string[] readTags = idCard.Item.Tags.Split(',');
if (readTags.Length == 0) return;
if (readTags.Length == 0) { return; }
if (idCard.StoredJobPrefab == null)
if (idCard.StoredOwnerAppearance.JobPrefab == null)
{
string jobIdTag = readTags.FirstOrDefault(s => s.StartsWith("jobid:"));
if (jobIdTag != null && jobIdTag.Length > 6)
{
string jobId = jobIdTag.Substring(6);
if (jobId != string.Empty)
{
idCard.StoredJobPrefab = JobPrefab.Get(jobId);
}
}
idCard.StoredOwnerAppearance.ExtractJobPrefab(readTags);
}
if (idCard.StoredPortrait == null)
if (idCard.StoredOwnerAppearance.Portrait == null)
{
string disguisedGender = string.Empty;
string disguisedRace = string.Empty;
string disguisedHeadSpriteId = string.Empty;
int disguisedHairIndex = -1;
int disguisedBeardIndex = -1;
int disguisedMoustacheIndex = -1;
int disguisedFaceAttachmentIndex = -1;
foreach (string tag in readTags)
{
string[] s = tag.Split(':');
switch (s[0])
{
case "gender":
disguisedGender = s[1];
break;
case "race":
disguisedRace = s[1];
break;
case "headspriteid":
disguisedHeadSpriteId = s[1];
break;
case "hairindex":
disguisedHairIndex = int.Parse(s[1]);
break;
case "beardindex":
disguisedBeardIndex = int.Parse(s[1]);
break;
case "moustacheindex":
disguisedMoustacheIndex = int.Parse(s[1]);
break;
case "faceattachmentindex":
disguisedFaceAttachmentIndex = int.Parse(s[1]);
break;
case "sheetindex":
string[] vectorValues = s[1].Split(";");
idCard.StoredSheetIndex = new Vector2(float.Parse(vectorValues[0]), float.Parse(vectorValues[1]));
break;
}
}
if (disguisedGender == string.Empty || disguisedRace == string.Empty || disguisedHeadSpriteId == string.Empty)
{
idCard.StoredPortrait = null;
idCard.StoredAttachments = null;
return;
}
foreach (XElement limbElement in Ragdoll.MainElement.Elements())
{
if (!limbElement.GetAttributeString("type", "").Equals("head", StringComparison.OrdinalIgnoreCase)) { continue; }
XElement spriteElement = limbElement.Element("sprite");
if (spriteElement == null) { continue; }
string spritePath = spriteElement.Attribute("texture").Value;
spritePath = spritePath.Replace("[GENDER]", disguisedGender);
spritePath = spritePath.Replace("[RACE]", disguisedRace.ToLowerInvariant());
spritePath = spritePath.Replace("[HEADID]", disguisedHeadSpriteId);
string fileName = Path.GetFileNameWithoutExtension(spritePath);
//go through the files in the directory to find a matching sprite
foreach (string file in Directory.GetFiles(Path.GetDirectoryName(spritePath)))
{
if (!file.EndsWith(".png", StringComparison.OrdinalIgnoreCase))
{
continue;
}
string fileWithoutTags = Path.GetFileNameWithoutExtension(file);
fileWithoutTags = fileWithoutTags.Split('[', ']').First();
if (fileWithoutTags != fileName) { continue; }
idCard.StoredPortrait = new Sprite(spriteElement, "", file) { RelativeOrigin = Vector2.Zero };
break;
}
break;
}
if (Wearables != null)
{
XElement disguisedHairElement, disguisedBeardElement, disguisedMoustacheElement, disguisedFaceAttachmentElement;
List<XElement> disguisedHairs, disguisedBeards, disguisedMoustaches, disguisedFaceAttachments;
Gender disguisedGenderEnum = disguisedGender == "female" ? Gender.Female : Gender.Male;
Race disguisedRaceEnum = (Race)Enum.Parse(typeof(Race), disguisedRace);
int headSpriteId = int.Parse(disguisedHeadSpriteId);
float commonness = disguisedGenderEnum == Gender.Female ? 0.05f : 0.2f;
disguisedHairs = AddEmpty(FilterByTypeAndHeadID(FilterElementsByGenderAndRace(wearables, disguisedGenderEnum, disguisedRaceEnum), WearableType.Hair, headSpriteId), WearableType.Hair, commonness);
disguisedBeards = AddEmpty(FilterByTypeAndHeadID(FilterElementsByGenderAndRace(wearables, disguisedGenderEnum, disguisedRaceEnum), WearableType.Beard, headSpriteId), WearableType.Beard);
disguisedMoustaches = AddEmpty(FilterByTypeAndHeadID(FilterElementsByGenderAndRace(wearables, disguisedGenderEnum, disguisedRaceEnum), WearableType.Moustache, headSpriteId), WearableType.Moustache);
disguisedFaceAttachments = AddEmpty(FilterByTypeAndHeadID(FilterElementsByGenderAndRace(wearables, disguisedGenderEnum, disguisedRaceEnum), WearableType.FaceAttachment, headSpriteId), WearableType.FaceAttachment);
if (IsValidIndex(disguisedHairIndex, disguisedHairs))
{
disguisedHairElement = disguisedHairs[disguisedHairIndex];
}
else
{
disguisedHairElement = GetRandomElement(disguisedHairs);
}
if (IsValidIndex(disguisedBeardIndex, disguisedBeards))
{
disguisedBeardElement = disguisedBeards[disguisedBeardIndex];
}
else
{
disguisedBeardElement = GetRandomElement(disguisedBeards);
}
if (IsValidIndex(disguisedMoustacheIndex, disguisedMoustaches))
{
disguisedMoustacheElement = disguisedMoustaches[disguisedMoustacheIndex];
}
else
{
disguisedMoustacheElement = GetRandomElement(disguisedMoustaches);
}
if (IsValidIndex(disguisedFaceAttachmentIndex, disguisedFaceAttachments))
{
disguisedFaceAttachmentElement = disguisedFaceAttachments[disguisedFaceAttachmentIndex];
}
else
{
disguisedFaceAttachmentElement = GetRandomElement(disguisedFaceAttachments);
}
idCard.StoredAttachments = new List<WearableSprite>();
disguisedFaceAttachmentElement?.Elements("sprite").ForEach(s => idCard.StoredAttachments.Add(new WearableSprite(s, WearableType.FaceAttachment)));
disguisedBeardElement?.Elements("sprite").ForEach(s => idCard.StoredAttachments.Add(new WearableSprite(s, WearableType.Beard)));
disguisedMoustacheElement?.Elements("sprite").ForEach(s => idCard.StoredAttachments.Add(new WearableSprite(s, WearableType.Moustache)));
disguisedHairElement?.Elements("sprite").ForEach(s => idCard.StoredAttachments.Add(new WearableSprite(s, WearableType.Hair)));
if (OmitJobInPortraitClothing)
{
JobPrefab.NoJobElement?.Element("PortraitClothing")?.Elements("sprite").ForEach(s => idCard.StoredAttachments.Add(new WearableSprite(s, WearableType.JobIndicator)));
}
else
{
idCard.StoredJobPrefab?.ClothingElement?.Elements("sprite").ForEach(s => idCard.StoredAttachments.Add(new WearableSprite(s, WearableType.JobIndicator)));
}
}
idCard.StoredOwnerAppearance.ExtractAppearance(this, readTags);
}
}
if (idCard.StoredJobPrefab != null)
if (idCard.StoredOwnerAppearance.JobPrefab != null)
{
disguisedJobIcon = idCard.StoredJobPrefab.Icon;
disguisedJobColor = idCard.StoredJobPrefab.UIColor;
disguisedJobIcon = idCard.StoredOwnerAppearance.JobPrefab.Icon;
disguisedJobColor = idCard.StoredOwnerAppearance.JobPrefab.UIColor;
}
disguisedPortrait = idCard.StoredPortrait;
disguisedSheetIndex = idCard.StoredSheetIndex;
disguisedAttachmentSprites = idCard.StoredAttachments;
disguisedPortrait = idCard.StoredOwnerAppearance.Portrait;
disguisedSheetIndex = idCard.StoredOwnerAppearance.SheetIndex;
disguisedAttachmentSprites = idCard.StoredOwnerAppearance.Attachments;
disguisedHairColor = idCard.StoredOwnerAppearance.HairColor;
disguisedFacialHairColor = idCard.StoredOwnerAppearance.FacialHairColor;
disguisedSkinColor = idCard.StoredOwnerAppearance.SkinColor;
}
partial void LoadAttachmentSprites(bool omitJob)
@@ -462,24 +309,35 @@ namespace Barotrauma
public void DrawPortrait(SpriteBatch spriteBatch, Vector2 screenPos, Vector2 offset, float targetWidth, bool flip = false, bool evaluateDisguise = false)
{
if (evaluateDisguise && IsDisguised) return;
if (evaluateDisguise && IsDisguised) { return; }
Vector2? sheetIndex;
Sprite portraitToDraw;
List<WearableSprite> attachmentsToDraw;
Color hairColor;
Color facialHairColor;
Color skinColor;
if (!IsDisguisedAsAnother || !evaluateDisguise)
{
sheetIndex = Head.SheetIndex;
portraitToDraw = Portrait;
attachmentsToDraw = AttachmentSprites;
hairColor = Head.HairColor;
facialHairColor = Head.FacialHairColor;
skinColor = Head.SkinColor;
}
else
{
//TODO: disguise skin and hair colors
sheetIndex = disguisedSheetIndex;
portraitToDraw = disguisedPortrait;
attachmentsToDraw = disguisedAttachmentSprites;
hairColor = disguisedHairColor;
facialHairColor = disguisedFacialHairColor;
skinColor = disguisedSkinColor;
}
if (portraitToDraw != null)
@@ -492,14 +350,14 @@ namespace Barotrauma
SetHeadEffect(spriteBatch);
portraitToDraw.SourceRect = new Rectangle(CalculateOffset(portraitToDraw, sheetIndex.Value.ToPoint()), portraitToDraw.SourceRect.Size);
}
portraitToDraw.Draw(spriteBatch, screenPos + offset, SkinColor, 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)
{
SetAttachmentEffect(spriteBatch, attachment);
DrawAttachmentSprite(spriteBatch, attachment, portraitToDraw, sheetIndex, screenPos + offset, scale, depthStep, GetAttachmentColor(attachment), flip ? SpriteEffects.FlipHorizontally : SpriteEffects.None);
DrawAttachmentSprite(spriteBatch, attachment, portraitToDraw, sheetIndex, screenPos + offset, scale, depthStep, GetAttachmentColor(attachment, hairColor, facialHairColor), flip ? SpriteEffects.FlipHorizontally : SpriteEffects.None);
depthStep += depthStep;
}
}
@@ -516,7 +374,7 @@ namespace Barotrauma
{
headEffectParameters.Effect ??= GameMain.GameScreen.ThresholdTintEffect;
headEffectParameters.Params ??= new Dictionary<string, object>();
headEffectParameters.Params["xBaseTexture"] = headSprite.Texture;
headEffectParameters.Params["xBaseTexture"] = HeadSprite.Texture;
headEffectParameters.Params["xTintMaskTexture"] = tintMask?.Texture ?? GUI.WhiteTexture;
headEffectParameters.Params["xCutoffTexture"] = GUI.WhiteTexture;
headEffectParameters.Params["baseToCutoffSizeRatio"] = 1.0f;
@@ -541,15 +399,15 @@ namespace Barotrauma
spriteBatch.SwapEffect(attachmentEffectParameters[attachment.Type]);
}
private Color GetAttachmentColor(WearableSprite attachment)
private Color GetAttachmentColor(WearableSprite attachment, Color hairColor, Color facialHairColor)
{
switch (attachment.Type)
{
case WearableType.Hair:
return HairColor;
return hairColor;
case WearableType.Beard:
case WearableType.Moustache:
return FacialHairColor;
return facialHairColor;
default:
return Color.White;
}
@@ -574,7 +432,7 @@ namespace Barotrauma
foreach (var attachment in AttachmentSprites)
{
SetAttachmentEffect(spriteBatch, attachment);
DrawAttachmentSprite(spriteBatch, attachment, headSprite, Head.SheetIndex, screenPos, scale, depthStep, GetAttachmentColor(attachment));
DrawAttachmentSprite(spriteBatch, attachment, headSprite, Head.SheetIndex, screenPos, scale, depthStep, GetAttachmentColor(attachment, HairColor, FacialHairColor));
depthStep += depthStep;
}
}
@@ -718,6 +576,7 @@ namespace Barotrauma
private readonly GUIComponent parentComponent;
private readonly List<Sprite> characterSprites = new List<Sprite>();
public GUIButton RandomizeButton;
public AppearanceCustomizationMenu(CharacterInfo info, GUIComponent parent, bool hasIcon = true)
{
@@ -737,13 +596,12 @@ namespace Barotrauma
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;
var listBox = new GUIListBox(
new RectTransform(new Vector2(contentWidth, 1.0f), parentComponent.RectTransform,
Anchor.CenterLeft))
{ CanBeFocused = false, CanTakeKeyBoardFocus = false };
var content = listBox.Content;
info.LoadHeadAttachments();
if (HasIcon)
{
@@ -754,7 +612,7 @@ namespace Barotrauma
RectTransform createItemRectTransform(string labelTag, float width = 0.6f)
{
var layoutGroup = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.2f), content.RectTransform));
var layoutGroup = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.166f), content.RectTransform));
var label = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), layoutGroup.RectTransform),
TextManager.Get(labelTag), font: GUI.SubHeadingFont);
@@ -793,6 +651,7 @@ namespace Barotrauma
info.FilterElementsByGenderAndRace(info.Wearables, info.Head.gender, info.Head.race),
wearableType, info.HeadSpriteId).Count();
List<GUIScrollBar> attachmentSliders = new List<GUIScrollBar>();
void createAttachmentSlider(int initialValue, WearableType wearableType)
{
int attachmentCount = countAttachmentsOfType(wearableType);
@@ -812,6 +671,7 @@ namespace Barotrauma
BarSize = 1.0f / (float)(attachmentCount + 1)
};
slider.BarScrollValue = initialValue;
attachmentSliders.Add(slider);
}
}
@@ -869,6 +729,36 @@ namespace Barotrauma
CanBeFocused = false
};
}
var childToSelect = dropdown.ListBox.Content.FindChild(c => (Color)c.UserData == getter());
dropdown.Select(dropdown.ListBox.Content.GetChildIndex(childToSelect));
//The following exists to track mouseover to preview colors before selecting them
bool previewingColor = false;
new GUICustomComponent(new RectTransform(Vector2.One, buttonFrame.RectTransform),
onUpdate: (deltaTime, component) =>
{
if (GUI.MouseOn is GUIFrame { Parent: { } p } hoveredFrame && dropdown.ListBox.Content.IsParentOf(hoveredFrame))
{
previewingColor = true;
Color color = (Color)(dropdown.ListBox.Content.FindChild(c =>
c == hoveredFrame || c.IsParentOf(hoveredFrame))?.UserData ?? dropdown.SelectedData);
setter(color);
buttonFrame.Color = getter();
buttonFrame.HoverColor = getter();
}
else if (previewingColor)
{
setter((Color)dropdown.SelectedData);
buttonFrame.Color = getter();
buttonFrame.HoverColor = getter();
previewingColor = false;
}
}, onDraw: null)
{
CanBeFocused = false,
Visible = true
};
}
if (countAttachmentsOfType(WearableType.Hair) > 0)
@@ -886,28 +776,54 @@ namespace Barotrauma
createColorSelector($"Customization.{nameof(info.SkinColor)}", info.SkinColors, () => info.SkinColor,
(color) => info.SkinColor = color);
RandomizeButton = new GUIButton(new RectTransform(Vector2.One * 0.12f,
parentComponent.RectTransform,
anchor: Anchor.BottomRight, scaleBasis: ScaleBasis.Smallest)
{ RelativeOffset = new Vector2(0.01f, 0.005f) }, style: "RandomizeButton")
{
OnClicked = (button, o) =>
{
var headPreset = info.Heads.Keys.GetRandom(Rand.RandSync.Unsynced);
info.Head.gender = headPreset.Gender;
info.Head.race = headPreset.Race;
info.Head.HeadSpriteId = headPreset.ID;
info.Head.HairIndex = Rand.Int(countAttachmentsOfType(WearableType.Hair), Rand.RandSync.Unsynced);
info.Head.BeardIndex = Rand.Int(countAttachmentsOfType(WearableType.Beard), Rand.RandSync.Unsynced);
info.Head.MoustacheIndex = Rand.Int(countAttachmentsOfType(WearableType.Moustache), Rand.RandSync.Unsynced);
info.Head.FaceAttachmentIndex = Rand.Int(countAttachmentsOfType(WearableType.FaceAttachment), Rand.RandSync.Unsynced);
info.Head.HairColor = info.HairColors.GetRandom(Rand.RandSync.Unsynced);
info.Head.FacialHairColor = info.FacialHairColors.GetRandom(Rand.RandSync.Unsynced);
info.Head.SkinColor = info.SkinColors.GetRandom(Rand.RandSync.Unsynced);
RecreateFrameContents();
info.RefreshHead();
OnHeadSwitch?.Invoke(this);
attachmentSliders.ForEach(s => OnSliderMoved?.Invoke(s, s.BarScroll));
return false;
}
};
//force update twice because the listbox is insanely janky
//TODO: fix all of the UI :)
listBox.ForceUpdate();
listBox.ForceUpdate();
foreach (var childLayoutGroup in listBox.Content.GetAllChildren<GUILayoutGroup>())
{
childLayoutGroup.Recalculate();
}
}
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(
HeadSelectionList ??= new GUIListBox(
new RectTransform(
new Point(parentComponent.Rect.Width,
(int)(parentComponent.Rect.Width * characterHeightWidthRatio * 0.6f)), GUI.Canvas)
@@ -915,6 +831,9 @@ namespace Barotrauma
AbsoluteOffset = new Point(parentComponent.Rect.Right - parentComponent.Rect.Width,
button.Rect.Bottom)
});
HeadSelectionList.Visible = true;
HeadSelectionList.Content.ClearChildren();
ClearSprites();
parentComponent.RectTransform.SizeChanged += () =>
{
@@ -952,15 +871,14 @@ namespace Barotrauma
{
row = null;
itemsInRow = 0;
foreach (var head in heads)
foreach (var kvp in heads.Where(kv => kv.Key.Gender == selectedGender))
{
var headPreset = head.Key;
Gender gender = headPreset.Gender;
var headPreset = kvp.Key;
Race race = headPreset.Race;
int headIndex = headPreset.ID;
string spritePath = spritePathWithTags
.Replace("[GENDER]", gender.ToString().ToLowerInvariant())
.Replace("[GENDER]", selectedGender.ToString().ToLowerInvariant())
.Replace("[RACE]", race.ToString().ToLowerInvariant());
if (!File.Exists(spritePath))
@@ -970,18 +888,18 @@ namespace Barotrauma
Sprite headSprite = new Sprite(headSpriteElement, "", spritePath);
headSprite.SourceRect =
new Rectangle(CharacterInfo.CalculateOffset(headSprite, head.Value.ToPoint()),
new Rectangle(CalculateOffset(headSprite, kvp.Value.ToPoint()),
headSprite.SourceRect.Size);
characterSprites.Add(headSprite);
if (itemsInRow >= 4 || row == null || gender != (Gender)row.UserData)
if (itemsInRow >= 4 || row == null)
{
row = new GUILayoutGroup(
new RectTransform(new Vector2(1.0f, 0.333f), HeadSelectionList.Content.RectTransform),
true)
{
UserData = gender,
Visible = gender == selectedGender
UserData = selectedGender,
Visible = true
};
itemsInRow = 0;
}
@@ -991,10 +909,10 @@ namespace Barotrauma
{
OutlineColor = Color.White * 0.5f,
PressedColor = Color.White * 0.5f,
UserData = new Tuple<Gender, Race, int>(gender, race, headIndex),
UserData = new Tuple<Gender, Race, int>(selectedGender, race, headIndex),
OnClicked = SwitchHead,
Selected = gender == info.Gender && race == info.Race && headIndex == info.HeadSpriteId,
Visible = gender == selectedGender
Selected = selectedGender == info.Gender && race == info.Race && headIndex == info.HeadSpriteId,
Visible = true
};
new GUIImage(new RectTransform(Vector2.One, btn.RectTransform), headSprite, scaleToFit: true);
@@ -1013,7 +931,7 @@ namespace Barotrauma
int id = ((Tuple<Gender, Race, int>)obj).Item3;
info.Gender = gender;
info.Race = race;
info.HeadSpriteId = id;
info.Head.HeadSpriteId = id;
RecreateFrameContents();
OnHeadSwitch?.Invoke(this);
return true;
@@ -66,8 +66,6 @@ namespace Barotrauma
private SpriteSheet medUIExtra;
private float medUIExtraAnimState;
private GUIComponent draggingMed;
private int highlightedLimbIndex = -1;
private int selectedLimbIndex = -1;
private LimbHealth currentDisplayedLimb;
@@ -118,7 +116,6 @@ namespace Barotrauma
if (prevOpenHealthWindow != null)
{
prevOpenHealthWindow.selectedLimbIndex = -1;
prevOpenHealthWindow.highlightedLimbIndex = -1;
}
@@ -207,7 +204,7 @@ namespace Barotrauma
new GUICustomComponent(new RectTransform(new Vector2(0.2f, 1.0f), nameContainer.RectTransform, Anchor.CenterLeft),
onDraw: (spriteBatch, component) =>
{
character.Info?.DrawPortrait(spriteBatch, new Vector2(component.Rect.X, component.Rect.Center.Y - component.Rect.Width / 2), Vector2.Zero, component.Rect.Width, false, openHealthWindow?.Character != Character.Controlled);
character.Info?.DrawPortrait(spriteBatch, new Vector2(component.Rect.X, component.Rect.Center.Y - component.Rect.Width / 2), Vector2.Zero, component.Rect.Width, false, character != Character.Controlled);
});
characterName = new GUITextBlock(new RectTransform(new Vector2(0.6f, 1.0f), nameContainer.RectTransform), "", textAlignment: Alignment.CenterLeft, font: GUI.SubHeadingFont)
{
@@ -216,7 +213,7 @@ namespace Barotrauma
new GUICustomComponent(new RectTransform(new Vector2(0.2f, 1.0f), nameContainer.RectTransform),
onDraw: (spriteBatch, component) =>
{
character.Info?.DrawJobIcon(spriteBatch, component.Rect, openHealthWindow?.Character != Character.Controlled);
character.Info?.DrawJobIcon(spriteBatch, component.Rect, character != Character.Controlled);
});
@@ -275,6 +272,34 @@ namespace Barotrauma
}
});
cprButton = new GUIButton(new RectTransform(new Vector2(0.17f, 0.17f), characterIndicatorArea.RectTransform, Anchor.BottomLeft, scaleBasis: ScaleBasis.Smallest), text: "", style: "CPRButton")
{
OnClicked = (button, userData) =>
{
Character selectedCharacter = Character.Controlled?.SelectedCharacter;
if (selectedCharacter == null || (!selectedCharacter.IsUnconscious && selectedCharacter.Stun <= 0.0f))
{
return false;
}
Character.Controlled.AnimController.Anim = (Character.Controlled.AnimController.Anim == AnimController.Animation.CPR) ?
AnimController.Animation.None : AnimController.Animation.CPR;
selectedCharacter.AnimController.ResetPullJoints();
if (GameMain.Client != null)
{
GameMain.Client.CreateEntityEvent(Character.Controlled, new object[] { NetEntityEvent.Type.Treatment });
}
return true;
},
ToolTip = TextManager.Get("doctor.cprobjective"),
IgnoreLayoutGroups = true,
Visible = false
};
var limbSelection = new GUICustomComponent(new RectTransform(new Vector2(0.4f, 1.0f), characterIndicatorArea.RectTransform),
(spriteBatch, component) =>
{
@@ -300,7 +325,7 @@ namespace Barotrauma
deadIndicator.AutoScaleHorizontal = true;
}
afflictionIconContainer = new GUIListBox(new RectTransform(new Vector2(0.25f, 0.7f), characterIndicatorArea.RectTransform), style: null);
afflictionIconContainer = new GUIListBox(new RectTransform(new Vector2(0.25f, 1.0f), characterIndicatorArea.RectTransform), style: null);
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.1f), healthWindowVerticalLayout.RectTransform),
TextManager.Get("SuitableTreatments"), font: GUI.SubHeadingFont, textAlignment: Alignment.BottomCenter);
@@ -324,33 +349,6 @@ namespace Barotrauma
characterIndicatorArea.Recalculate();
cprButton = new GUIButton(new RectTransform(new Vector2(afflictionIconContainer.RectTransform.RelativeSize.X, 0.3f), characterIndicatorArea.RectTransform, Anchor.BottomRight, scaleBasis: ScaleBasis.Smallest), text: "", style: "CPRButton")
{
OnClicked = (button, userData) =>
{
Character selectedCharacter = Character.Controlled?.SelectedCharacter;
if (selectedCharacter == null || (!selectedCharacter.IsUnconscious && selectedCharacter.Stun <= 0.0f))
{
return false;
}
Character.Controlled.AnimController.Anim = (Character.Controlled.AnimController.Anim == AnimController.Animation.CPR) ?
AnimController.Animation.None : AnimController.Animation.CPR;
selectedCharacter.AnimController.ResetPullJoints();
if (GameMain.Client != null)
{
GameMain.Client.CreateEntityEvent(Character.Controlled, new object[] { NetEntityEvent.Type.Treatment });
}
return true;
},
ToolTip = TextManager.Get("doctor.cprobjective"),
IgnoreLayoutGroups = true,
Visible = false
};
healthBarHolder = new GUIFrame(new RectTransform(Point.Zero, GUI.Canvas), style: null)
{
HoverCursor = CursorState.Hand
@@ -721,20 +719,19 @@ namespace Barotrauma
foreach (GUIComponent afflictionIcon in afflictionIconContainer.Content.Children)
{
if (!(afflictionIcon.UserData is Affliction affliction)) { continue; }
var btn = afflictionIcon.GetChild<GUIButton>();
if (affliction.AppliedAsFailedTreatmentTime > Timing.TotalTime - 1.0 && btn.FlashTimer <= 0.0f)
if (affliction.AppliedAsFailedTreatmentTime > Timing.TotalTime - 1.0 && afflictionIcon.FlashTimer <= 0.0f)
{
btn.Flash(GUI.Style.Red);
afflictionIcon.Flash(GUI.Style.Red);
}
else if (affliction.AppliedAsSuccessfulTreatmentTime > Timing.TotalTime - 1.0 && btn.FlashTimer <= 0.0f)
else if (affliction.AppliedAsSuccessfulTreatmentTime > Timing.TotalTime - 1.0 && afflictionIcon.FlashTimer <= 0.0f)
{
btn.Flash(GUI.Style.Green);
afflictionIcon.Flash(GUI.Style.Green);
}
}
if (GUI.MouseOn != null && GUI.MouseOn.UserData is string str && str == "selectaffliction")
if (GUI.MouseOn?.UserData is Affliction)
{
Affliction affliction = GUI.MouseOn.Parent.UserData as Affliction;
Affliction affliction = GUI.MouseOn?.UserData as Affliction;
if (afflictionTooltip == null || afflictionTooltip.UserData != affliction)
{
@@ -802,6 +799,8 @@ namespace Barotrauma
currentDisplayedLimb = selectedLimb;
}
UpdateAfflictionInfos(displayedAfflictions.Select(d => d.affliction));
foreach (GUIComponent component in recommendedTreatmentContainer.Content.Children)
{
var treatmentButton = component.GetChild<GUIButton>();
@@ -857,15 +856,6 @@ namespace Barotrauma
selectedLimbIndex = highlightedLimbIndex;
}
}
if (draggingMed != null)
{
if (!PlayerInput.PrimaryMouseButtonHeld())
{
OnItemDropped(draggingMed.UserData as Item, ignoreMousePos: false);
draggingMed = null;
}
}
}
else
{
@@ -1157,8 +1147,6 @@ namespace Barotrauma
{
CreateRecommendedTreatments();
}
UpdateAfflictionInfos(displayedAfflictions.Select(d => d.affliction));
}
private void CreateAfflictionInfos(IEnumerable<Affliction> afflictions)
@@ -1173,28 +1161,40 @@ namespace Barotrauma
{
displayedAfflictions.Add((affliction, affliction.Strength));
var child = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.3f), afflictionIconContainer.Content.RectTransform, Anchor.TopCenter))
var frame = new GUIButton(new RectTransform(new Vector2(1.0f, 0.25f), afflictionIconContainer.Content.RectTransform), style: "ListBoxElement")
{
Stretch = true,
UserData = affliction
};
var button = new GUIButton(new RectTransform(new Vector2(1.0f, 0.9f), child.RectTransform), style: null)
{
Color = Color.Gray.Multiply(0.1f).Opaque(),
HoverColor = Color.Gray.Multiply(0.4f).Opaque(),
SelectedColor = Color.Gray.Multiply(0.25f).Opaque(),
PressedColor = Color.Gray.Multiply(0.2f).Opaque(),
UserData = "selectaffliction",
UserData = affliction,
OnClicked = SelectAffliction
};
new GUIFrame(new RectTransform(Vector2.One, frame.RectTransform), style: "GUIFrameListBox") { CanBeFocused = false };
var content = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.85f), frame.RectTransform, Anchor.Center), childAnchor: Anchor.TopCenter)
{
Stretch = true,
CanBeFocused = false
};
var progressbarBg = new GUIProgressBar(new RectTransform(new Vector2(1.0f, 0.18f), content.RectTransform), 0.0f, GUI.Style.Green, style: "GUIAfflictionBar")
{
UserData = "afflictionstrengthprediction",
CanBeFocused = false
};
new GUIProgressBar(new RectTransform(Vector2.One, progressbarBg.RectTransform), 0.0f, Color.Transparent, showFrame: false, style: "GUIAfflictionBar")
{
UserData = "afflictionstrength",
CanBeFocused = false
};
//spacing
new GUIFrame(new RectTransform(new Vector2(1.0f, 0.15f), content.RectTransform), style: null) { CanBeFocused = false };
if (affliction == mostSevereAffliction)
{
buttonToSelect = button;
buttonToSelect = frame;
}
var afflictionIcon = new GUIImage(new RectTransform(Vector2.One * 0.8f, button.RectTransform, Anchor.Center), affliction.Prefab.Icon, scaleToFit: true)
var afflictionIcon = new GUIImage(new RectTransform(Vector2.One * 0.8f, content.RectTransform), affliction.Prefab.Icon, scaleToFit: true)
{
Color = GetAfflictionIconColor(affliction),
CanBeFocused = false
@@ -1203,32 +1203,22 @@ namespace Barotrauma
afflictionIcon.HoverColor = Color.Lerp(afflictionIcon.Color, Color.White, 0.6f);
afflictionIcon.SelectedColor = Color.Lerp(afflictionIcon.Color, Color.White, 0.5f);
float afflictionVitalityDecrease = affliction.GetVitalityDecrease(this);
Color afflictionEffectColor = Color.White;
if (afflictionVitalityDecrease > 0.0f)
var nameText = new GUITextBlock(new RectTransform(new Vector2(1.1f, 0.0f), content.RectTransform),
affliction.Prefab.Name, font: GUI.SmallFont, textAlignment: Alignment.BottomCenter)
{
afflictionEffectColor = GUI.Style.Red;
}
else if (afflictionVitalityDecrease < 0.0f)
{
afflictionEffectColor = GUI.Style.Green;
}
var nameText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), child.RectTransform),
affliction.Prefab.Name, font: GUI.SmallFont, textAlignment: Alignment.Center, style: "GUIToolTip");
CanBeFocused = false
};
nameText.Text = ToolBox.LimitString(nameText.Text, nameText.Font, nameText.Rect.Width);
nameText.RectTransform.MinSize = new Point(0, (int)(nameText.TextSize.Y * 1.25f));
new GUIProgressBar(new RectTransform(new Vector2(1.0f, 0.15f), child.RectTransform), 0.0f, afflictionEffectColor, style: "GUIAfflictionBar")
nameText.RectTransform.MinSize = new Point(0, (int)(nameText.TextSize.Y));
nameText.RectTransform.SizeChanged += () =>
{
UserData = "afflictionstrength"
nameText.Text = ToolBox.LimitString(nameText.Text, nameText.Font, nameText.Rect.Width);
};
child.Recalculate();
content.Recalculate();
}
buttonToSelect?.OnClicked(buttonToSelect, "selectaffliction");
buttonToSelect?.OnClicked(buttonToSelect, buttonToSelect.UserData);
afflictionIconContainer.RecalculateChildren();
}
@@ -1448,11 +1438,52 @@ namespace Barotrauma
private void UpdateAfflictionInfos(IEnumerable<Affliction> afflictions)
{
var potentialTreatment = Inventory.DraggingItems.FirstOrDefault();
if (potentialTreatment == null && GUI.MouseOn?.UserData is ItemPrefab itemPrefab)
{
potentialTreatment = Character.Controlled.Inventory.AllItems.FirstOrDefault(it => it.prefab == itemPrefab);
}
potentialTreatment ??= Inventory.SelectedSlot?.Item;
foreach (Affliction affliction in afflictions)
{
float afflictionVitalityDecrease = affliction.GetVitalityDecrease(this);
Color afflictionEffectColor = Color.White;
if (afflictionVitalityDecrease > 0.0f)
{
afflictionEffectColor = GUI.Style.Red;
}
else if (afflictionVitalityDecrease < 0.0f)
{
afflictionEffectColor = GUI.Style.Green;
}
var child = afflictionIconContainer.Content.FindChild(affliction);
var afflictionStrengthBar = child.GetChildByUserData("afflictionstrength") as GUIProgressBar;
var afflictionStrengthPredictionBar = child.GetChild<GUILayoutGroup>().GetChildByUserData("afflictionstrengthprediction") as GUIProgressBar;
afflictionStrengthPredictionBar.BarSize = 0.0f;
var afflictionStrengthBar = afflictionStrengthPredictionBar.GetChildByUserData("afflictionstrength") as GUIProgressBar;
afflictionStrengthBar.BarSize = affliction.Strength / affliction.Prefab.MaxStrength;
afflictionStrengthBar.Color = afflictionEffectColor;
float afflictionStrengthPrediction = GetAfflictionStrengthPrediction(potentialTreatment, affliction);
if (!MathUtils.NearlyEqual(afflictionStrengthPrediction, affliction.Strength))
{
float t = (float)Math.Max(0.5f, (Math.Sin(Timing.TotalTime * 5) + 1.0f) / 2.0f);
if (afflictionStrengthPrediction < affliction.Strength)
{
afflictionStrengthBar.Color = afflictionEffectColor;
afflictionStrengthPredictionBar.Color = GUI.Style.Blue * t;
afflictionStrengthPredictionBar.BarSize = afflictionStrengthBar.BarSize;
afflictionStrengthBar.BarSize = afflictionStrengthPrediction / affliction.Prefab.MaxStrength;
}
else
{
afflictionStrengthPredictionBar.Color = Color.Red * t;
afflictionStrengthPredictionBar.BarSize = afflictionStrengthPrediction / affliction.Prefab.MaxStrength;
}
}
if (afflictionTooltip != null && afflictionTooltip.UserData == affliction)
{
UpdateAfflictionInfo(afflictionTooltip.Content, affliction);
@@ -1460,6 +1491,32 @@ namespace Barotrauma
}
}
private float GetAfflictionStrengthPrediction(Item item, Affliction affliction)
{
float strength = affliction.Strength;
if (item == null) { return strength; }
foreach (ItemComponent ic in item.Components)
{
if (ic.statusEffectLists == null) { continue; }
if (!ic.statusEffectLists.TryGetValue(ActionType.OnUse, out List<StatusEffect> statusEffects)) { continue; }
foreach (StatusEffect effect in statusEffects)
{
foreach (var reduceAffliction in effect.ReduceAffliction)
{
if (reduceAffliction.affliction != affliction.Identifier && reduceAffliction.affliction != affliction.Prefab.AfflictionType) { continue; }
strength -= reduceAffliction.amount * (effect.Duration > 0 ? effect.Duration : 1.0f);
}
foreach (var addAffliction in effect.Afflictions)
{
if (addAffliction.Prefab != affliction.Prefab) { continue; }
strength += addAffliction.Strength * (effect.Duration > 0 ? effect.Duration : 1.0f);
}
}
}
return strength;
}
private void UpdateAfflictionInfo(GUIComponent parent, Affliction affliction)
{
var labelContainer = parent.GetChildByUserData("label");
@@ -1722,13 +1779,6 @@ namespace Barotrauma
Color.LightGray * 0.5f, width: 4);
}
}
if (draggingMed != null)
{
GUIImage itemImage = draggingMed.GetChild<GUIImage>();
float scale = Math.Min(40.0f / itemImage.Sprite.size.X, 40.0f / itemImage.Sprite.size.Y);
itemImage.Sprite.Draw(spriteBatch, PlayerInput.MousePosition, itemImage.Color, 0, scale);
}
}
private void DrawLimbAfflictionIcon(SpriteBatch spriteBatch, Affliction affliction, float iconScale, ref Vector2 iconPos)
@@ -679,6 +679,14 @@ namespace Barotrauma
{
clr = clr.Multiply(character.Info.SkinColor);
}
if (character.CharacterHealth.FaceTint.A > 0 && type == LimbType.Head)
{
clr = Color.Lerp(clr, character.CharacterHealth.FaceTint.Opaque(), character.CharacterHealth.FaceTint.A / 255.0f);
}
if (character.CharacterHealth.BodyTint.A > 0)
{
clr = Color.Lerp(clr, character.CharacterHealth.BodyTint.Opaque(), character.CharacterHealth.BodyTint.A / 255.0f);
}
}
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);
@@ -720,6 +728,7 @@ namespace Barotrauma
}
body.UpdateDrawPosition();
float depthStep = 0.000001f;
if (!hideLimb)
{
@@ -794,7 +803,7 @@ namespace Barotrauma
}
else
{
body.Draw(spriteBatch, conditionalSprite.Sprite, color, null, Scale * TextureScale, Params.MirrorHorizontally, Params.MirrorVertically);
body.Draw(spriteBatch, conditionalSprite.Sprite, color, depth: activeSprite.Depth - (depthStep * 50), Scale * TextureScale, Params.MirrorHorizontally, Params.MirrorVertically);
}
}
}
@@ -809,7 +818,7 @@ namespace Barotrauma
new Vector2(body.DrawPosition.X, -body.DrawPosition.Y),
color * Math.Min(damageOverlayStrength, 1.0f), activeSprite.Origin,
-body.DrawRotation,
Scale, spriteEffect, activeSprite.Depth - 0.0000015f);
Scale, spriteEffect, activeSprite.Depth - (depthStep * 90));
}
foreach (var decorativeSprite in DecorativeSprites)
{
@@ -827,9 +836,8 @@ namespace Barotrauma
Vector2 transformedOffset = new Vector2(ca * offset.X + sa * offset.Y, -sa * offset.X + ca * offset.Y);
decorativeSprite.Sprite.Draw(spriteBatch, new Vector2(body.DrawPosition.X + transformedOffset.X, -(body.DrawPosition.Y + transformedOffset.Y)), c,
-body.Rotation + rotation, decorativeSprite.GetScale(spriteAnimState[decorativeSprite].RandomScaleFactor) * Scale, spriteEffect,
depth: decorativeSprite.Sprite.Depth);
depth: activeSprite.Depth - (depthStep * 100));
}
float depthStep = 0.000001f;
float step = depthStep;
WearableSprite onlyDrawable = wearingItems.Find(w => w.HideOtherWearables);
if (Params.MirrorHorizontally)