Unstable 1.8.4.0
This commit is contained in:
@@ -7,6 +7,7 @@ using System.Linq;
|
||||
using Barotrauma.Extensions;
|
||||
using Barotrauma.Networking;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using Microsoft.Xna.Framework.Input;
|
||||
using static Barotrauma.TalentTree;
|
||||
using static Barotrauma.TalentTree.TalentStages;
|
||||
@@ -83,17 +84,21 @@ namespace Barotrauma
|
||||
private GUIButton? talentApplyButton,
|
||||
talentResetButton;
|
||||
|
||||
public void CreateGUI(GUIFrame parent, Character? targetCharacter)
|
||||
private delegate void StartAnimation(RectangleF start, RectangleF end, float duration);
|
||||
private StartAnimation? startAnimation;
|
||||
private GUIComponent? talentMainArea;
|
||||
|
||||
public void CreateGUI(GUIFrame parent, CharacterInfo? characterInfo)
|
||||
{
|
||||
this.characterInfo = characterInfo;
|
||||
character = characterInfo?.Character;
|
||||
|
||||
parent.ClearChildren();
|
||||
talentButtons.Clear();
|
||||
talentShowCaseButtons.Clear();
|
||||
talentCornerIcons.Clear();
|
||||
showCaseTalentFrames.Clear();
|
||||
|
||||
character = targetCharacter;
|
||||
characterInfo = targetCharacter?.Info;
|
||||
|
||||
GUIFrame background = new GUIFrame(new RectTransform(Vector2.One, parent.RectTransform, Anchor.TopCenter), style: "GUIFrameListBox");
|
||||
int padding = GUI.IntScale(15);
|
||||
GUIFrame frame = new GUIFrame(new RectTransform(new Point(background.Rect.Width - padding, background.Rect.Height - padding), parent.RectTransform, Anchor.Center), style: null);
|
||||
@@ -136,7 +141,7 @@ namespace Barotrauma
|
||||
GUILayoutGroup playerFrame = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.9f), containerFrame.RectTransform, Anchor.TopCenter));
|
||||
GameMain.NetLobbyScreen.CreatePlayerFrame(playerFrame, alwaysAllowEditing: true, createPendingText: false);
|
||||
|
||||
if (!GameMain.NetLobbyScreen.PermadeathMode)
|
||||
if (!GameMain.NetLobbyScreen.PermadeathMode && GameMain.GameSession?.GameMode is not PvPMode)
|
||||
{
|
||||
GUIButton newCharacterBox = new GUIButton(new RectTransform(new Vector2(0.5f, 0.2f), skillLayout.RectTransform, Anchor.BottomRight),
|
||||
text: GameMain.NetLobbyScreen.CampaignCharacterDiscarded ? TextManager.Get("settings") : TextManager.Get("createnew"), style: "GUIButtonSmall")
|
||||
@@ -294,7 +299,7 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
ImmutableHashSet<TalentPrefab?> talentsOutsideTree = info.GetUnlockedTalentsOutsideTree().Select(static e => TalentPrefab.TalentPrefabs.Find(c => c.Identifier == e)).ToImmutableHashSet();
|
||||
if (talentsOutsideTree.Any())
|
||||
if (talentsOutsideTree.Any(static t => t != null && !t.IsHiddenExtraTalent))
|
||||
{
|
||||
//spacing
|
||||
new GUIFrame(new RectTransform(new Vector2(1.0f, 0.01f), nameLayout.RectTransform), style: null);
|
||||
@@ -319,6 +324,7 @@ namespace Barotrauma
|
||||
foreach (var extraTalent in talentsOutsideTree)
|
||||
{
|
||||
if (extraTalent is null) { continue; }
|
||||
if (extraTalent.IsHiddenExtraTalent) { continue; }
|
||||
GUIImage talentImg = new GUIImage(new RectTransform(Vector2.One, extraTalentList.Content.RectTransform, scaleBasis: ScaleBasis.BothHeight), sprite: extraTalent.Icon, scaleToFit: true)
|
||||
{
|
||||
ToolTip = RichString.Rich($"‖color:{Color.White.ToStringHex()}‖{extraTalent.DisplayName}‖color:end‖" + "\n\n" + ToolBox.ExtendColorToPercentageSigns(extraTalent.Description.Value)),
|
||||
@@ -341,7 +347,15 @@ namespace Barotrauma
|
||||
|
||||
private void CreateTalentMenu(GUIComponent parent, CharacterInfo info, TalentTree tree)
|
||||
{
|
||||
GUIListBox mainList = new GUIListBox(new RectTransform(new Vector2(1f, 0.9f), parent.RectTransform, anchor: Anchor.TopCenter));
|
||||
talentMainArea = new GUIFrame(new RectTransform(new Vector2(1f, 0.9f), parent.RectTransform, Anchor.TopCenter), style: null );
|
||||
|
||||
GUIListBox mainList = new GUIListBox(new RectTransform(Vector2.One, talentMainArea.RectTransform));
|
||||
startAnimation = CreatePopupAnimationHandler(talentMainArea);
|
||||
|
||||
if (info is { TalentRefundPoints: > 0, ShowTalentResetPopupOnOpen: true })
|
||||
{
|
||||
CreateTalentResetPopup(talentMainArea);
|
||||
}
|
||||
|
||||
selectedTalents = info.GetUnlockedTalentsInTree().ToHashSet();
|
||||
|
||||
@@ -425,6 +439,130 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
private void CreateTalentResetPopup(GUIComponent parent)
|
||||
{
|
||||
int talentResetCount = 0;
|
||||
if (character?.Info != null)
|
||||
{
|
||||
talentResetCount = Math.Min(character.Info.TalentResetCount, character.Info.GetCurrentLevel());
|
||||
}
|
||||
bool hasResetTalentsBefore = talentResetCount > 0;
|
||||
var bgBlocker = new GUIFrame(new RectTransform(Vector2.One, parent.RectTransform, anchor: Anchor.Center), style: "GUIBackgroundBlocker")
|
||||
{
|
||||
IgnoreLayoutGroups = true
|
||||
};
|
||||
|
||||
var popup = new GUIFrame(new RectTransform(new Vector2(0.6f, 0.8f), bgBlocker.RectTransform, Anchor.Center));
|
||||
|
||||
var popupLayout = new GUILayoutGroup(new RectTransform(ToolBox.PaddingSizeParentRelative(popup.RectTransform, 0.95f), popup.RectTransform, Anchor.Center), isHorizontal: false);
|
||||
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.15f), popupLayout.RectTransform), TextManager.Get("talentresetheader"), font: GUIStyle.SubHeadingFont, textAlignment: Alignment.Center);
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, hasResetTalentsBefore ? 0.25f : 0.5f), popupLayout.RectTransform), TextManager.Get("talentresetprompt"), wrap: true);
|
||||
|
||||
if (hasResetTalentsBefore)
|
||||
{
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.25f), popupLayout.RectTransform),
|
||||
TextManager.GetWithVariable("talentresetpromptwarning", "[count]", talentResetCount.ToString()), wrap: true)
|
||||
{
|
||||
TextColor = GUIStyle.Red
|
||||
};
|
||||
}
|
||||
|
||||
var buttonLayout = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.35f), popupLayout.RectTransform), childAnchor: Anchor.CenterLeft, isHorizontal: true);
|
||||
|
||||
var confirmButton = new GUIButton(new RectTransform(new Vector2(0.5f, 1.0f), buttonLayout.RectTransform), TextManager.Get("holdtoconfirm"))
|
||||
{
|
||||
RequireHold = true,
|
||||
HoldDurationSeconds = 1.5f,
|
||||
OnClicked = (button, o) =>
|
||||
{
|
||||
if (character is null || characterInfo is null) { return false; }
|
||||
|
||||
characterInfo.RefundTalents();
|
||||
selectedTalents.Clear();
|
||||
UpdateTalentInfo();
|
||||
bgBlocker.Visible = false;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
var denyButton = new GUIButton(new RectTransform(new Vector2(0.5f, 1.0f), buttonLayout.RectTransform), TextManager.Get("decidelater"))
|
||||
{
|
||||
RequireHold = false,
|
||||
OnClicked = (button, userData) =>
|
||||
{
|
||||
if (talentResetButton is not { } resetButton) { return false; }
|
||||
startAnimation?.Invoke(popup.Rect, resetButton.Rect, 0.25f);
|
||||
resetButton.Flash(GUIStyle.Green);
|
||||
bgBlocker.Visible = false;
|
||||
if (characterInfo != null)
|
||||
{
|
||||
characterInfo.ShowTalentResetPopupOnOpen = false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static StartAnimation CreatePopupAnimationHandler(GUIComponent parent)
|
||||
{
|
||||
bool drawAnimation = false;
|
||||
|
||||
float animDur = 1f,
|
||||
animTimer = 0f;
|
||||
|
||||
RectangleF drawRect = RectangleF.Empty,
|
||||
animStartRect = RectangleF.Empty,
|
||||
animEndRect = RectangleF.Empty;
|
||||
|
||||
void StartAnimation(RectangleF start, RectangleF end, float duration)
|
||||
{
|
||||
animStartRect = start;
|
||||
animEndRect = end;
|
||||
animTimer = 0;
|
||||
animDur = duration;
|
||||
drawRect = start;
|
||||
drawAnimation = true;
|
||||
}
|
||||
|
||||
void OnDraw(SpriteBatch batch, GUICustomComponent component)
|
||||
{
|
||||
if (!drawAnimation) { return; }
|
||||
|
||||
GUIComponentStyle style = GUIStyle.GetComponentStyle("GUIFrame");
|
||||
|
||||
style.Sprites[GUIComponent.ComponentState.None][0].Draw(batch, drawRect, Color.White);
|
||||
}
|
||||
|
||||
void OnUpdate(float f, GUICustomComponent component)
|
||||
{
|
||||
if (!drawAnimation) { return; }
|
||||
|
||||
animTimer += f;
|
||||
if (animTimer > animDur)
|
||||
{
|
||||
drawRect = animEndRect;
|
||||
drawAnimation = false;
|
||||
return;
|
||||
}
|
||||
|
||||
float lerp = animTimer / animDur;
|
||||
|
||||
drawRect = new RectangleF(
|
||||
MathHelper.Lerp(animStartRect.X, animEndRect.X, lerp),
|
||||
MathHelper.Lerp(animStartRect.Y, animEndRect.Y, lerp),
|
||||
MathHelper.Lerp(animStartRect.Width, animEndRect.Width, lerp),
|
||||
MathHelper.Lerp(animStartRect.Height, animEndRect.Height, lerp));
|
||||
}
|
||||
|
||||
new GUICustomComponent(new RectTransform(Vector2.One, parent.RectTransform), onDraw: OnDraw, onUpdate: OnUpdate)
|
||||
{
|
||||
IgnoreLayoutGroups = true,
|
||||
CanBeFocused = false
|
||||
};
|
||||
|
||||
return StartAnimation;
|
||||
}
|
||||
|
||||
private void CreateTalentOption(GUIComponent parent, TalentSubTree subTree, int index, TalentOption talentOption, CharacterInfo info, int specializationCount)
|
||||
{
|
||||
int elementPadding = GUI.IntScale(8);
|
||||
@@ -679,6 +817,15 @@ namespace Barotrauma
|
||||
private bool ResetTalentSelection(GUIButton guiButton, object userData)
|
||||
{
|
||||
if (characterInfo is null) { return false; }
|
||||
|
||||
int newTalentCount = selectedTalents.Count - characterInfo.GetUnlockedTalentsInTree().Count();
|
||||
// if we don't have talents selected, and we have points to refund, show the refund popup
|
||||
if (characterInfo.TalentRefundPoints > 0 && newTalentCount == 0)
|
||||
{
|
||||
CreateTalentResetPopup(talentMainArea!);
|
||||
return true;
|
||||
}
|
||||
|
||||
selectedTalents = characterInfo.GetUnlockedTalentsInTree().ToHashSet();
|
||||
UpdateTalentInfo();
|
||||
return true;
|
||||
@@ -844,12 +991,31 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly LocalizedString refundText = TextManager.Get("refund"),
|
||||
resetText = TextManager.Get("reset");
|
||||
|
||||
public void Update()
|
||||
{
|
||||
if (characterInfo is null || talentResetButton is null || talentApplyButton is null) { return; }
|
||||
|
||||
int talentCount = selectedTalents.Count - characterInfo.GetUnlockedTalentsInTree().Count();
|
||||
talentResetButton.Enabled = talentApplyButton.Enabled = talentCount > 0;
|
||||
talentApplyButton.Enabled = character != null && talentCount > 0;
|
||||
talentResetButton.Enabled = character != null && (talentCount > 0 || characterInfo.TalentRefundPoints > 0);
|
||||
|
||||
if (talentCount == 0 && characterInfo.TalentRefundPoints > 0)
|
||||
{
|
||||
if (talentResetButton.FlashTimer <= 0.0f)
|
||||
{
|
||||
talentResetButton.Flash(GUIStyle.Orange);
|
||||
}
|
||||
|
||||
talentResetButton.Text = refundText;
|
||||
}
|
||||
else
|
||||
{
|
||||
talentResetButton.Text = resetText;
|
||||
}
|
||||
|
||||
if (talentApplyButton.Enabled && talentApplyButton.FlashTimer <= 0.0f)
|
||||
{
|
||||
talentApplyButton.Flash(GUIStyle.Orange);
|
||||
@@ -893,6 +1059,22 @@ namespace Barotrauma
|
||||
return info.GetIdentifierUsingOriginalName() == ownCharacterInfo.GetIdentifierUsingOriginalName();
|
||||
}
|
||||
|
||||
private static bool IsOnSameTeam(CharacterInfo? info)
|
||||
{
|
||||
if (info is null) { return false; }
|
||||
|
||||
CharacterTeamType? ownCharacterTeam = Character.Controlled?.TeamID ?? GameMain.Client?.MyClient?.TeamID;
|
||||
if (ownCharacterTeam is null) { return false; }
|
||||
|
||||
return info.TeamID == ownCharacterTeam;
|
||||
}
|
||||
|
||||
private static bool IsSpectatingInMultiplayer()
|
||||
{
|
||||
if (GameMain.Client?.MyClient is not { } myClient) { return false; }
|
||||
return myClient.Spectating;
|
||||
}
|
||||
|
||||
public static bool CanManageTalents(CharacterInfo targetInfo)
|
||||
{
|
||||
// in singleplayer we can do whatever we want
|
||||
@@ -901,10 +1083,16 @@ namespace Barotrauma
|
||||
// always allow managing talents for own character
|
||||
if (IsOwnCharacter(targetInfo)) { return true; }
|
||||
|
||||
// disallow managing talents while spectating
|
||||
if (IsSpectatingInMultiplayer()) { return false; }
|
||||
|
||||
// don't allow controlling non-bot characters
|
||||
if (targetInfo.Character is not { IsBot: true }) { return false; }
|
||||
|
||||
// lastly check if we have the permission to do this
|
||||
// only allow managing talents for bots on the same team
|
||||
if (!IsOnSameTeam(targetInfo)) { return false; }
|
||||
|
||||
// lastly, check if we have the permission to do this
|
||||
return GameMain.Client is { } client && client.HasPermission(ClientPermissions.ManageBotTalents);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user